<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ryan Trimble, UX/UI Developer</title><description>Frontend Developer, Design System Enthusiast, and Accessibility Advocate living in Central PA!</description><link>https://ryantrimble.com/</link><item><title>Things I Like</title><link>https://ryantrimble.com/blog/things-i-like/</link><guid isPermaLink="true">https://ryantrimble.com/blog/things-i-like/</guid><description>I like a lot about web development, even if its hard to remember sometimes.</description><pubDate>Tue, 16 Dec 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m feeling &lt;em&gt;pretty&lt;/em&gt; bad about web development (like, in general) lately. There is a lot happening that makes all of &lt;em&gt;this&lt;/em&gt; a whole lot less fun in my opinion. I&apos;ve drafted quite a few angry posts that haven&apos;t been finished and will never be published.&lt;/p&gt;
&lt;p&gt;Instead of stewing in that negative energy, I wanted to remind myself of what I do like about web development.&lt;/p&gt;
&lt;h2&gt;I Like Accessibility&lt;/h2&gt;
&lt;p&gt;My first web developer position was at a local college, where I learned a lot about accessibility. A majority of my time was spent checking out various components of the site, testing them, and learning how to make them more accessible. That experience made me understand the importance of accessibility in web development.&lt;/p&gt;
&lt;p&gt;Although it&apos;s generally a good idea to follow established patterns, there is a fun challenge in crafting user interfaces with accessibility in mind. Accessibility really makes you stop and consider all the different ways a user might interact with a design, and how best to prepare.&lt;/p&gt;
&lt;p&gt;This involves a lot:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Color contrast, typography, and readability&lt;/li&gt;
&lt;li&gt;Semantic HTML and information hierarchy&lt;/li&gt;
&lt;li&gt;Testing how screenreaders might interpret things&lt;/li&gt;
&lt;li&gt;Navigating sites without a mouse&lt;/li&gt;
&lt;li&gt;... so much more!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I truly believe there&apos;s a good balance to be found in providing fun user experiences, designed to be accessible, with results that benefit everyone.&lt;/p&gt;
&lt;p&gt;If it&apos;s designed well, but not accessible - it&apos;s not designed well.&lt;/p&gt;
&lt;h2&gt;I Like Animations&lt;/h2&gt;
&lt;p&gt;I&apos;m a fan of animation in many forms, unfortunately I don&apos;t have the skills to create cartoons. I &lt;em&gt;do&lt;/em&gt; have the skills to create web animations, at least.&lt;/p&gt;
&lt;p&gt;The animation capabilities of CSS and animation libraries such as GSAP (GreenSock Animation Platform) are super fun to explore. One of my favorite workshops I participated in was about &lt;a href=&quot;https://www.cassie.codes/speaking/getting-started-with-svg-animation/&quot;&gt;animating SVGs&lt;/a&gt;, with instructor &lt;a href=&quot;https://www.cassie.codes/&quot;&gt;Cassie Evans&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some animation may conflict with accessibility, but I feel like there is always room to add non-intrusive micro-animations on interactions to make them a tad more enjoyable. Animation may improve perceived performance of sites, as well as inform users while something happens in the background.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe
height=&quot;600&quot;
style=&quot;width: 100%;&quot;
scrolling=&quot;no&quot;
title=&quot;User Interaction Animation&quot;
src=&quot;https://codepen.io/mrtrimble/embed/preview/dyRZwVW?default-tab=&amp;amp;theme-id=default&quot;
frameborder=&quot;no&quot;
loading=&quot;lazy&quot;
allowtransparency=&quot;true&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/dyRZwVW&quot;&amp;gt;User Interaction Animation&amp;lt;/a&amp;gt; by Ryan Trimble (
&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;h2&gt;I Like Building Stuff&lt;/h2&gt;
&lt;p&gt;As much as I enjoy building complete websites or applications, I think I have more fun building tools and libraries that may be used in any type of project.&lt;/p&gt;
&lt;p&gt;At a previous position, I contributed to our company&apos;s &lt;a href=&quot;https://platformui.com/&quot;&gt;in-house design system&lt;/a&gt;, which was used in several of our projects. I built tools like &lt;a href=&quot;https://github.com/ritterim/skellyCSS&quot;&gt;skellyCSS&lt;/a&gt; (now &lt;a href=&quot;https://ryantrimble.com/blog/introducing-skelly-wc/&quot;&gt;skelly-wc&lt;/a&gt;), just a tiny library to quickly add skeleton screens into projects.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;really like&lt;/em&gt; building custom components. Like components that nail functionality and are reusable. Digging into the small details of a single component, providing the right functionality, making it accessible - it&apos;s where I thrive, I think.&lt;/p&gt;
&lt;p&gt;I feel I have a more difficult time working in third-party component libraries than I do creating components from scratch. This is most likely due to some personal standards that never feel met when perusing docs of an off-the-shelf component library. My problem, not theirs.&lt;/p&gt;
&lt;p&gt;Personally, I love the idea of using native web components to make reusable user interfaces, with zero dependencies and can be used everywhere.&lt;/p&gt;
&lt;p&gt;If I had to pick a reactive JavaScript framework to build components with, it would be &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;. Vue&apos;s single file component structure works well with my mental model for what a component needs: a template, script, and styling.&lt;/p&gt;
&lt;h2&gt;I Like Learning Stuff&lt;/h2&gt;
&lt;p&gt;I love learning new things and luckily, with web development, there is an &lt;strong&gt;endless amount&lt;/strong&gt; of &lt;em&gt;things&lt;/em&gt; to learn about.&lt;/p&gt;
&lt;p&gt;My favorite thing to do is just pick a topic and do a deep dive, try to figure out how it plays a part of the web. A lot of the time, I start a project to build and use whatever &lt;em&gt;thing&lt;/em&gt; that happens to be. I never really finish the project, but I do learn a lot about the &lt;em&gt;thing&lt;/em&gt;, which is the actual goal.&lt;/p&gt;
&lt;p&gt;Also, the web evolves fast: CSS becomes more powerful all the time, new tools for building static websites or new ways to render server-side. I love finding creative solutions to various types of problems, please keep sharing how you &quot;solved it&quot; on your blogs!&lt;/p&gt;
&lt;h2&gt;I Like Optimizing&lt;/h2&gt;
&lt;p&gt;I never really consider something &quot;finished&quot; and strive to make things &lt;em&gt;better&lt;/em&gt;. In a variety of ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faster website and web application performance&lt;/li&gt;
&lt;li&gt;Enhancing semantics for accessibility and search engines&lt;/li&gt;
&lt;li&gt;Updating styles towards more modern CSS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also like tinkering with tools to help with optimizing things! For example, &lt;a href=&quot;https://vite.dev/&quot;&gt;Vite&lt;/a&gt; is one of my favorite tools as it is crazy fast and has a great ecosystem for optimizing compiled code.&lt;/p&gt;
&lt;h2&gt;I Like Semantic Markup&lt;/h2&gt;
&lt;p&gt;There are over one hundred different HTML tags that are highly capable in structuring documents and templates.&lt;/p&gt;
&lt;p&gt;Semantic markup is helpful in lots of different ways, especially for accessibility. I&apos;d say the primary benefit is information hierarchy, helping users understand the flow of a document easily.&lt;/p&gt;
&lt;p&gt;If I find myself reaching for a generic &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;, I tend to revisit the code and see if there is possibly a more applicable HTML element to handle it.&lt;/p&gt;
&lt;h2&gt;I Like Styling&lt;/h2&gt;
&lt;p&gt;Of the many, many, many aspects of web development, CSS is my absolute favorite. CSS provides an infinite canvas to create anything and without a doubt is the best design tool available.&lt;/p&gt;
&lt;p&gt;Admittedly, I took a long time to fully understand how JavaScript works and would often find various ways to avoid it, instead reaching for CSS-only solutions. Back then, this was probably not the best approach, however nowadays CSS is so powerful I find it weird developers aren&apos;t using it more effectively.&lt;/p&gt;
&lt;p&gt;CSS really checks off all the boxes of &quot;things I like&quot; -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS helps with accessibility and semantics&lt;/li&gt;
&lt;li&gt;CSS provides enjoyable and memorable user experiences&lt;/li&gt;
&lt;li&gt;CSS has a lot to learn and is always improving&lt;/li&gt;
&lt;li&gt;CSS enables me to endlessly create&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I love getting to share my excitement for CSS here on my blog and over on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CSS has taken me places as well, I flew halfway across the world to attend &lt;a href=&quot;https://ryantrimble.com/blog/visiting-amsterdam-for-css-day/&quot;&gt;CSS Day in Amsterdam&lt;/a&gt;. Still one of the best trips; it didn&apos;t even feel like a conference, as everyone was also there because they also love CSS.&lt;/p&gt;
&lt;h2&gt;I Like the Web&lt;/h2&gt;
&lt;p&gt;As disappointing as &lt;em&gt;things&lt;/em&gt; have been lately, I still really enjoy working on the web.&lt;/p&gt;
&lt;p&gt;I find it fantastic that there is such a low barrier for entry to writing your first lines of code. There are so many resources available to help folks learn, build, and create on the web.&lt;/p&gt;
&lt;p&gt;Hopefully, as &quot;hype&quot; dies down about &lt;em&gt;certain technologies&lt;/em&gt;, I&apos;ll be able to return to a point where I&apos;m more excited about the web again.&lt;/p&gt;
</content:encoded></item><item><title>Taking things into my own hands, Part 2: Electric Boogaloo</title><link>https://ryantrimble.com/blog/taking-things-into-my-own-hands-part-2/</link><guid isPermaLink="true">https://ryantrimble.com/blog/taking-things-into-my-own-hands-part-2/</guid><description>Continuing the journey of detaching myself from big tech, one step at a time.</description><pubDate>Sat, 29 Nov 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last year &lt;a href=&quot;/blog/whats-cool-about-coolify/&quot;&gt;I checked out Coolify&lt;/a&gt;, which I determined to be a rad self-hosting solution, however I never actually committed to making the switch away from Netlify.&lt;/p&gt;
&lt;p&gt;There were a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Netlify makes things super easy&lt;/li&gt;
&lt;li&gt;Lack of confidence (on my part)&lt;/li&gt;
&lt;li&gt;Laziness (also on my part)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Earlier this year, I decided to take things into &lt;a href=&quot;/blog/taking-things-into-my-own-hands/&quot;&gt;my own hands&lt;/a&gt; a bit more, and I&apos;m happy to say I&apos;ve finally made the switch.&lt;/p&gt;
&lt;p&gt;That&apos;s right! The website you are looking at right now is hosted on a Coolify instance, running on a virtual private server (VPS) in Ashburn, VA.&lt;/p&gt;
&lt;p&gt;It&apos;s not &lt;em&gt;just&lt;/em&gt; Coolify I switched to; as described in my blog post discussing self-hosted applications, I&apos;m also self-hosting a &lt;a href=&quot;https://about.gitea.com/&quot;&gt;Gitea&lt;/a&gt; server on my network area storage (NAS) server. Now I manage my website&apos;s git repo on my own hardware and deploy my site to Coolify. This circumvents a need for GitHub, giving me a lot more control over my entire deployment pipeline.&lt;/p&gt;
&lt;h2&gt;What is Coolify, again?&lt;/h2&gt;
&lt;p&gt;In case you didn&apos;t read the original post, &lt;a href=&quot;https://coolify.io/&quot;&gt;Coolify&lt;/a&gt; is an open-source, self-hostable, &quot;Netlify-in-a-box&quot; type application. Developers are able to set up an instance and deploy all sorts of websites and applications.&lt;/p&gt;
&lt;p&gt;Coolify works a lot like Netlify, connecting to git repositories to easily deploy things. Coolify works with many different services, databases, and even backend APIs, which is rad.&lt;/p&gt;
&lt;h2&gt;VPS Hosting&lt;/h2&gt;
&lt;p&gt;To host the Coolify instance, I set up a virtual private server through &lt;a href=&quot;https://www.hetzner.com/&quot;&gt;Hetzner&lt;/a&gt;. As far as I can tell, Hetzner is a great choice for this, especially as they have a 1-click installer to configure Coolify.&lt;/p&gt;
&lt;p&gt;Also, the price isn&apos;t bad either at $9.99 per month, with $2 per month backups.&lt;/p&gt;
&lt;p&gt;I was a chump paying for Netlify&apos;s Pro plan, which was around $20 per month (on a legacy plan). Actually, I don&apos;t mind paying for services I use and I was a big fan of Netlify for a long time.&lt;/p&gt;
&lt;p&gt;Netlify is following the lead of AI companies and began charging based on &quot;token&quot; usage. I&apos;m not a fan of token-based &lt;em&gt;anything&lt;/em&gt; - it all feels a bit like a ploy to squeeze users for more money.&lt;/p&gt;
&lt;p&gt;Now things are a bit cheaper and I have even more functionality should I need it.&lt;/p&gt;
&lt;h2&gt;Cloudflare DNS&lt;/h2&gt;
&lt;p&gt;I&apos;m routing my site through &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt; now, as they have a couple of great features for handling domains:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Automatic SSL - this was something that Netlify provides and I don&apos;t like to manage certificates.&lt;/li&gt;
&lt;li&gt;AI prevention - Cloudflare has the capability to prevent AI bots from crawling and scraping my site&apos;s content.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I know Cloudflare had some uptime issues recently, but they are a powerhouse of the internet and are &lt;em&gt;generally reliable&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;How I&apos;m handling emails&lt;/h2&gt;
&lt;p&gt;One of the best things about Netlify is Netlify Forms. Probably the easiest way of processing forms I&apos;ve ever used, as all you really need to do is add a &lt;code&gt;netlify&lt;/code&gt; attribute to &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;
&lt;p&gt;I came across &lt;a href=&quot;https://resend.com/&quot;&gt;Resend&lt;/a&gt; as I was setting up notifications for my Coolify instance. Resend is an email-by-API tool that is only &lt;em&gt;slightly&lt;/em&gt; more work than adding an attribute, and determined it would work just as well for my contact form.&lt;/p&gt;
&lt;p&gt;Using Astro, I created an &lt;a href=&quot;https://docs.astro.build/en/guides/actions/&quot;&gt;Action&lt;/a&gt; to listen for form submit events to send submissions my way.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// example action

import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;
import { Resend } from &apos;resend&apos;;

export const server = {
  contact: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      email: z.string(),
      message: z.string(),
    }),
    handler: async function (input) {
      const resend = new Resend(import.meta.env.RESEND_API_KEY);

      const { data, error } = await resend.emails.send({
        from: `[Contact Form] ${input.name} &amp;lt;from@domain.com&amp;gt;`,
        to: [&apos;recipient@domain.com&apos;],
        subject: `Contact Submission`,
        html: `
          &amp;lt;h1&amp;gt;Contact Submission&amp;lt;/h1&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Name:&amp;lt;/strong&amp;gt; ${input.name}&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Email:&amp;lt;/strong&amp;gt; ${input.email}&amp;lt;/p&amp;gt;
          &amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Message:&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;
          &amp;lt;div&amp;gt;
            ${input.message}
          &amp;lt;/div&amp;gt;
        `,
      });

      // success/error handling

    }
  }),
  //... other actions...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Resend&apos;s free tier allows 3,000 emails per month, which is good enough for my needs. Honestly, I don&apos;t get a whole lot of form submissions, usually just spam.&lt;/p&gt;
&lt;p&gt;I thought about scrapping the contact form altogether, as it&apos;s not super useful, but I do like to provide it as an option.&lt;/p&gt;
&lt;h2&gt;What about Analytics?&lt;/h2&gt;
&lt;p&gt;I&apos;ve been using &lt;a href=&quot;https://plausible.io/&quot;&gt;Plausible&lt;/a&gt; analytics for a while now and I would still recommend it, especially as they have a self-hostable, &quot;community&quot; version. However, I decided to switch things up and found another open-source analytics tool called &lt;a href=&quot;https://umami.is/&quot;&gt;Umami&lt;/a&gt;, which I was able to deploy on my Coolify instance right alongside my website.&lt;/p&gt;
&lt;p&gt;Based on the few days I&apos;ve had it running, Umami seems easy-to-use and understand. I don&apos;t really do much in-depth assessment of my website&apos;s analytics, I mostly just like to see where my site is being linked from.&lt;/p&gt;
&lt;h2&gt;Anything else?&lt;/h2&gt;
&lt;p&gt;I fixed a bug that was preventing folks from signing my website&apos;s &lt;a href=&quot;/experiments/guestbook/&quot;&gt;guestbook&lt;/a&gt;, so now that should be working again - feel free to leave your mark and remember to be nice to me!&lt;/p&gt;
&lt;h2&gt;In Conclusion...&lt;/h2&gt;
&lt;p&gt;I know I&apos;m still a ways away from fully detaching myself from big tech entirely, but I&apos;m trying.&lt;/p&gt;
&lt;p&gt;I&apos;m not a fan of the current trends and priorities of companies I became dependent on. So, rather than sitting back and accepting all these force-fed features, I&apos;m slowly carving out my own slice of the Internet.&lt;/p&gt;
</content:encoded></item><item><title>Uploading Some Old Posts</title><link>https://ryantrimble.com/blog/reuploading-old-posts/</link><guid isPermaLink="true">https://ryantrimble.com/blog/reuploading-old-posts/</guid><description>A former employer closed down their development blog, so I&apos;ve uploaded my old posts here!</description><pubDate>Mon, 22 Sep 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just wanted to pop a quick note on here to say that my former employer shut down their development blog, which had some articles I wrote prior to launching my own personal blog.&lt;/p&gt;
&lt;p&gt;Here&apos;s the articles I wrote:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;/blog/animated-scroll-effects&quot;&gt;Animated Scroll Effects&lt;/a&gt; - published May 18th, 2022, I wrote about how to replicate an animation effect using GSAP!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/building-an-online-store-with-platform-ui-and-hugo&quot;&gt;Building an Online Store with Platform UI and Hugo&lt;/a&gt; - published June 16th, 2022, a how-to guide on building an online store using our CSS framework (Platform UI) and the static site generator Hugo.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/recreating-the-spotify-like-button&quot;&gt;Recreating the Spotify &quot;Like&quot; Button&lt;/a&gt; - published August 11th, 2022, a co-worker nerd-sniped me into rebuilding the Spotify Like button using CSS animations.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/rimdev-radio-building-with-astro&quot;&gt;RIMdev Radio: Building with Astro&lt;/a&gt; - published October 12th, 2022, wrote about one of my initial experiments with Astro and a dev-team playlist.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;/blog/automatically-import-components-in-astro-mdx&quot;&gt;Automatically Import Components in Astro MDX&lt;/a&gt; - published November 17th, 2023, explained how to set up automatically imported components for MDX files in Astro.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;ve also forked the entire blog, with all articles as originally posted, &lt;a href=&quot;https://github.com/mrtrimble/ritterim.github.io/tree/master/src/content/posts&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The articles are probably a bit out of date, but want to preserve things for sentimental value. I truly enjoyed my time at Ritter and miss my team a lot!&lt;/p&gt;
</content:encoded></item><item><title>My Strong Interests Profile</title><link>https://ryantrimble.com/blog/my-strong-interests-profile/</link><guid isPermaLink="true">https://ryantrimble.com/blog/my-strong-interests-profile/</guid><description>I recently completed the Strong Interest Inventory assessment, which helped me understand my interests and how they relate to potential career paths.</description><pubDate>Sun, 03 Aug 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Back in High School, I remember taking career assessment tests that were supposed to help us figure out what the hell we wanted to do with our lives. I don&apos;t recall ever appreciating the results, I wanted to do something cool like go to space or be a rock star, but these damn tests always said I&apos;d end up working with computers in some capacity.&lt;/p&gt;
&lt;p&gt;In hindsight, obviously the results were accurate, but I also don&apos;t think it was hard to predict that kids growing up in the &apos;90s would end up using computers in their day jobs later in life.&lt;/p&gt;
&lt;p&gt;Recently, I took the the &lt;a href=&quot;https://careerassessmentsite.com/tests/strong-tests/strong-interest-inventory-interpretive-report/&quot;&gt;Strong Interest Inventory Profile&lt;/a&gt;, available on &lt;a href=&quot;https://careerassessmentsite.com/&quot;&gt;Career Assessment Site&lt;/a&gt;, at the suggestion of my therapist. Mainly just to check in and see if my interests are really lining up with the types of things I&apos;m doing professionally.&lt;/p&gt;
&lt;p&gt;The assessment is about $65 and only takes about 45 minutes to complete. The test is not about skills or abilities, just interests, and the goal is to help guide you towards making decisions for jobs or furthering education.&lt;/p&gt;
&lt;h2&gt;The Results&lt;/h2&gt;
&lt;h3&gt;General Occupational Themes&lt;/h3&gt;
&lt;p&gt;According to the assessment, general occupational themes are six broad interest patterns used to describe a person&apos;s &quot;work personality.&quot;&lt;/p&gt;
&lt;p&gt;My top ranking occupational themes include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Artistic&lt;/li&gt;
&lt;li&gt;Conventional&lt;/li&gt;
&lt;li&gt;Social&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Artistic personality types find interest in self-expression, art appreciation, communication, and culture. Work activities may include composing music, performing, writing, or creating visual art. Potential skills include creativity, musical ability, artistic expression, and find value in beauty, originality, independence, and imagination.&lt;/p&gt;
&lt;p&gt;Conventional personality types enjoy organizaiton, data management, accounting, investing, and information systems. Work activities may include setting up procedures and systems, organizing and keeping records, and developing computer applications. Potential skills include ability to work with numbers, data analysis, finances, and attention to detail, and find value in accuracy, stability, and efficiency.&lt;/p&gt;
&lt;p&gt;Social personality types are interested in people, teamwork, helping, and community service. These folks work in fields of teaching, caring for people, counseling, or training other employees. People skills are important, verbal ability, listening, showing an understanding, and find value in cooperation, generosity, and service to others.&lt;/p&gt;
&lt;h3&gt;Basic Interest Scales&lt;/h3&gt;
&lt;p&gt;The assessment&apos;s &quot;basic interest scales&quot; specify the types of work activities or projects that are personally motivating and rewarding.&lt;/p&gt;
&lt;p&gt;My Top 5 Interest Areas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Research&lt;/li&gt;
&lt;li&gt;Programming &amp;amp; Information Systems&lt;/li&gt;
&lt;li&gt;Office Management&lt;/li&gt;
&lt;li&gt;Writing &amp;amp; Mass Communication&lt;/li&gt;
&lt;li&gt;Teaching &amp;amp; Education&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Selected Career Fields&lt;/h3&gt;
&lt;p&gt;Based on interests, the assessment provides some selected career fields as suggestions.&lt;/p&gt;
&lt;p&gt;The career fields suggested for me are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Graphic Artist&lt;/li&gt;
&lt;li&gt;Calligraphy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web site design&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Film and video production&lt;/li&gt;
&lt;li&gt;Cartooning&lt;/li&gt;
&lt;li&gt;Music librarian&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did not know calligraphy is a career.&lt;/p&gt;
&lt;h2&gt;Reflections&lt;/h2&gt;
&lt;p&gt;Lately, I&apos;m feeling that I&apos;m not headed in the right direction or like I haven&apos;t quite figured out where exactly I fit in, based on my personality, skills, and interests.&lt;/p&gt;
&lt;p&gt;I was drawn to the web as a medium and a platform as it&apos;s a super interesting intersection for art and technology, and those two interests present heavily in the results of my assessment. This may also explain why I&apos;m so interested in Design Systems.&lt;/p&gt;
&lt;p&gt;I don&apos;t generally care for tests that think they can pidgeon-hole me into some broad categorizations, but I mean this feels pretty accurate.&lt;/p&gt;
&lt;p&gt;I&apos;ve a tendency to blame myself for... well most things, this assessment helps me realize that the disconnect I feel may not actually be my own fault, which is relieving to understand.&lt;/p&gt;
</content:encoded></item><item><title>Troubleshooting my emotions</title><link>https://ryantrimble.com/blog/troubleshooting-my-emotions/</link><guid isPermaLink="true">https://ryantrimble.com/blog/troubleshooting-my-emotions/</guid><description>I&apos;ve been seeing a therapist for the past few weeks and plan to continue throughout the next year.</description><pubDate>Thu, 19 Jun 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Like many folks, I struggle with mental health issues: depression, anxiety, and ADHD. I&apos;ve been on an anti-depressant for some time, and while it seems to keep me going, I still can&apos;t help but feel I&apos;m not quite the person I &lt;em&gt;could&lt;/em&gt; be. I feel these issues prevent me from doing things I enjoy doing, making decisions, and advocating for myself and my beliefs.&lt;/p&gt;
&lt;p&gt;I&apos;m just beginning my mental health journey, but have already learned quite a bit about the way I think. My therapist has me journaling, trying to recognize cognitive distortions in my thought patterns. I&apos;m noticing how often I manage to point the finger at myself as the problem, whether justified or not.&lt;/p&gt;
&lt;p&gt;Another of my tasks was to create a list of ten things I honestly like about myself, which was daunting. I&apos;m not super confident, a frequent self-doubter with a penchant for self-deprecation, which ultimately leads to &lt;em&gt;not&lt;/em&gt; liking myself very much at all.&lt;/p&gt;
&lt;p&gt;Here&apos;s where I arrived:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am curious&lt;/li&gt;
&lt;li&gt;I am a problem-solver&lt;/li&gt;
&lt;li&gt;I am good with technology&lt;/li&gt;
&lt;li&gt;I am empathetic&lt;/li&gt;
&lt;li&gt;I am hard-working&lt;/li&gt;
&lt;li&gt;I am creative&lt;/li&gt;
&lt;li&gt;I am open-minded&lt;/li&gt;
&lt;li&gt;I am courteous&lt;/li&gt;
&lt;li&gt;I am inventive&lt;/li&gt;
&lt;li&gt;My pets like me&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This list became my &quot;positive self-talk script,&quot; which I&apos;m reading to myself daily. The idea behind a positive self-talk script is to replace negative thoughts with positive ones, reading daily in order to help retain and reinforce that positivity towards yourself.&lt;/p&gt;
&lt;p&gt;It&apos;s all rather awkward and uncomfortable for me, but like, &lt;em&gt;in a good way&lt;/em&gt;. I&apos;m finally taking care of myself, and I hope you are doing the same.&lt;/p&gt;
</content:encoded></item><item><title>Taking things into my own hands</title><link>https://ryantrimble.com/blog/taking-things-into-my-own-hands/</link><guid isPermaLink="true">https://ryantrimble.com/blog/taking-things-into-my-own-hands/</guid><description>Learning how to build my own Internet, by self-hosting all the applications.</description><pubDate>Sun, 18 May 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Earlier this year, I purchased myself a new toy: a network area storage device (NAS), the &lt;a href=&quot;https://www.bhphotovideo.com/c/product/1757288-REG/synology_diskstation_ds423_4_bay_nas.html&quot;&gt;Synology DiskStation DS423+&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main purpose of a NAS is as a storage hub for your network, where you&apos;re able to easily share and collaborate on files between devices on your network. The fun part of an always-connected device with tons of storage is self-hosting &lt;em&gt;all-the-things&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;System Information&lt;/h2&gt;
&lt;p&gt;Here are the specs of my NAS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make: Synology&lt;/li&gt;
&lt;li&gt;Model: &lt;a href=&quot;https://www.bhphotovideo.com/c/product/1757288-REG/synology_diskstation_ds423_4_bay_nas.html&quot;&gt;DiskStation DS423+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bays: 4x HDD, 2x NVMe&lt;/li&gt;
&lt;li&gt;CPU: 2.0 GHz Intel Celeron J4125 Quad-Core&lt;/li&gt;
&lt;li&gt;Drives:
&lt;ul&gt;
&lt;li&gt;4x &lt;a href=&quot;https://www.bhphotovideo.com/c/product/1666829-REG/seagate_st8000vn004_8tb_ironwolf_7200_rpm.html&quot;&gt;SeaGate IronWolf&lt;/a&gt; - 8TB&lt;/li&gt;
&lt;li&gt;2x &lt;a href=&quot;https://www.bhphotovideo.com/c/product/1684095-REG/synology_snv3410_400g_400gb_snv3410_nvme_m_2.html&quot;&gt;Synology NVMe M.2 2280&lt;/a&gt; - 400GB&lt;/li&gt;
&lt;li&gt;RAID5&lt;/li&gt;
&lt;li&gt;Total Capacity: 24TB&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RAM:
&lt;ul&gt;
&lt;li&gt;2GB (onboard)&lt;/li&gt;
&lt;li&gt;16GB &lt;a href=&quot;https://www.amazon.com/dp/B07H4XNNXK&quot;&gt;Timetec 16GB DDR4 2666MHz PC4-21300&lt;/a&gt; (installed)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Remote Access&lt;/h2&gt;
&lt;p&gt;I&apos;ve enabled remote access to my NAS, and many of these applications, through the use of dynamic DNS and reverse-proxy addresses.&lt;/p&gt;
&lt;p&gt;Synology includes a dynamic DNS (DDNS) service within the operating system of the DiskStation. If you aren&apos;t familiar with DDNS, it&apos;s a service that assigns a human-readable domain name to a dynamically updated IP address. The service runs on the device and informs an outside DNS provider of the current external IP address of the device.&lt;/p&gt;
&lt;p&gt;I purchased a personal domain name for my NAS and set it up to use Cloudflare nameservers. Cloudflare makes it easy to manage DNS records. Here, I can create a &lt;code&gt;CNAME&lt;/code&gt; records for any subdomain I want and point it towards the DDNS address of the NAS. Then I can add reverse proxy rules pointing the subdomains to different services running on the NAS side.&lt;/p&gt;
&lt;p&gt;Now, I&apos;m able to access any applications I need from outside my network!&lt;/p&gt;
&lt;h2&gt;Applications&lt;/h2&gt;
&lt;p&gt;I&apos;ve been having a lot of fun checking out all the self-hostable open-source projects out there. I have &lt;em&gt;lots&lt;/em&gt; of plans for my NAS, but here&apos;s a list of the applications and services I&apos;ve figured out how to get running so far:&lt;/p&gt;
&lt;h3&gt;ConvertX&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/C4illin/ConvertX&quot;&gt;ConvertX&lt;/a&gt; is a handy tool that allows for converting files of all different kinds into many other formats.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  convertx:
    image: ghcr.io/c4illin/convertx:latest
    container_name: Convertx
    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;nc -z 127.0.0.1 3000 || exit 1&apos;]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    ports:
      - 3522:3000
    environment:
      JWT_SECRET: ${CONVERTX_JWT_SECRET}
      ACCOUNT_REGISTRATION: false #Set To false To Disallow User Registration.
      HTTP_ALLOWED: true #Allow HTTP Connections, Only Set This To true Locally.
      ALLOW_UNAUTHENTICATED: false #Allow Unauthenticated Users To Use The Service, Only Set This To true Locally.
    volumes:
      - /volume1/docker/convertx:/app/data:rw
    restart: on-failure:5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Gitea&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://about.gitea.com/&quot;&gt;Gitea&lt;/a&gt; is an open-source code versioning platform, alternative to GitHub. Feature parity is very similar to what GitHub offers, too - including repository management, issue and project tracking, organizations, and much more.&lt;/p&gt;
&lt;p&gt;Here&apos;s the dockerfile I used to set up Gitea on my NAS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  db:
    image: postgres:17
    container_name: Gitea-DB
    hostname: gitea-db
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: [&apos;CMD&apos;, &apos;pg_isready&apos;, &apos;-q&apos;, &apos;-d&apos;, &apos;gitea&apos;, &apos;-U&apos;, &apos;giteauser&apos;]
      timeout: 45s
      interval: 10s
      retries: 10
    volumes:
      - /volume1/docker/gitea/db:/var/lib/postgresql/data:rw
    environment:
      - POSTGRES_DB=gitea
      - POSTGRES_USER=${GITEA_DB_USER}
      - POSTGRES_PASSWORD=${GITEA_DB_PASS}
    restart: on-failure:5

  web:
    image: gitea/gitea:latest
    container_name: Gitea
    hostname: gitea
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1
    ports:
      - 3052:3000
      - 2222:22
    volumes:
      - /volume1/docker/gitea/data:/data
      - /etc/TZ:/etc/TZ:ro
      - /etc/localtime:/etc/localtime:ro
    environment:
      - USER_UID=${PUID}
      - USER_GID=${PGID}
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=gitea-db:5432
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=${GITEA_DB_USER}
      - GITEA__database__PASSWD=${GITEA_DB_PASS}
      - ROOT_URL=${GITEA_ROOT_URL}
    restart: on-failure:5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Home Assistant&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.home-assistant.io/&quot;&gt;Home Assistant&lt;/a&gt; consolidates home automation services and &quot;Internet-of-Things&quot; (IoT) devices under one roof, replacing Google Home. Control lights, thermostats, robot vaccuums, and whatever else, as it integrates with thousands of devices. You can even replace voice assistants like Google Assistant or Siri!&lt;/p&gt;
&lt;p&gt;Here is my Dockerfile for Home Assistant:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  homeassistant:
    image: homeassistant/home-assistant
    container_name: Home-Assistant
    mem_limit: 8g
    cpu_shares: 768
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: curl -f http://localhost:8123/ || exit 1
    restart: on-failure:5
    network_mode: host
    volumes:
      - /volume1/docker/homeassistant:/config:rw
    environment:
      TZ: ${TZ}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Immich&lt;/h3&gt;
&lt;p&gt;Immich is an open-source photo management application that provides a comparable experience to Google Photos, one of my favorite apps by Google.&lt;/p&gt;
&lt;p&gt;Here&apos;s the dockerfile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  immich-redis:
    image: redis
    container_name: Immich-REDIS
    hostname: immich-redis
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;redis-cli ping || exit 1&apos;]
    user: ${PUID}:${PGID}
    environment:
      - TZ=${TZ}
    volumes:
      - /volume1/docker/immich/redis:/data:rw
      - /volume1/Photos/:/photos:rw
    restart: on-failure:5

  immich-db:
    image: ghcr.io/immich-app/postgres:16-vectorchord0.3.0-pgvectors0.2.0
    container_name: Immich-DB
    hostname: immich-db
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: [&apos;CMD&apos;, &apos;pg_isready&apos;, &apos;-q&apos;, &apos;-d&apos;, &apos;immich&apos;, &apos;-U&apos;, &apos;immichuser&apos;]
      interval: 10s
      timeout: 5s
      retries: 5
    volumes:
      - /volume1/docker/immich/db:/var/lib/postgresql/data:rw
      - /volume1/Photos/:/photos:rw
    environment:
      - TZ=${TZ}
      - POSTGRES_DB=${IMMICH_DB_NAME}
      - POSTGRES_USER=${IMMICH_DB_USER}
      - POSTGRES_PASSWORD=${IMMICH_DB_PASSWORD}
      - DB_STORAGE_TYPE=${IMMICH_DB_STORAGE_TYPE}
    restart: on-failure:5

  immich-server:
    image: ghcr.io/immich-app/immich-server:release
    container_name: Immich-SERVER
    hostname: immich-server
    user: ${PUID}:${PGID}
    security_opt:
      - no-new-privileges:true
    env_file:
      - stack.env
    ports:
      - 8212:2283
    volumes:
      - /volume1/docker/immich/upload:/usr/src/app/upload:rw
      - /volume1/Photos/:/photos:rw
    restart: on-failure:5
    depends_on:
      immich-redis:
        condition: service_healthy
      immich-db:
        condition: service_started

  immich-machine-learning:
    image: ghcr.io/immich-app/immich-machine-learning:release
    container_name: Immich-LEARNING
    hostname: immich-machine-learning
    user: ${PUID}:${PGID}
    security_opt:
      - no-new-privileges:true
    env_file:
      - stack.env
    volumes:
      - /volume1/docker/immich/upload:/usr/src/app/upload:rw
      - /volume1/docker/immich/cache:/cache:rw
      - /volume1/docker/immich/matplotlib:/matplotlib:rw
      - /volume1/Photos/:/photos:rw
    environment:
      - MPLCONFIGDIR=/matplotlib
    restart: on-failure:5
    depends_on:
      immich-db:
        condition: service_started
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Paperless-NGX&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.paperless-ngx.com/&quot;&gt;Paperless-NGX&lt;/a&gt; is &lt;em&gt;rad&lt;/em&gt; if you are an organization nerd, like me. This is document organization cranked up to 11. You can organize your files in all kinds of ways, programmatically, with tags, types, correspondents, and many other factors.&lt;/p&gt;
&lt;p&gt;Here&apos;s how I set it up:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  broker:
    image: redis
    container_name: Paperless-NGX-REDIS
    restart: always
    volumes:
      - /volume1/docker/paperlessngx/redis:/data

  db:
    image: postgres:16
    container_name: Paperless-NGX-DB
    restart: always
    volumes:
      - /volume1/docker/paperlessngx/db:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${PAPERLESS_DB_NAME}
      POSTGRES_USER: ${PAPERLESS_DB_USER}
      POSTGRES_PASSWORD: ${PAPERLESS_DB_PASS}

  webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    container_name: Paperless-NGX
    restart: always
    depends_on:
      - db
      - broker
    ports:
      - 8777:8000
    volumes:
      - /volume1/docker/paperlessngx/data:/usr/src/paperless/data
      - /volume1/docker/paperlessngx/media:/usr/src/paperless/media
      - /volume1/docker/paperlessngx/export:/usr/src/paperless/export
      - /volume1/docker/paperlessngx/consume:/usr/src/paperless/consume
    environment:
      PAPERLESS_REDIS: redis://broker:6379
      PAPERLESS_DBHOST: db
      USERMAP_UID: ${PUID}
      USERMAP_GID: ${PGID}
      PAPERLESS_TIME_ZONE: ${TZ}
      PAPERLESS_URL: ${PAPERLESS_URL}
      PAPERLESS_CSRF_TRUSTED_ORIGINS: ${PAPERLESS_URL}
      PAPERLESS_ADMIN_USER: ${PAPERLESS_ADMIN_USER}
      PAPERLESS_ADMIN_PASSWORD: ${PAPERLESS_ADMIN_PASS}
      PAPERLESS_OCR_LANGUAGE: ${PAPERLESS_OCR_LANGUAGE}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Pi-hole&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://pi-hole.net/&quot;&gt;Pi-hole&lt;/a&gt; is a whole-network advertisement blocker. This thing works as a network DNS server with a hefty blocklist for advertisements. I&apos;ve found something like two-thirds of DNS requests turn out to be ad requests, so this can save you some bandwidth by blocking annoying shit.&lt;/p&gt;
&lt;p&gt;Here&apos;s how to set it up:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  pihole:
    image: pihole/pihole
    container_name: Pi-Hole
    network_mode: host
    security_opt:
      - no-new-privileges:false
    restart: on-failure:5
    volumes:
      - /volume1/docker/pihole/dnsmasq.d:/etc/dnsmasq.d:rw
      - /volume1/docker/pihole/pihole:/etc/pihole:rw
    environment:
      FTLCONF_webserver_api_password: ${PIHOLE_PASS}
      FTLCONF_webserver_port: 8080
      FTLCONF_dns_listeningMode: all
      TZ: ${TZ}
      DNSMASQ_USER: pihole #or root NOT recommended to use root.
      PIHOLE_UID: ${PUID}
      PIHOLE_GID: ${PGID}
    cap_add:
      - SYS_TIME
      - SYS_NICE
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Plausible&lt;/h3&gt;
&lt;p&gt;I&apos;ve been using the cloud version of &lt;a href=&quot;https://plausible.io/&quot;&gt;Plausible&lt;/a&gt; for website analytics for a while, however Plausible also provides a community edition that is self-hostable.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  db:
    image: postgres:17-alpine
    container_name: Plausible-DB
    hostname: plausible_db
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/plausible/db:/var/lib/postgresql/data:rw
    environment:
      - POSTGRES_DB=plausible_db
      - POSTGRES_PASSWORD=postgres
    restart: on-failure:5

  events-db:
    image: clickhouse/clickhouse-server:24.12-alpine
    ulimits:
      nofile:
        soft: 262144
        hard: 262144
    container_name: Plausible-EVENTS-DB
    hostname: plausible_events_db
    security_opt:
      - no-new-privileges:true
    user: ${PUID}:${PGID}
    environment:
      CLICKHOUSE_SKIP_USER_SETUP: 1
    volumes:
      - /volume1/docker/plausible/data:/var/lib/clickhouse:rw
      - /volume1/docker/plausible/logs:/var/log/clickhouse-server:rw
    restart: on-failure:5

  plausible:
    image: ghcr.io/plausible/community-edition:latest
    command: sh -c &quot;sleep 10 &amp;amp;&amp;amp; /entrypoint.sh db createdb &amp;amp;&amp;amp; /entrypoint.sh db migrate &amp;amp;&amp;amp; /entrypoint.sh run&quot;
    container_name: Plausible
    hostname: plausible
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://localhost:8000/ || exit 1
    ports:
      - 9850:8000
    environment:
      DISABLE_REGISTRATION: false # Type in true Instead of false to Disable Registration After Your Initial Registration.
      BASE_URL: ${PLAUSIBLE_BASE_URL}
      SECRET_KEY_BASE: ${PLAUSIBLE_SECRET_KEY_BASE}
      TOTP_VAULT_KEY: ${PLAUSIBLE_TOTP_VAULT_KEY}
      # MAILER_EMAIL: site@example.com
      SMTP_HOST_ADDR: ${SMTP_HOST}
      SMTP_HOST_PORT: ${SMTP_PORT}
      SMTP_USER_NAME: ${SMTP_USER_ADDRESS}
      SMTP_USER_PWD: ${SMTP_PASSWORD}
      MAILER_ADAPTER: Bamboo.Mua
    restart: on-failure:5
    depends_on:
      - db
      - events-db
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Penpot&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://penpot.app/&quot;&gt;Penpot&lt;/a&gt; is an open-source, self-hostable alternative to Figma. As I&apos;m using it, I&apos;m noticing Penpot seems to be more in-line with how CSS works than it&apos;s major competitor. For example, Penpot has a grid system that matches grid&apos;s use in CSS.&lt;/p&gt;
&lt;p&gt;I followed the guide provided by Penpot and got it working with this Dockerfile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;x-flags: &amp;amp;penpot-flags
  PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies

x-uri: &amp;amp;penpot-public-uri
  PENPOT_PUBLIC_URI: http://localhost:9001

x-body-size: &amp;amp;penpot-http-body-size
  PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 31457280
  PENPOT_HTTP_SERVER_MAX_MULTIPART_BODY_SIZE: 367001600

networks:
  penpot:

volumes:
  penpot_postgres_v15:
  penpot_assets:

services:
  penpot-frontend:
    image: &apos;penpotapp/frontend:${PENPOT_VERSION:-latest}&apos;
    restart: always
    ports:
      - 9001:8080

    volumes:
      - penpot_assets:/opt/data/assets

    depends_on:
      - penpot-backend
      - penpot-exporter

    networks:
      - penpot

    environment:
      &amp;lt;&amp;lt;: [*penpot-flags, *penpot-http-body-size]

  penpot-backend:
    image: &apos;penpotapp/backend:${PENPOT_VERSION:-latest}&apos;
    restart: always

    volumes:
      - penpot_assets:/opt/data/assets

    depends_on:
      penpot-postgres:
        condition: service_healthy
      penpot-redis:
        condition: service_healthy

    networks:
      - penpot

    environment:
      &amp;lt;&amp;lt;: [*penpot-flags, *penpot-public-uri, *penpot-http-body-size]

      PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
      PENPOT_DATABASE_USERNAME: ${PENPOT_DB_USER}
      PENPOT_DATABASE_PASSWORD: ${PENPOT_DB_PASS}
      PENPOT_REDIS_URI: redis://penpot-redis/0
      PENPOT_ASSETS_STORAGE_BACKEND: assets-fs
      PENPOT_STORAGE_ASSETS_FS_DIRECTORY: /opt/data/assets
      PENPOT_TELEMETRY_ENABLED: true
      PENPOT_TELEMETRY_REFERER: compose
      PENPOT_SMTP_DEFAULT_FROM: ${PENPOT_SMTP_FROM}
      PENPOT_SMTP_DEFAULT_REPLY_TO: ${PENPOT_SMTP_REPLY_TO}
      PENPOT_SMTP_HOST: ${PENPOT_SMTP_HOST:-penpot-mailcatch}
      PENPOT_SMTP_PORT: ${PENPOT_SMTP_PORT:-1025}
      PENPOT_SMTP_USERNAME:
      PENPOT_SMTP_PASSWORD:
      PENPOT_SMTP_TLS: false
      PENPOT_SMTP_SSL: false

  penpot-exporter:
    image: &apos;penpotapp/exporter:${PENPOT_VERSION:-latest}&apos;
    restart: always

    depends_on:
      penpot-redis:
        condition: service_healthy

    networks:
      - penpot

    environment:
      PENPOT_PUBLIC_URI: http://penpot-frontend:8080
      PENPOT_REDIS_URI: redis://penpot-redis/0

  penpot-postgres:
    image: &apos;postgres:15&apos;
    restart: always
    stop_signal: SIGINT

    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;pg_isready -U penpot&apos;]
      interval: 2s
      timeout: 10s
      retries: 5
      start_period: 2s

    volumes:
      - penpot_postgres_v15:/var/lib/postgresql/data

    networks:
      - penpot

    environment:
      - POSTGRES_INITDB_ARGS=--data-checksums
      - POSTGRES_DB=${PENPOT_DB_NAME}
      - POSTGRES_USER=${PENPOT_DB_USER}
      - POSTGRES_PASSWORD=${PENPOT_DB_PASS}

  penpot-redis:
    image: redis:7.2
    restart: always

    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;redis-cli ping | grep PONG&apos;]
      interval: 1s
      timeout: 3s
      retries: 5
      start_period: 3s

    networks:
      - penpot

  ## A mailcatch service, used as temporal SMTP server. You can access via HTTP to the
  ## port 1080 for read all emails the penpot platform has sent. Should be only used as a
  ## temporal solution while no real SMTP provider is configured.

  penpot-mailcatch:
    image: sj26/mailcatcher:latest
    restart: always
    expose:
      - &apos;1025&apos;
    ports:
      - &apos;1080:1080&apos;
    networks:
      - penpot
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;SearXNG&lt;/h3&gt;
&lt;p&gt;For safe, tracker-free searching, I&apos;ve installed &lt;a href=&quot;https://docs.searxng.org/&quot;&gt;SearXNG&lt;/a&gt; - a meta-search engine application.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  searxng:
    image: searxng/searxng
    container_name: SearXNG
    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;nc -z 127.0.0.1 8080 || exit 1&apos;]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    mem_limit: 8g
    cpu_shares: 2048
    security_opt:
      - no-new-privileges:true
    volumes:
      - /volume1/docker/searxng:/etc/searxng:rw
    restart: on-failure:5
    ports:
      - 5147:8080
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;SolidInvoice&lt;/h3&gt;
&lt;p&gt;Sometimes I do work for clients and need to send an invoice, so instead of paying for an infrequently used service, I have installed &lt;a href=&quot;https://solidinvoice.co/&quot;&gt;SolidInvoice&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  db:
    image: postgres:17
    container_name: Solidinvoice-DB
    hostname: solidinvoice-db
    mem_limit: 1g
    cpu_shares: 1024
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: [&apos;CMD&apos;, &apos;pg_isready&apos;, &apos;-q&apos;, &apos;-d&apos;, &apos;solidinvoice&apos;, &apos;-U&apos;, &apos;solidinvoiceuser&apos;]
      timeout: 45s
      interval: 10s
      retries: 10
    volumes:
      - /volume1/docker/solidinvoice/db:/var/lib/postgresql/data:rw
    environment:
      POSTGRES_DB: ${SOLIDINVOICE_DB}
      POSTGRES_USER: ${SOLIDINVOICE_DB_USER}
      POSTGRES_PASSWORD: ${SOLIDINVOICE_DB_PASS}
    restart: on-failure:5

  solidinvoice:
    image: solidinvoice/solidinvoice:2.3.5
    container_name: Solidinvoice
    healthcheck:
      test: [&apos;CMD-SHELL&apos;, &apos;nc -z 127.0.0.1 8765 || exit 1&apos;]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    volumes:
      - /volume1/docker/solidinvoice/data:/etc/solidinvoice:rw
    depends_on:
      - db
    ports:
      - 5484:8765
    restart: on-failure:5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Stirling-PDF&lt;/h3&gt;
&lt;p&gt;Another utility application, Stirling-PDF enables you to do whatever you need with PDF files.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  stirling-pdf:
    container_name: Stirling-PDF
    image: docker.stirlingpdf.com/stirlingtools/stirling-pdf
    mem_limit: 4g
    cpu_shares: 1024
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: timeout 10s bash -c &apos;:&amp;gt; /dev/tcp/127.0.0.1/8080&apos; || exit 1
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    ports:
      - 7890:8080
    volumes:
      - /volume1/docker/stirling/data:/usr/share/tessdata:rw # Required for extra OCR languages
      - /volume1/docker/stirling/config:/configs:rw
      - /volume1/docker/stirling/logs:/logs:rw
    environment:
      PUID: ${PUID}
      PGID: ${PGID}
      DOCKER_ENABLE_SECURITY: true # or false
      SECURITY_ENABLELOGIN: true #or false
      SECURITY_INITIALLOGIN_USERNAME: ${STIRLING_USER}
      SECURITY_INITIALLOGIN_PASSWORD: ${STIRLING_PASS}
      INSTALL_BOOK_AND_ADVANCED_HTML_OPS: false #or true
      SECURITY_CSRFDISABLED: true #or false
      SYSTEM_DEFAULTLOCALE: en_US # or fr_FR or de_DE
      UI_APPNAME: ${STIRLING_APP_NAME}
      UI_HOMEDESCRIPTION: ${STIRLING_APP_DESCRIPTION}
      UI_APPNAMENAVBAR: ${STIRLING_APP_NAME}
      SYSTEM_MAXFILESIZE: ${STIRLING_MAX_FILESIZE} # Set the maximum file size in MB
      METRICS_ENABLED: true
      SYSTEM_GOOGLEVISIBILITY: false # or true
    restart: on-failure:5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Vaultwarden&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/dani-garcia/vaultwarden&quot;&gt;Vaultwarden&lt;/a&gt; is the open-source alternative of Bitwarden, a fantastic password manager. I&apos;m comparing this against Dashlane and it seems to match my needs.&lt;/p&gt;
&lt;p&gt;Here&apos;s the Dockerfile:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;services:
  db:
    image: postgres:17
    container_name: Vaultwarden-DB
    hostname: vaultwarden-db
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: [&apos;CMD&apos;, &apos;pg_isready&apos;, &apos;-q&apos;, &apos;-d&apos;, &apos;vaultwarden&apos;, &apos;-U&apos;, &apos;vaultwardenuser&apos;]
      timeout: 45s
      interval: 10s
      retries: 10
    volumes:
      - /volume1/docker/vaultwarden/db:/var/lib/postgresql/data:rw
    environment:
      POSTGRES_DB: ${VAULTWARDEN_DB_NAME}
      POSTGRES_USER: ${VAULTWARDEN_DB_USER}
      POSTGRES_PASSWORD: ${VAULTWARDEN_DB_PASS}
    restart: on-failure:5

  vaultwarden:
    image: vaultwarden/server:latest
    container_name: Vaultwarden
    hostname: vaultwarden
    security_opt:
      - no-new-privileges:true
    user: ${PUID}:${PGID}
    ports:
      - 4080:4020
    volumes:
      - /volume1/docker/vaultwarden/data:/data:rw
    environment:
      ROCKET_PORT: 4020
      DATABASE_URL: postgresql://vaultwardenuser:vaultwardenpass@vaultwarden-db:5432/vaultwarden
      ADMIN_TOKEN: ${VAULTWARDEN_ADMIN_TOKEN}
      DISABLE_ADMIN_TOKEN: false
      DOMAIN: ${VAULTWARDEN_URL}
      SMTP_HOST: ${SMTP_HOST}
      SMTP_FROM: ${SMTP_USER_ADDRESS}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_SECURITY: starttls
      SMTP_USERNAME: ${SMTP_USER_ADDRESS}
      SMTP_PASSWORD: ${SMTP_PASS}
    restart: on-failure:5
    depends_on:
      db:
        condition: service_started
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Synology Apps&lt;/h3&gt;
&lt;p&gt;The DiskStation DS423+ comes preloaded with a few applications from Synology that work as replacements for cloud application suites like Google Apps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.synology.com/en-global/dsm/feature/drive&quot;&gt;Synology Drive&lt;/a&gt; - This is like Google Drive, complete with web-based office applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reasoning&lt;/h2&gt;
&lt;p&gt;As the title implies, I want to be more in control of my personal data by relying less on big-tech companies to manage things for me. This is especially true as big-tech continues to shoehorn artificial intelligence and LLMs into all their products and services.&lt;/p&gt;
&lt;p&gt;Thankfully, the open-source software community provides folks the ability to take things into their own hands!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #39</title><link>https://ryantrimble.com/blog/weekly-roundup-39/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-39/</guid><description>I like writing code, writing about code, and reading about code. Here are some links about code 😎.</description><pubDate>Sat, 15 Feb 2025 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.zachleat.com/web/nodefine/&quot;&gt;?nodefine — a pattern to skip Custom Element definitions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.zachleat.com/web/nodefine/&quot;&gt;Zach Leatherman&lt;/a&gt; on 2/14/2025&lt;/p&gt;
&lt;p&gt;Zach shares a super clever pattern enables custom element consumers to opt out of automatic definition. Also, &lt;code&gt;&amp;lt;nim-ble&amp;gt;&lt;/code&gt; rhymes with &lt;code&gt;Trimble&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://vale.rocks/posts/ai-is-stifling-tech-adoption&quot;&gt;AI is Stifling Tech Adoption&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://vale.rocks/posts/ai-is-stifling-tech-adoption&quot;&gt;Vale&lt;/a&gt; on 2/13/2025&lt;/p&gt;
&lt;p&gt;Vale&apos;s essay clicks with me; React seems to be the default option when it comes to code generation, leaving out potentially better, more modern, alternatives.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.miriamsuzanne.com/2025/02/12/tech-ai-wtf/&quot;&gt;Tech continues to be political&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.miriamsuzanne.com/&quot;&gt;Miriam Suzanne&lt;/a&gt; on 2/12/2025&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don&apos;t need an agent, I want to maintain my own agency.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Appreciating this article from Mia. Thank you for being here and doing what you do.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.bram.us/2025/02/09/css-custom-functions-teaser/&quot;&gt;CSS Custom Functions are coming … and they are going to be a game changer!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://bram.us/&quot;&gt;Bramus&lt;/a&gt; on 2/9/2025&lt;/p&gt;
&lt;p&gt;Chrome is experimenting with CSS custom functions, which is &lt;em&gt;quite&lt;/em&gt; exciting. Bramus gives a sneak peek of the syntax, it has a &lt;code&gt;return&lt;/code&gt; value!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/what-i-learned-from-migrating-a-vue-project-from-vuex-to-pinia/&quot;&gt;What I learned from migrating a Vue project from Vuex to Pinia&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Michelle Barker&lt;/a&gt;, published on &lt;a href=&quot;https://piccalil.li/&quot;&gt;Piccalilli&lt;/a&gt; on 2/6/2025&lt;/p&gt;
&lt;p&gt;Michelle provides key considerations for planning a large upgrades to your codebase, and digs into migrating from Vuex to Pinia.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ericwbailey.website/published/stanislav-petrov/&quot;&gt;Stanislav Petrov&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ericwbailey.website/&quot;&gt;Eric W. Bailey&lt;/a&gt; on 2/4/2025&lt;/p&gt;
&lt;p&gt;I&apos;ve heard the cliffnotes of this story previously, but a very interesting history lesson from Eric, given how applicable the lesson is nowadays.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;From yours truly&lt;/h2&gt;
&lt;p&gt;I published a few articles over at &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt;, check &apos;em out if you like weird topics such as: &lt;a href=&quot;https://css-tricks.com/handwriting-an-svg-heart-with-our-hearts/&quot;&gt;handwriting SVGs&lt;/a&gt;, &lt;a href=&quot;https://css-tricks.com/organizing-design-system-component-patterns-with-css-cascade-layers/&quot;&gt;nesting cascade layers&lt;/a&gt;, and &lt;a href=&quot;https://css-tricks.com/compiling-css-with-vite-and-lightning-css/&quot;&gt;build configurations&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Building with AI: Work Hackathon</title><link>https://ryantrimble.com/blog/building-with-ai-work-hackathon/</link><guid isPermaLink="true">https://ryantrimble.com/blog/building-with-ai-work-hackathon/</guid><description>I participated in a work hackathon exploring artificial intelligence, here&apos;s what I found out!</description><pubDate>Sun, 02 Feb 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As a team-building exercise, this was a lot of fun for a group of developers and engineers. I&apos;ve never participated in a hackathon before, so I was excited to try something new.&lt;/p&gt;
&lt;p&gt;The scope of the hackathon was to experiment with AI: use AI powered tools, implement AI into our app, or create new products or features using AI.&lt;/p&gt;
&lt;p&gt;We&apos;re alotted 2 days of work (lunch provided!) to answer a few questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What did you discover?&lt;/li&gt;
&lt;li&gt;What&apos;s the value to the business?&lt;/li&gt;
&lt;li&gt;What next steps would you recommend?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Selecting an AI Model&lt;/h2&gt;
&lt;p&gt;There&apos;s several different AI models to choose from nowadays: GPT, Claude, Gemini - they all do pretty much the same things.&lt;/p&gt;
&lt;p&gt;I&apos;m by no means about to claim I understand the technical differences of the models, but the gist of &lt;em&gt;all&lt;/em&gt; of them is: you tell AI what you want, and hope that it returns some semblence of the thing you&apos;re looking for.&lt;/p&gt;
&lt;p&gt;With that in mind, Google&apos;s Gemini has a very straightforward node package and API, plus I was born in June, so I chose that one.&lt;/p&gt;
&lt;p&gt;Quick note on pricing: it&apos;s all very confusing, I imagine that&apos;s deliberate. I handled everything using the free tier Gemini provides, though the main benefit of paid tiers is that data sent to Gemini is allegedly not used in training their product.&lt;/p&gt;
&lt;h2&gt;Building the project&lt;/h2&gt;
&lt;p&gt;I&apos;m already put off from &quot;chat&quot; user interfaces for AI, so I wanted to do something a bit different. Also, this was a great excuse to try out the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API&quot;&gt;Media Capture and Streams API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I scaffolded the application with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; as my main framework, opting for &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; to handle the reactive client-side JavaScript bits.&lt;/p&gt;
&lt;p&gt;Astro is great for this kind of stuff: I can quickly build endpoints using &lt;a href=&quot;https://docs.astro.build/en/guides/actions/&quot;&gt;Actions&lt;/a&gt;, wrap the JavaScript up as an &lt;a href=&quot;https://docs.astro.build/en/concepts/islands/&quot;&gt;Island&lt;/a&gt;, as well as &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/netlify/&quot;&gt;server side render&lt;/a&gt; things on &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Vue is my favorite of the popular reactive JavaScript libraries and frameworks, as it&apos;s a pleasure to work with, even with Typescript. Also, it&apos;s the primary framework we use in our product applications.&lt;/p&gt;
&lt;p&gt;The idea is to have the AI extract information from photos, rather than text prompts. Basically, a simplified version of &lt;a href=&quot;https://lens.google/&quot;&gt;Google Lens&lt;/a&gt;. You can find the full project code in &lt;a href=&quot;https://github.com/mrtrimble/a-eye/tree/main&quot;&gt;the project&apos;s GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Creating a Web Cam&lt;/h3&gt;
&lt;p&gt;The core functionality of my idea revolved around taking photos, so I decided to get that working first. I hadn&apos;t really tried doing any kind of media capture before, but it&apos;s weirdly fun to work with hardware and code. Like an &quot;A-ha!&quot; moment when the camera turns on.&lt;/p&gt;
&lt;p&gt;Resources for building the webcam:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Followed along with Chris Nwamba&apos;s Digital Ocean community tutorial, &lt;a href=&quot;https://www.digitalocean.com/community/tutorials/front-and-rear-camera-access-with-javascripts-getusermedia&quot;&gt;How To Access Front and Rear cameras with JavaScript&apos;s getUserMedia()&lt;/a&gt;, which got me quite far building things out.&lt;/li&gt;
&lt;li&gt;I also checked out &lt;a href=&quot;https://charliegerard.dev/&quot;&gt;Charlie Gerard&lt;/a&gt;&apos;s project from the &lt;a href=&quot;https://youtu.be/_H5pnNeCJWQ?si=IbrFYN06bjjYArkU&quot;&gt;Web Dev Challenge&lt;/a&gt; episode she had featured on, for some hints on how to turn the data into blobs and how to pass that along to Gemini.&lt;/li&gt;
&lt;li&gt;Of course, MDN also has &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia&quot;&gt;excellent information&lt;/a&gt; on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API&quot;&gt;Media Capture and Streams API&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I originally built the web camera component as a &lt;a href=&quot;https://github.com/mrtrimble/a-eye/blob/main/src/components/WebCamera.vue&quot;&gt;Vue single file component&lt;/a&gt; for the hackathon project, but later rewrote it as a web component for future use as a web component. Check out the repo for that on &lt;a href=&quot;https://github.com/mrtrimble/wc-camera&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Adding AI&lt;/h3&gt;
&lt;p&gt;Google has an easy to set up node package, installable with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm install @google/generative-ai
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You need an API key, which can be created on the &lt;a href=&quot;https://ai.google.dev/&quot;&gt;Google AI Studio&lt;/a&gt; site. I stored my key in an &lt;code&gt;.env&lt;/code&gt; file and named the environment variable &lt;code&gt;GEMINI_API_KEY&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can quickly get a response from Gemini like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { GoogleGenerativeAI } from &apos;@google/generative-ai&apos;;

const key = import.meta.env.GEMINI_API_KEY; // vite
const genAI = new GoogleGenerativeAI(key);
const model = genAI.getGenerativeModel({
  model: &apos;gemini-1.5-flash&apos;,
});

const prompt = &apos;This is a test, are you there?&apos;;

const { reponse } = await model.generateContent(prompt);

console.log({ response });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That will return a very conversational-like response, basically the same as what you get when you ask Gemini a question in the official application. We don&apos;t really want that though, as the response will be unpredictable.&lt;/p&gt;
&lt;p&gt;Instead, we can tell Gemini exactly the response format we need by passing along response schema.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Import SchemaType
import { GoogleGenerativeAI, SchemaType } from &apos;@google/generative-ai&apos;;

const key = import.meta.env.GEMINI_API_KEY; // vite
const genAI = new GoogleGenerativeAI(key);

// Create a schema object for desired response:
const myResponseSchema = {
  description: &apos;Part Identification&apos;,
  type: SchemaType.OBJECT,
  properties: {
    name: {
      type: SchemaType.STRING,
      description: &apos;Provide the name of the part in the included photo&apos;,
      nullable: false,
    },
    description: {
      type: SchemaType.STRING,
      description: &apos;Provide a short description of the part in the included photo&apos;,
      nullable: false,
    },
    dimensions: {
      type: SchemaType.OBJECT,
      properties: {
        height: {
          type: SchemaType.STRING,
          description: &quot;Provide the part&apos;s height in inches&quot;,
          nullable: false,
        },
        width: {
          type: SchemaType.STRING,
          description: &quot;Provide the part&apos;s width in inches&quot;,
          nullable: false,
        },
        depth: {
          type: SchemaType.STRING,
          description: &quot;Provide the part&apos;s depth in inches&quot;,
        },
      },
    },
    color: {
      type: SchemaType.STRING,
      description: &quot;Provide the part&apos;s color in hexadecimal&quot;,
    },
    materials: {
      type: SchemaType.ARRAY,
      description: &apos;Provide a list of part materials&apos;,
      items: {
        type: SchemaType.STRING,
      },
    },
  },
  required: [&apos;name&apos;, &apos;description&apos;, &apos;dimensions&apos;, &apos;color&apos;, &apos;materials&apos;],
};

// Include the schema in the model:
const model = genAI.getGenerativeModel({
  model: &apos;gemini-1.5-flash&apos;,
  generationConfig: {
    responseMimeType: &apos;application/json&apos;,
    responseSchema: myResponseSchema,
  },
});

const { reponse } = await model.generateContent(prompt);

console.log({ response });
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can also send our prompt as an array to Gemini, each item in the array a different part of the prompt. Here I&apos;m sending some prompt instructions as well as the image created by the web camera component:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//... image comes from web camera

const promptInstructions = `
    Examine the part in this photo. 
    
    Provide a name and description of the part. Also provide the dimensions: height, width, and depth in inches. 
    
    Follow the provided JSON schema.
  `;

// passing promptInstructions and image to Gemini:
const { response } = await model.generateContent([promptInstructions, image]);
console.log(response);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If I take a photo of an Xbox controller on my desk, Gemini will return a response such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;color&quot;: &quot;#FFFFFF&quot;,
  &quot;description&quot;: &quot;A white wireless controller with black joysticks and buttons. The controller has a directional pad, four face buttons (A, B, X, Y) on the right side, two joysticks, and a share button in the middle. The controller has a glossy finish and a textured grip on the back. It is designed for use with the Xbox Series X and Series S consoles.&quot;,
  &quot;dimensions&quot;: {
    &quot;depth&quot;: &quot;2.5&quot;,
    &quot;height&quot;: &quot;4&quot;,
    &quot;width&quot;: &quot;6&quot;
  },
  &quot;materials&quot;: [&quot;plastic&quot;],
  &quot;name&quot;: &quot;Xbox Wireless Controller&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Not gonna lie, this part is pretty cool. It felt very much like working with a backend engineer who can quickly provide whatever you need, in whatever format you need. However, the data in the results still varies widely.&lt;/p&gt;
&lt;h3&gt;Working with Astro Actions&lt;/h3&gt;
&lt;p&gt;Once I had worked out both the web cam and the Gemini pieces, I was able to wire up the calls to Gemini as Astro actions.&lt;/p&gt;
&lt;p&gt;Actions are basically endpoints we can use to trigger server-side functions. This is how we can snap a photo, submit the photo to Gemini, then dynamically receive a response.&lt;/p&gt;
&lt;p&gt;To create actions, add an &lt;code&gt;actions/&lt;/code&gt; folder to the Astro project, and include an &lt;code&gt;index.ts&lt;/code&gt; file (&lt;code&gt;index.js&lt;/code&gt; if not using Typescript).&lt;/p&gt;
&lt;p&gt;Inside the &lt;code&gt;index.ts&lt;/code&gt; file, we can define a server to handle our actions. As an example, we can create an action to return a greeting after submitting a form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//actions/index.ts
import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;

export const server = {
  // define actions as properties of server
  getGreeting: defineAction({
    accepts: &apos;form&apos;,
    input: z.object({
      name: z.string(),
    }),
    handler: async input =&amp;gt; {
      return `Hello, ${input.name}!`;
    },
  }),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One unexpected bit of awesomeness was that Actions work in any type of component, not &lt;em&gt;just&lt;/em&gt; Astro components. This allowed me to import actions into Vue components, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;!-- Vue Template --&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script setup lang=&quot;ts&quot;&amp;gt;
import { actions } from &apos;astro:actions&apos;;

const handleAction = payload =&amp;gt; {
  try {
    const { data, error } = await actions.getGreeting(payload);

    if (error) throw new Error(error);

    if (data) {
      // do stuff!
    }
  } catch (error) {
    console.log(error);
  }
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Actions can also be organized into independent files, then imported into the &lt;code&gt;actions/index.ts&lt;/code&gt; file. I seperated Actions for Gemini into its own, &lt;a href=&quot;https://github.com/mrtrimble/a-eye/blob/main/src/actions/gemini.ts&quot;&gt;separate file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Actions give us a simple way to ideate a bit and extend our application&apos;s features easily.&lt;/p&gt;
&lt;h3&gt;Extending Featureset&lt;/h3&gt;
&lt;p&gt;Along with detecting and identifying objects, I had planned for a few more features: document scanning, 2D diagram drawings, and even generating 3D models, all based on objects found in the captured photo image.&lt;/p&gt;
&lt;p&gt;I added two more Astro actions and different response schemas for each. Adding the document scanner went smoothly, no troubles there.&lt;/p&gt;
&lt;p&gt;AI can definitely transcribe text, as I tested it with handwritten messages and it nailed it every time. The part I raised an eyebrow at was when I scanned a paragraph of a book, and it was able to return the entire page the paragraph was in. I don&apos;t know how it would have known that, without already knowing the book.&lt;/p&gt;
&lt;p&gt;The main problem was when I attempted to have the Gemini return a generated image. The very interesting part is Gemini never even told me it could not handle this through the JavaScript API, instead returned fake links to Imgur pages.&lt;/p&gt;
&lt;p&gt;After doing a bit of research, I realized I&apos;d have to configure some sort of &lt;a href=&quot;https://ai.google.dev/gemini-api/docs/imagen&quot;&gt;Python based backend service&lt;/a&gt;, and I didn&apos;t really feel like doing that. I opted for the next best thing: asking Gemini to create ASCII art style 2D diagrams of the object found in the photo.&lt;/p&gt;
&lt;p&gt;This proved hilarious and nightmare-inducing results. Mainly in the form of this guy:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     _.--&quot;&quot;&quot;--._
    .&apos;          `.
   /   O      O   \
  |    \  ^  /    |
  \     `----&apos;     /
   `. _______ .&apos;
     //_____\\
    (( ____ ))
     `-----&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&apos;t want to imagine AI as having feelings or being human-like in any way, however, I can&apos;t help but feel that Gemini was frustrated with my request, as this face was &lt;em&gt;all&lt;/em&gt; it would return after a while, with occasional slight variations: sometimes taller, sometimes offscreen, sometimes zoomed in, sometimes happy, sometimes mad.&lt;/p&gt;
&lt;p&gt;I also didn&apos;t want to imagine what might happen if that face had a third dimension, and well, since the API doesn&apos;t support image generation yet - I didn&apos;t even attempt to have Gemini generate anything 3D.&lt;/p&gt;
&lt;h2&gt;My Findings&lt;/h2&gt;
&lt;p&gt;I have to admit something. I&apos;m not a fan of AI. This might not be news if you follow my blog.&lt;/p&gt;
&lt;p&gt;With obvious concerns over &lt;a href=&quot;https://en.wikipedia.org/wiki/Environmental_impacts_of_artificial_intelligence&quot;&gt;energy and environmental damage&lt;/a&gt;, as well as widespread &lt;a href=&quot;https://hbr.org/2023/04/generative-ai-has-an-intellectual-property-problem&quot;&gt;copyright abuse and infringement&lt;/a&gt; - all of which to give us something we &lt;em&gt;most likely&lt;/em&gt; shouldn&apos;t trust (given a tendency of &lt;a href=&quot;https://searchengineland.com/google-ai-overview-fails-442575&quot;&gt;inaccurate results&lt;/a&gt;, &lt;a href=&quot;https://time.com/7202784/ai-research-strategic-lying/&quot;&gt;lying&lt;/a&gt;, or &lt;a href=&quot;https://www.ibm.com/think/topics/ai-hallucinations&quot;&gt;straight up making things up&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Setting aside &lt;em&gt;all that&lt;/em&gt; for now, I understand it&apos;s the &lt;em&gt;next big thing&lt;/em&gt;™, and many businesses already rushed in headfirst or are likely looking into how to use it in some capacity. I think the hackathon was a decent approach: test the waters and see what we might find.&lt;/p&gt;
&lt;p&gt;Seeing the varying levels of success I, myself, had - as well as the other participants in the hackathon (very awesome submissions!) - I still can&apos;t say I can trust results provided by artificial intelligence.&lt;/p&gt;
&lt;p&gt;Larger AI companies tend to make us believe that these tools might be useful for &lt;em&gt;all the things&lt;/em&gt;, however, if you narrow the scope of data these models are training on, you may have much higher success rates with recieving useful results.&lt;/p&gt;
&lt;p&gt;This was pointed out by one of my co-workers, who explained how using open source models, such as &lt;a href=&quot;https://www.llama.com/&quot;&gt;Llama&lt;/a&gt;, may be more cost-effective on our own infrastructure, as well as having a smaller carbon footprint.&lt;/p&gt;
&lt;p&gt;Interacting with AI was fine, even fun at times, and &lt;em&gt;can&lt;/em&gt; be helpful. You can iterate on ideas quickly, which is nice, but mixed results leave me feeling less-than-confident about trusting what AI tells me. I feel it may have &lt;em&gt;some&lt;/em&gt; value, however, I&apos;m not sure that value outweighs the cost our environment is paying.&lt;/p&gt;
&lt;p&gt;Personally, I try to be open-minded about many things and enjoy challenging my own beliefs, making sure I&apos;ve given things a fair shake before fully commiting the belief to the repository in my head. I went into the hackathon with some pre-conceived notions about using artificial intelligence, and for the most part, my views remain unchanged.&lt;/p&gt;
&lt;p&gt;If AI companies were able solve some of the larger problems plaguing artificial intelligence, it may be worth a re-visit. The Chinese-backed company behind &lt;a href=&quot;https://www.deepseek.com/&quot;&gt;Deepseek&lt;/a&gt; has &lt;a href=&quot;https://www.reuters.com/technology/artificial-intelligence/what-is-deepseek-why-is-it-disrupting-ai-sector-2025-01-27/&quot;&gt;claimed&lt;/a&gt; to create faster, smarter models with a fraction of the overhead compared to OpenAI&apos;s GPT. These types of advancements are more exciting to me than the continuous efforts to make faster, more all-encompassing models.&lt;/p&gt;
&lt;p&gt;As for hackathons: how do I sign up for the &lt;a href=&quot;https://www.youtube.com/playlist?list=PLz8Iz-Fnk_eTkZvSNWXW_TKZ2UwVirT2M&quot;&gt;Web Dev Challenge&lt;/a&gt;?&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #38</title><link>https://ryantrimble.com/blog/weekly-roundup-38/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-38/</guid><description>I built a project with AI, Andy has opinions on CSS nesting, and Josh explains container queries!</description><pubDate>Sun, 02 Feb 2025 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ryantrimble.com/blog/building-with-ai-work-hackathon&quot;&gt;Building with AI: Work Hackathon&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ryantrimble.com/&quot;&gt;Ryan Trimble&lt;/a&gt; on 2/2/2025&lt;/p&gt;
&lt;p&gt;I participated in my work&apos;s hackathon exploring AI. I had some fun with it, however I&apos;m still not ready to trust AI. Check out how I built my project with Astro, Vue, and Google Gemini.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/css-nesting-use-with-caution/&quot;&gt;CSS Nesting: use with caution&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt;, published on &lt;a href=&quot;https://piccalil.li/&quot;&gt;Piccalilli&lt;/a&gt; on 1/30/2025&lt;/p&gt;
&lt;p&gt;Andy makes the case for using CSS native nesting with caution; I mostly agree that Sass has done a number on us, though I&apos;d argue for &quot;use responsibly&quot; instead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/the-mistakes-of-css/&quot;&gt;The Mistakes of CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://css-tricks.com/author/monknow/&quot;&gt;Juan Diego Rodriguez&lt;/a&gt;, published on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; on 1/27/2025&lt;/p&gt;
&lt;p&gt;Juan thoughtfully comments on the &quot;mistakes&quot; in CSS and the technical debt on fixing these mistakes. If only the CSS Working Group had a time machine!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.joshwcomeau.com/css/container-queries-unleashed/&quot;&gt;Container Queries Unleashed&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.joshwcomeau.com/&quot;&gt;Josh W. Comeau&lt;/a&gt; on 1/27/2025&lt;/p&gt;
&lt;p&gt;Many of Josh&apos;s articles include top-notch interactive examples, and this is no different. If you are having trouble understanding container queries, look no further!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/uswds/uswds-site/pull/3078&quot;&gt;Pull Request #3078 of the US Web Design System&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Take a look at how an &lt;a href=&quot;https://www.whitehouse.gov/presidential-actions/2025/01/ending-radical-and-wasteful-government-dei-programs-and-preferencing/&quot;&gt;executive order&lt;/a&gt; deleted sections focusing on diversity, equity, and inclusivity of the United State&apos;s Digital Web Service&apos;s design system site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://blog.archive.org/2024/05/08/end-of-term-web-archive/&quot;&gt;End of Term Web Archive&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Many folks have noticed government websites containing lots of vital information are being purged. I&apos;m glad there are folks out there preserving things, such as &lt;a href=&quot;https://archive.org/donate&quot;&gt;Archive.org&lt;/a&gt;. Apparently, they run an &quot;end of term&quot; archive as a United States President is ending their term in office. Pretty rad!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #37</title><link>https://ryantrimble.com/blog/weekly-roundup-37/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-37/</guid><description>I took last week off, now I owe twice as many links.</description><pubDate>Sat, 25 Jan 2025 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://simonwillison.net/2025/Jan/24/selfish-open-source/&quot;&gt;A selfish personal argument for releasing code as Open Source&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://simonwillison.net/&quot;&gt;Simon Willison&lt;/a&gt; on 1/24/2025&lt;/p&gt;
&lt;p&gt;During a recent interview, Simon explained how open sourcing code helps make sure he never loses access to code, even if when moving to a new job.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://whitep4nth3r.com/blog/how-to-build-a-copy-code-snippet-button/&quot;&gt;How to build a copy code snippet button and why it matters&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://whitep4nth3r.com/&quot;&gt;Salma Alam-Naylor&lt;/a&gt; on 1/24/2025&lt;/p&gt;
&lt;p&gt;Salma&apos;s been coding hands-free and finding code snippets generally difficult to copy and paste without using your hands in some capacity, and provides directions on how to add it to your site.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://gomakethings.com/accessibility-is-woke-now/&quot;&gt;Accessibility is woke now?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on 1/24/2025&lt;/p&gt;
&lt;p&gt;Chris shares concerns over how the United States seems to be shutting down many diversity, equality, and inclusivity programs and what that means for the accessible web. Personally, accessibility will remain a primary goal for me going forward; I consider it part of the job.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.mikeaparicio.com/posts/2025-01-23-styling-a-meter-element-with-css-and-svg/&quot;&gt;Styling a meter element with CSS and SVG&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.mikeaparicio.com/&quot;&gt;Mike Aparicio&lt;/a&gt; on 1/23/2025&lt;/p&gt;
&lt;p&gt;Mike explains how to transform the &lt;code&gt;&amp;lt;meter&amp;gt;&lt;/code&gt; HTML element into a star rating, excellent for rating movies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.bram.us/2025/01/20/css-attr-gets-an-upgrade/&quot;&gt;CSS attr() gets an upgrade&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.bram.us/&quot;&gt;Bramus&lt;/a&gt; on 1/20/2025&lt;/p&gt;
&lt;p&gt;This is a ridiculously exciting development, giving us a new way to interface our CSS with HTML. Bramus gives a great rundown as per usual, also be sure check out all the exciting features released in the &lt;a href=&quot;https://developer.chrome.com/blog/chrome-133-beta&quot;&gt;Chrome 133 beta&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://nerdy.dev/6-css-snippets-every-front-end-developer-should-know-in-2025&quot;&gt;6 CSS Snippets Every Front-End Developer Should Know In 2025&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; on 1/19/2025&lt;/p&gt;
&lt;p&gt;Adam wrote up this list of some great features he thinks CSS developers should know going into 2025. I still want CSS developers to know grid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://bobmonsour.com/notes/music-is-replacing-my-self-talk/&quot;&gt;Music is replacing my self-talk&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://bobmonsour.com/&quot;&gt;Bob Monsour&lt;/a&gt; on 1/15/2025&lt;/p&gt;
&lt;p&gt;Bob bestows some excellent advice for us folks with busy minds. Also, his post about &lt;a href=&quot;https://bobmonsour.com/notes/playing-poosticks/&quot;&gt;playing Poohsticks&lt;/a&gt; is adorable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://fullystacked.net/new-with-dialog/&quot;&gt;What&apos;s new with dialog&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://fullystacked.net/&quot;&gt;Ollie Williams&lt;/a&gt; on 1/15/2025&lt;/p&gt;
&lt;p&gt;Ollie dives into &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements in Chrome Canary, looks like there might be HTML-only controls coming soon.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://cloudfour.com/thinks/justified-text-better-than-expected/&quot;&gt;Justified Text: Better Than Expected?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://tylersticka.com/&quot;&gt;Tyler Sticka&lt;/a&gt; on 1/15/2025&lt;/p&gt;
&lt;p&gt;Tyler examines &lt;code&gt;hyphens&lt;/code&gt;, &lt;code&gt;text-wrap&lt;/code&gt; and &lt;code&gt;hyphenate-limit-chars&lt;/code&gt; to see if we are closer to having decent justified text on the web, and it turns out: maybe!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/how-to-wait-for-the-sibling-count-and-sibling-index-functions/&quot;&gt;How to Wait for the sibling-count() and sibling-index() Functions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://css-tricks.com/author/monknow/&quot;&gt;Juan Diego Rodriguez&lt;/a&gt;, published on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; on 1/13/2025&lt;/p&gt;
&lt;p&gt;My friend Juan over at CSS-Tricks is onto some next-level stuff, explaining newer CSS functions &lt;code&gt;sibling-count()&lt;/code&gt; and &lt;code&gt;sibling-index()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #36</title><link>https://ryantrimble.com/blog/weekly-roundup-36/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-36/</guid><description>Welcome to 2025, let&apos;s make this year fun!</description><pubDate>Sat, 11 Jan 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m still settling into my new role, and having a great time! The folks on my team are super nice and helpful, I see a lot of great opportunities for the frontend.&lt;/p&gt;
&lt;p&gt;It&apos;s an interesting thing; jumping into a new software development team and comparing notes on processes. There are things you see and are like, &quot;Oh, so &lt;em&gt;that&apos;s&lt;/em&gt; how that should work&quot; or maybe you already tackled a particular problem with your former team, so you have some experience on how to improve something (currently introducing my friend, &lt;a href=&quot;https://vite.dev/&quot;&gt;Vite&lt;/a&gt;, to the team).&lt;/p&gt;
&lt;p&gt;I&apos;m quite excited, which makes it easy to fall into &lt;em&gt;&quot;Do All the Things!&quot;&lt;/em&gt; mode, so I have to keep reminding myself there&apos;ll be plenty of time to get things right.&lt;/p&gt;
&lt;h2&gt;Blogroll Updates&lt;/h2&gt;
&lt;p&gt;My &lt;a href=&quot;https://ryantrimble.com/blog/roll&quot;&gt;Blogroll&lt;/a&gt; is kind of my rolodex of awesome, so I asked on &lt;a href=&quot;https://bsky.app/profile/ryantrimble.com/post/3lemkgf3ow22r&quot;&gt;Bluesky&lt;/a&gt; and &lt;a href=&quot;https://front-end.social/@mrtrimble/113748569257216451&quot;&gt;Mastodon&lt;/a&gt; for new feeds to follow, and you all delivered.&lt;/p&gt;
&lt;p&gt;I added 40+ feeds to the blogroll and the damn thing stopped working. More specifically, the site build kept timing out while fetching all the posts.&lt;/p&gt;
&lt;p&gt;I&apos;ve fixed this temporarily by switching to a more manual process, writing a node script to grab the feeds from a JSON file, parsing each feed and grabbing the latest three posts.&lt;/p&gt;
&lt;p&gt;It&apos;s working, like, ~95% — for whatever reason it&apos;s not sorting &lt;em&gt;something&lt;/em&gt; correctly, so some feeds are giving the &lt;em&gt;first&lt;/em&gt; three posts instead of the latest.&lt;/p&gt;
&lt;p&gt;I&apos;ve got a better solution in mind, so I&apos;m not sure I&apos;ll spend a lot of time fixing this temporary solution.&lt;/p&gt;
&lt;p&gt;Also, I thought it might be nice for folks to grab these feeds for themselves, so I created an &lt;a href=&quot;https://docs.astro.build/en/guides/endpoints/&quot;&gt;Astro endpoint&lt;/a&gt; to dynamically generate an &lt;a href=&quot;https://en.wikipedia.org/wiki/OPML&quot;&gt;OPML file&lt;/a&gt; based on the list feeds.&lt;/p&gt;
&lt;p&gt;Yeah, I know I could have just shared the OPML file, but where is the fun in that? (Thanks to &lt;a href=&quot;https://rknight.me/blog/creating-an-opml-file-for-my-blogroll/&quot;&gt;Robb Knight&lt;/a&gt; for the inspiration.)&lt;/p&gt;
&lt;p&gt;While checking out all these rad personal sites and blogs from all the folks who kindly shared their work with me, I spotted a &lt;em&gt;sick&lt;/em&gt; sticker:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I messaged the sticker&apos;s creator, &lt;a href=&quot;https://benji.dog/&quot;&gt;Benji&lt;/a&gt;, asking if these metal AF stickers were still available and received a prompt reply asking for a mailing address. A few days later I received it in the mail, thank you so much, Benji!&lt;/p&gt;
&lt;p&gt;Benji has a &lt;code&gt;/stickers&lt;/code&gt; page on their site, which is something I&apos;ve been thinking about adding to my site for a while, as I&apos;ve got a quite a sticker collection going at this point.&lt;/p&gt;
&lt;p&gt;Wait, what were we talking about? Oh right!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://neal.fun/stimulation-clicker/&quot;&gt;Stimulation Clicker&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;created by &lt;a href=&quot;https://neal.fun/&quot;&gt;Neal Agarwal&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Neal makes some of the most ridiculous things ever and I love it, definitely check this out for yourself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/the-importance-of-investing-in-soft-skills-in-the-age-of-ai/&quot;&gt;The Importance of Investing in Soft Skills in the Age of AI&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt;, published on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; on 1/10/2025&lt;/p&gt;
&lt;p&gt;Andy makes the case for developing soft skills to stand out against the rising risk of AI competition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/balancing-text-css/&quot;&gt;Balancing Text In CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on 1/4/2025&lt;/p&gt;
&lt;p&gt;Ahmad provides a high-quality explainer on one of the prettier new CSS properties: &lt;code&gt;text-balance&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://adrianroselli.com/2025/01/ftc-catches-up-to-accessibe.html&quot;&gt;FTC Catches up to #accessiBe&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://adrianroselli.com/&quot;&gt;Adrian Roselli&lt;/a&gt; on 1/4/2025&lt;/p&gt;
&lt;p&gt;Anyone who knows about accessibility overlays probably isn&apos;t shocked right now, but also probably feeling a &lt;em&gt;little&lt;/em&gt; vindication.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://chriskirknielsen.com/blog/simple-table-of-contents-highlighter/&quot;&gt;“Simple” Table of Contents Highlighter&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://chriskirknielsen.com/&quot;&gt;Christopher Kirk-Nielson&lt;/a&gt; on 1/3/2025&lt;/p&gt;
&lt;p&gt;Chris breaks down different approaches to a common user interface pattern, each time improving on the concept. I&apos;ve built one of these before and stopped around the &quot;basic&quot; version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://anhvn.com/posts/2025/media-recap-2024/&quot;&gt;Media Recap 2024&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://anhvn.com/&quot;&gt;Anh&lt;/a&gt; on 1/2/2025&lt;/p&gt;
&lt;p&gt;Maybe the most gorgeous Media Recap ever? Anh delivers art and some solid recommendations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://khalidabuhakmeh.com/great-dotnet-documentation-with-astro-starlight-and-markdownsnippets&quot;&gt;Great .NET Documentation with Astro, Starlight, and MarkdownSnippets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://khalidabuhakmeh.com/&quot;&gt;Khalid Abuhakmah&lt;/a&gt; on 12/31/2024&lt;/p&gt;
&lt;p&gt;Khalid always seems to know what problems I am going to run into someday, and has a blog post at the ready.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;New Looks for 2025&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;While touch-and-go for a moment, &lt;a href=&quot;https://lynnandtonic.com/&quot;&gt;Lynn Fisher&lt;/a&gt; delivered her annual portfolio redesign, and of course it rocks.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://henry.codes/&quot;&gt;Henry Desroches&lt;/a&gt; dropped a gothic, bombshell of a redesign as well (don&apos;t worry, Henry knows about the &lt;a href=&quot;https://henry.codes/writing/i-know-about-the-date-in-the-footer/&quot;&gt;date in the footer&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Looking to Learn&lt;/h2&gt;
&lt;p&gt;If your New Year&apos;s resolution involves learning to code, I&apos;ve got a few links for you to check out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you&apos;re looking for a great way to learn &lt;a href=&quot;https://thebasics.dev/&quot;&gt;the basics&lt;/a&gt;, my pal Geoff Graham has you covered.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Kevin Powell recently released two courses: &lt;a href=&quot;https://www.youtube.com/playlist?list=PL4-IK0AVhVjOJs_UjdQeyEZ_cmEV3uJvx&quot;&gt;HTML for Beginners&lt;/a&gt; over on his YouTube channel, as well as &lt;a href=&quot;https://frontendmasters.com/courses/pro-css/&quot;&gt;Professional CSS&lt;/a&gt; on Frontend Masters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To round out your CSS skills, Andy Bell&apos;s &lt;a href=&quot;https://piccalil.li/complete-css&quot;&gt;Complete CSS&lt;/a&gt; is might be your speed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #35</title><link>https://ryantrimble.com/blog/weekly-roundup-35/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-35/</guid><description>The final Weekly Roundup... of the year!</description><pubDate>Sat, 28 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last Roundup of the year!&lt;/p&gt;
&lt;p&gt;I&apos;m still surprised I&apos;ve managed to keep this routine going, 35 weeks later. I think I might have skipped one week, but otherwise &lt;em&gt;fairly&lt;/em&gt; consistent.&lt;/p&gt;
&lt;p&gt;Anyway, let&apos;s wrap up the year with some great links!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;/blog/yearly-roundup-1&quot;&gt;Yearly Roundup #1&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ryantrimble.com/&quot;&gt;Ryan Trimble&lt;/a&gt; on 12/29/2024&lt;/p&gt;
&lt;p&gt;A lot of things happened at me in 2024, so I figured some personal reflection on the year might be nice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://codepen.io/propjockey/pen/JoPyxrK&quot;&gt;Jane Ori found my IP Address with CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Codepen by &lt;a href=&quot;https://propjockey.io/experiments/&quot;&gt;Jane Ori&lt;/a&gt; on 12/28/2024&lt;/p&gt;
&lt;p&gt;Jane continually proves that CSS has a lot more to offer than folks give it credit for, by using it to make an API request and finding the user&apos;s IP address. Read more on the process in the &lt;a href=&quot;https://github.com/propjockey/css-api-fetch&quot;&gt;repo&lt;/a&gt;!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.fronteers.nl/en/blog/2024/12/what-determines-the-accessible-name-of-an-element&quot;&gt;What determines the accessibile name of an element?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt; on 12/26/2024&lt;/p&gt;
&lt;p&gt;Kilian provides a &lt;em&gt;lot&lt;/em&gt; of good information in this article, explaining what an accessible name is and a few gotchas to look out for. Read in &lt;a href=&quot;https://www.fronteers.nl/nl/blog/2024/12/wat-bepaalt-de-toegankelijke-naam-van-een-element&quot;&gt;Dutch&lt;/a&gt; if you are brave...&lt;/p&gt;
&lt;p&gt;...or Dutch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://rightbadcode.com/the-wcag-for-content-writers&quot;&gt;The WCAG for Content Writers&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://rightbadcode.com/&quot;&gt;Homer Gaines&lt;/a&gt; on 3/16/2024&lt;/p&gt;
&lt;p&gt;Accessibility is a team effort, and not just something that only developers need to pay attention to. Homer provides success criteria helpful to content writers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://pridever.org/&quot;&gt;Pride Versioning&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;idea by &lt;a href=&quot;https://tonsky.me/&quot;&gt;Niki Tonsky&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is basically just semantic versioning, but you feel good about it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;12daysofweb.dev&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://12daysofweb.dev/&quot;&gt;12 Days of Web&lt;/a&gt; series concluded this week, here are the last few days - be sure to check out all the articles!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/broadcastchannel-api/&quot;&gt;Day 10: BroadcastChannel API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Stephanie Eckles&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Did you know you can broadcast data between open tabs if they are from the same origin? Steph explains with an awesome demo: open the page twice in different tabs to try it for yourself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/how-to-use-baseline-data/&quot;&gt;Day 11: How to Use Baseline Data&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://rachelandrew.co.uk/&quot;&gt;Rachel Andrew&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As a lead of the &lt;a href=&quot;https://web.dev/baseline&quot;&gt;Baseline initiative&lt;/a&gt;, Rachel is the best person to explain what it is and how to use it. We&apos;ve been using Baseline over at CSS-Tricks for a few weeks now!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/css-margin-trim-line-height-units/&quot;&gt;Day 12: CSS margin-trim and line height units&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://jensimmons.com/&quot;&gt;Jen Simmons&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Jen explains a couple of new CSS properties that are sure to make designers happy. I&apos;m quite interested in &lt;code&gt;margin-trim&lt;/code&gt; and hope to see it in more browsers soon!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Personal thank you&lt;/h2&gt;
&lt;p&gt;Thank you to all the folks featured throughout the past 35 issues. Thank you for making awesome stuff to talk about, please keep it up!&lt;/p&gt;
&lt;p&gt;Thank you to all the folks who actually read these - I don&apos;t do this for an audience, but I know there are a few of you out there and I appreciate you.&lt;/p&gt;
</content:encoded></item><item><title>Yearly Roundup #1</title><link>https://ryantrimble.com/blog/yearly-roundup-1/</link><guid isPermaLink="true">https://ryantrimble.com/blog/yearly-roundup-1/</guid><description>A look back on all the things that happened to me this year.</description><pubDate>Sat, 28 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;With only a few days left of 2024, I thought it might be nice to do a bit of a retrospective on the year.&lt;/p&gt;
&lt;h2&gt;My 2024&lt;/h2&gt;
&lt;h3&gt;Sold our house&lt;/h3&gt;
&lt;p&gt;Early this year, we sold our house and moved into a new apartment building. I really liked the old place, but it was causing a lot of stress from upkeep and maintenance, not to mention being located in a floodzone as it was right next to a creek.&lt;/p&gt;
&lt;h3&gt;Weekly Roundups&lt;/h3&gt;
&lt;p&gt;In April, I posted the &lt;a href=&quot;https://ryantrimble.com/blog/weekly-roundup-1&quot;&gt;first Weekly Roundup&lt;/a&gt; to my blog. I wanted to make posting to my site a routine, as well as practice writing and this turned out to be a great way to do that. I do this for myself, really - not you.&lt;/p&gt;
&lt;h3&gt;Bit of a mental breakdown&lt;/h3&gt;
&lt;p&gt;My job changed &lt;em&gt;dramatically&lt;/em&gt;, and with it my mental state. It&apos;s a story that affects many, a larger company came in and took over. Unfortunately the changes were not positive for me, effectively ending many of the things I cared about, leaving me feeling stranded.&lt;/p&gt;
&lt;h3&gt;Visited Los Angeles&lt;/h3&gt;
&lt;p&gt;Took a &lt;a href=&quot;https://ryantrimble.com/blog/surviving-los-angeles&quot;&gt;trip out to LA&lt;/a&gt; for the first time ever. I really enjoyed the visit and hope to go back at some point. My wife got to meet a friend from New Zealand, and I got to find out if there really was &lt;a href=&quot;https://www.youtube.com/watch?v=g6Kfhwt88ps&quot;&gt;a man behind Winkie&apos;s&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Technical Writer for CSS-Tricks&lt;/h3&gt;
&lt;p&gt;I still can&apos;t believe this one! &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; was one of my favorite sites while learning all things web development, now I get to help others learn! I&apos;m looking forward to what we&apos;ll be able to accomplish with the site in 2025.&lt;/p&gt;
&lt;h3&gt;Attended &lt;em&gt;Frostapalooza&lt;/em&gt;&lt;/h3&gt;
&lt;p&gt;This was &lt;a href=&quot;https://frostapalooza.bradfrost.com/&quot;&gt;a rad musical event&lt;/a&gt; put on by Brad Frost and friends, and a highlight of the year. I got to hangout with my friend &lt;a href=&quot;https://www.mikeaparicio.com/&quot;&gt;Mike&lt;/a&gt; and hear some exceptional covers of &lt;em&gt;Pink Floyd&lt;/em&gt;, &lt;em&gt;Arcade Fire&lt;/em&gt;, and the &lt;em&gt;Yeah Yeah Yeahs&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Redesigned my website&lt;/h3&gt;
&lt;p&gt;Rebuilt my website with iterative improvements over the previous design. I called it &lt;a href=&quot;https://ryantrimble.com/blog/the-hd-remaster&quot;&gt;the HD Remaster&lt;/a&gt;, like how video game studios re-release the same game with slight improvements.&lt;/p&gt;
&lt;h3&gt;Sister&apos;s wedding&lt;/h3&gt;
&lt;p&gt;My sister got married and I was the impromptu wedding photographer. I can&apos;t say I knew what I was doing most of the time, but I managed to get some great photos that came out quite well.&lt;/p&gt;
&lt;h3&gt;A new job!&lt;/h3&gt;
&lt;p&gt;After submitting a countless number of applications and hours of interviewing, I landed a new job at &lt;a href=&quot;https://www.stratus.build/&quot;&gt;Stratus&lt;/a&gt;, as a &lt;em&gt;Senior Frontend Engineer&lt;/em&gt;. The job market is incredibly difficult to navigate nowadays and I&apos;m so glad to finally be done with my search.&lt;/p&gt;
&lt;h2&gt;On to the next one&lt;/h2&gt;
&lt;p&gt;I think 2025 will be another challenging year, but here&apos;s hoping for the best!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #34</title><link>https://ryantrimble.com/blog/weekly-roundup-34/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-34/</guid><description>First week at the new job, plus lots of great CSS articles this week, check it out!</description><pubDate>Sat, 21 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Next week is Christmas and I am not prepared at all. Honestly, I don&apos;t think I was prepared for any holidays this year, they just kind of happened. Now that I&apos;ve found a new job though, I&apos;m hoping for a somewhat slow 2025 so I can actually enjoy time with the important folks in my life.&lt;/p&gt;
&lt;p&gt;Speaking of the new job: I completed my first week! I&apos;d say things are going pretty well so far, I&apos;m already digging into the codebase and pushed my first pull-request. I see lots of great opportunities for growth and I&apos;m itching to do my part.&lt;/p&gt;
&lt;p&gt;Alright, now let&apos;s get into it!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/the-little-triangle-in-the-tooltip/&quot;&gt;The Little Triangle in the Tooltip&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://chriskirknielsen.com/&quot;&gt;Juan Diego Roderiguez&lt;/a&gt;, published by &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; on 12/20/2024&lt;/p&gt;
&lt;p&gt;Juan walks us through how to add the little triangle to tooltips in, not one, not two, but &lt;em&gt;four&lt;/em&gt; different ways.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://nerdy.dev/carousel-adaptive-anchor-positioning-with-calc-in-a-container-query&quot;&gt;A powerful container query&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; on 12/19/2024&lt;/p&gt;
&lt;p&gt;Did you know you could use &lt;code&gt;calc&lt;/code&gt; in container queries? I didn&apos;t either. Adam figured out this powerful combo while making a CSS carousel.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://daverupert.com/2024/12/every-token-is-a-feature/&quot;&gt;Every Token is a feature&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://daverupert.com/&quot;&gt;Dave Rupert&lt;/a&gt; on 12/19/2024&lt;/p&gt;
&lt;p&gt;Interesting observation from Dave on how design tokens can be thought of as features, useful to both design and engineering.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/why-im-excited-about-text-box-trim-as-a-designer/&quot;&gt;Why I&apos;m excited about text-box-trim as a designer&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://piccalil.li/author/jason-bradberry/&quot;&gt;Jason Bradberry&lt;/a&gt;, published by &lt;a href=&quot;https://piccalil.li/&quot;&gt;Piccalilli&lt;/a&gt; on 12/19/2024&lt;/p&gt;
&lt;p&gt;Jason gives a typography lesson and explains why the new &lt;code&gt;text-box-trim&lt;/code&gt; CSS property will help your buttons.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.bram.us/2024/12/18/the-future-of-css-construct-custom-idents-and-dashed-idents-with-ident/&quot;&gt;The Future of CSS: Construct &amp;lt;custom-ident&amp;gt; and &amp;lt;dashed-ident&amp;gt; values with ident()&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.bram.us/&quot;&gt;Bramus&lt;/a&gt; on 12/18/2024&lt;/p&gt;
&lt;p&gt;The CSS Working Group recently resolved to adopt a solution for constructing ident values in CSS, these are what we use to name things like &lt;code&gt;container-name&lt;/code&gt; and &lt;code&gt;view-transition-name&lt;/code&gt;. Bramus proposed this solution and his article explains how this will be beneficial.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.alwaystwisted.com/articles/quick-and-dirty-colour-palettes-using-color-mix&quot;&gt;Quick and Dirty Colour Palettes using color-mix()&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.alwaystwisted.com/&quot;&gt;Stuart Robinson&lt;/a&gt; on 12/9/2024&lt;/p&gt;
&lt;p&gt;I love &lt;a href=&quot;https://ryantrimble.com/blog/mixing-colors-with-css.html&quot;&gt;mixing colors with CSS&lt;/a&gt; and Stuart provides some awesome tips on mixing colors to build color palettes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Sites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://supersnowflakemaker.com/&quot;&gt;Super Snowflake Maker&lt;/a&gt;&lt;/h3&gt;
To help get in the festive spirit, &lt;a href=&quot;https://shalanah.com/&quot;&gt;Shalanah Dawson&lt;/a&gt; created this awesome snowflake maker.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;12daysofweb.dev&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://12daysofweb.dev/&quot;&gt;12 Days of Web&lt;/a&gt; series continues this week, here are few highlights - be sure to check out all the articles!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/css-content-visibility/&quot;&gt;Day 5: CSS content-visibility&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://knowler.dev/&quot;&gt;Nathan Knowler&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nathan explains the newly available &lt;code&gt;content-visibility&lt;/code&gt; property of CSS, which can hide &lt;em&gt;everything&lt;/em&gt; within a wrapper, including content not wrapped inside an HTML tag.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/css-box-decoration-break/&quot;&gt;Day 7: CSS box-decoration-break&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kilian shows us how to fix those weird instances where your design is busted thanks to a line wrap using the &lt;code&gt;box-decoration-break&lt;/code&gt; property.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/css-light-dark/&quot;&gt;Day 9: CSS light-dark()&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://mayank.co/&quot;&gt;Mayank&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mayank gives a rundown of how the CSS &lt;code&gt;light-dark()&lt;/code&gt; function works, allowing you to automatically swap between color-schemes. Bonus points: an easy to implement toggle for your site.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #33</title><link>https://ryantrimble.com/blog/weekly-roundup-33/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-33/</guid><description>My new position starts on Monday, looking forward to new challenges!</description><pubDate>Sat, 14 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On Monday, I start as a &lt;em&gt;Senior Frontend Engineer&lt;/em&gt; for &lt;a href=&quot;https://www.stratus.build/&quot;&gt;STRATUS&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;STRATUS creates applications for &lt;em&gt;MEP&lt;/em&gt; (metal, electrical, and plumbing) professionals that help in design, fabrication, and installations.&lt;/p&gt;
&lt;p&gt;Admittedly, I don&apos;t know much about the construction industry, but I didn&apos;t know much about the insurance industry when I started my previous position either.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;do know&lt;/em&gt; Frontend Development, though, and I&apos;m quite excited to bring my skills to new projects!&lt;/p&gt;
&lt;p&gt;I&apos;ll miss working with my &lt;a href=&quot;https://rimdev.io/&quot;&gt;RIMdev&lt;/a&gt; friends, but let&apos;s be real, I&apos;ll probably bug most of them on occasion anyway.&lt;/p&gt;
&lt;p&gt;Ok, now Let&apos;s dig into some links!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://chriskirknielsen.com/blog/vertical-slider-fitting-the-tallest-element-in-pure-css/&quot;&gt;Vertical slider fitting the tallest element in pure CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://chriskirknielsen.com/&quot;&gt;Christopher Kirk-Nielsen&lt;/a&gt; on 12/13/2024&lt;/p&gt;
&lt;p&gt;Christopher shares an excellent CSS tip to make equal height, scrollable elements. Timely, I&apos;m experimenting with something that could use this technique!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://gomakethings.com/an-overview-of-javascript-testing/&quot;&gt;An overview of JavaScript testing&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on 12/10/2024&lt;/p&gt;
&lt;p&gt;Chris kicked off a nice series of articles to help get up-to-speed on JavaScript testing. Also, Congratulations to Chris on &lt;a href=&quot;https://gomakethings.com/joining-nebula/&quot;&gt;joining Nebula.tv&lt;/a&gt;!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/modern-css-feature-image/&quot;&gt;Solved By Modern CSS: Feature Image&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on 12/9/2024&lt;/p&gt;
&lt;p&gt;Ahmad walks us through how he created the feature image on his website&apos;s homepage using modern CSS techniques.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://benmyers.dev/blog/dont-use-aria-label-on-static-text-elements/&quot;&gt;Don&apos;t Use aria-label on Static Text Elements&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://benmyers.dev/&quot;&gt;Ben Myers&lt;/a&gt; on 12/7/2024&lt;/p&gt;
&lt;p&gt;Ben clears up some confusion on when to use &lt;code&gt;aria-label&lt;/code&gt; and &lt;code&gt;aria-labelledby&lt;/code&gt;. I&apos;m a fan of the landmark pattern!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://rightbadcode.com/explaining-design-systems-to-a-golfer&quot;&gt;Explaining Design Systems to a Golfer&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://rightbadcode.com/&quot;&gt;Homer Gaines&lt;/a&gt; on 12/7/2024&lt;/p&gt;
&lt;p&gt;Lovely recap of how Homer relates design systems to golfing to help his father understand what he does for work.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;12daysofweb.dev&lt;/h2&gt;
&lt;p&gt;I&apos;m a big fan of Steph Eckles&apos; yearly &lt;a href=&quot;https://12daysofweb.dev/&quot;&gt;12 Days of Web&lt;/a&gt; series which kicked off this week!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/calc-size-and-interpolate-size/&quot;&gt;Day 1: calc-size() and interpolate size&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://kevinpowell.co/&quot;&gt;Kevin Powell&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kevin explains the neat new &lt;code&gt;interpolate-size&lt;/code&gt; property and how to use &lt;code&gt;calc-size()&lt;/code&gt; CSS function when animating with keywords.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://12daysofweb.dev/2024/animating-entry-effects/&quot;&gt;Day 2: Animating Entry Effects&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Guest author, &lt;a href=&quot;https://sillyz.computer/&quot;&gt;Tyler Childs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Tyler gives an overview on &lt;code&gt;@starting-style&lt;/code&gt; and &lt;code&gt;transition-behavior: allow-descrete&lt;/code&gt; when animating on entry.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #32</title><link>https://ryantrimble.com/blog/weekly-roundup-32/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-32/</guid><description>I don&apos;t mean to brag, but I wrote two of the articles this week.</description><pubDate>Sat, 07 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Folks, big news&lt;/strong&gt;: I&apos;ve accepted an offer for a new position! I&apos;ll follow-up with more details soon, I&apos;m currently enjoying a bit of R&amp;amp;R until starting.&lt;/p&gt;
&lt;p&gt;Job hunting is long and discouraging. I swear, I must have submitted &lt;em&gt;thousands&lt;/em&gt; of applications with a &lt;em&gt;very small&lt;/em&gt; success rate.&lt;/p&gt;
&lt;p&gt;That being said, the few companies and organizations I had the pleasure to interview with were great. I was in the final round more than a few times, but it&apos;s a tough market with a lot of skilled folks out there.&lt;/p&gt;
&lt;p&gt;I wish I could give a list of tips for folks still looking for a job, but the only suggestion I can muster is: &lt;em&gt;just keep trying&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/7/&quot;&gt;HTMHAIL&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://tink.uk/about-leonie/&quot;&gt;Léonie Watson&lt;/a&gt;, published on 12/7/2024&lt;/p&gt;
&lt;p&gt;Manuel Matuzović&apos;s &lt;a href=&quot;https://htmhell.dev/adventcalendar/&quot;&gt;HTMHell Advent Calendar&lt;/a&gt; is back in time for the holiday season and Léonie wrote about an AI encounter that went entirely wrong.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-12-06-time-for-something-new/&quot;&gt;Time for something new&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on 12/6/2024&lt;/p&gt;
&lt;p&gt;I&apos;m so proud of Jaime, this was an absolutely massive leap and she landed gracefully. I&apos;m looking forward to where her journey leads next!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/one-of-those-onboarding-uis-with-anchor-positioning/&quot;&gt;One of Those “Onboarding” UIs, With Anchor Positioning&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://css-tricks.com/authors/ryantrimble&quot;&gt;Ryan Trimble&lt;/a&gt; on 12/2/2024&lt;/p&gt;
&lt;p&gt;I didn&apos;t intend for this article to eat up my November, but I kept thinking of different ways to use CSS anchor positioning. I&apos;m super excited for it, hope you are as well!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://htmhell.dev/adventcalendar/2024/2/&quot;&gt;Starting off right: Where autofocus shines&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;written by &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt;, published on 12/2/2024&lt;/p&gt;
&lt;p&gt;Another brilliant entry in this year&apos;s HTMHell Advent Calendar, Kilian helps remind folks that &lt;code&gt;autofocus&lt;/code&gt; is a thing and you can actually use it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ryantrimble.com/blog/migrating-your-guestbook&quot;&gt;Migrating your guestbook from Astro Studio&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ryantrimble.com/&quot;&gt;Ryan Trimble&lt;/a&gt; on 12/2/2024&lt;/p&gt;
&lt;p&gt;Another one from me, apologies for shameless self-promotion (this is my website). You might remember, I wrote about how to make a guestbook using Astro Studio, this is a follow up on how to migrate to a different database.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Sites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The Chrome DevRel team put together the &lt;a href=&quot;https://chrome.dev/css-wrapped-2024/&quot;&gt;2024 CSS Wrapped&lt;/a&gt;, showcasing all the neat features CSS received this year.&lt;/li&gt;
&lt;li&gt;I came across &lt;a href=&quot;https://ambiph.one/&quot;&gt;Ambiphone&lt;/a&gt; on &lt;a href=&quot;https://bsky.app/profile/matteason.me/post/3lce5jecqy22k&quot;&gt;Bluesky&lt;/a&gt;, and it&apos;s a lovely little ambient noise generator.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://indieweb.social/@johnallsopp/113596871807715709&quot;&gt;John Allsopp shared a new website&lt;/a&gt; where folks can find all available &quot;A Book Apart&quot; books online, &lt;a href=&quot;https://authors-together.org/&quot;&gt;&lt;em&gt;Authors Together&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Migrating your guestbook from Astro Studio</title><link>https://ryantrimble.com/blog/migrating-your-guestbook/</link><guid isPermaLink="true">https://ryantrimble.com/blog/migrating-your-guestbook/</guid><description>Astro Studio is shutting down, time to migrate to a new database.</description><pubDate>Mon, 02 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Back in March, I wrote an article about &lt;a href=&quot;http://ryantrimble.com/blog/creating-a-guestbook-with-astro-db&quot;&gt;creating a guestbook with Astro DB&lt;/a&gt;, which is still a fairly popular article!&lt;/p&gt;
&lt;p&gt;Astro DB is a libSQL database you can use within your Astro projects, to make development with a database super easy.&lt;/p&gt;
&lt;p&gt;You still need to have a hosted libSQL database for production, so Astro themselves had released a service called &lt;a href=&quot;https://studio.astro.build/&quot;&gt;Astro Studio&lt;/a&gt;. Not long after that, Astro decided to &lt;a href=&quot;https://astro.build/blog/goodbye-astro-studio/&quot;&gt;shut down Astro Studio&lt;/a&gt; in September the same year.&lt;/p&gt;
&lt;p&gt;I used Astro Studio in my article, so as it&apos;s shutting down, now might be the time to talk about how to migrate to a different service.&lt;/p&gt;
&lt;h2&gt;Exporting the data&lt;/h2&gt;
&lt;p&gt;If you previously used Astro Studio, you can still log in using your GitHub login at:&lt;/p&gt;
&lt;p&gt;https://studio.astro.build/&lt;/p&gt;
&lt;p&gt;Once logged in, select the project you&apos;d like to export. In the project dashboard, choose &lt;strong&gt;Settings&lt;/strong&gt;, then on the &lt;em&gt;General&lt;/em&gt; page, click &lt;strong&gt;Export Database&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This will export as a &lt;code&gt;.sql&lt;/code&gt; file. This is nice if you decide to use another SQL database, as you can typically import the table directly into the database.&lt;/p&gt;
&lt;p&gt;I&apos;ve decided to try out a different database service that I haven&apos;t used before, &lt;a href=&quot;https://www.convex.dev/&quot;&gt;Convex&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Converting to JSON&lt;/h2&gt;
&lt;p&gt;Convex is not a SQL database, instead more closely resembles &lt;a href=&quot;https://firebase.com/&quot;&gt;Firebase&lt;/a&gt; (from what I can tell), as it uses &quot;JSON-like documents&quot; as it&apos;s database. Easy enough!&lt;/p&gt;
&lt;p&gt;First thing though, we need to convert that data from SQL to JSON.&lt;/p&gt;
&lt;p&gt;Not an easy conversion and typically something I would probaby do manually, instead let&apos;s make AI do the things I don&apos;t want to do, and toss it to ChatGPT.&lt;/p&gt;
&lt;p&gt;Surprisingly, ChatGPT understood exactly what I was asking and provided a mostly complete, JSON formatted data structure. I had to prompt it three times total to get the entire output, but it got there! Your mileage may vary!&lt;/p&gt;
&lt;h2&gt;Setting up Convex&lt;/h2&gt;
&lt;p&gt;Once logged into Convex, I set up a new project called &quot;guestbook&quot; and created a similarly named table on the database.&lt;/p&gt;
&lt;p&gt;Here I selected &lt;strong&gt;Add Documents&lt;/strong&gt;, where I could paste in my JSON to import the data. ChatGPT must have did alright with the conversion, as I now had all my former guestbook data in a Convex database. I got a little confused at first, realizing that I only added the data to the &lt;code&gt;development&lt;/code&gt; database - make sure to include it in &lt;code&gt;production&lt;/code&gt; as well.&lt;/p&gt;
&lt;h2&gt;Integrating into Astro&lt;/h2&gt;
&lt;p&gt;Part of the intention for the &lt;a href=&quot;https://ryantrimble.com/blog/the-hd-remaster&quot;&gt;HD remaster&lt;/a&gt; of my website was to bring in some of my projects, so I had planned on adding the guestbook here at some point. I needed to recreate the functionality of reading and writing to the guestbook, however there isn&apos;t a Convex + Astro integration as far as I can tell. We can still accomplish our goal though, and take a look at &lt;a href=&quot;https://docs.astro.build/en/guides/actions/&quot;&gt;Astro Actions&lt;/a&gt; in the process.&lt;/p&gt;
&lt;h3&gt;Convex API&lt;/h3&gt;
&lt;p&gt;First thing to do is read the data and output the entries on an Astro page.&lt;/p&gt;
&lt;p&gt;The Convex package can be installed by running:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install convex
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To initialize Convex, next run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx convex dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will prompt to create a new project or connect to an existing project, I connected to the project I already set up in the Convex dashboard.&lt;/p&gt;
&lt;p&gt;After connecting to the database, Convex will create a &lt;code&gt;/convex/&lt;/code&gt; directory with some generated files inside. This is where we can work on building an API to interact with the database.&lt;/p&gt;
&lt;p&gt;I created a file called &lt;code&gt;entries.js&lt;/code&gt; as I want to work with guestbook &lt;em&gt;entries&lt;/em&gt;. We need to import a couple of things from our Convex installation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { query } from &apos;./_generated/server&apos;;
import { v } from &apos;convex/values&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;query&lt;/code&gt; is the method used to query the database.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;v&lt;/code&gt; is a validator tool, used to make sure data passed in is typed correctly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we can define a &lt;code&gt;get&lt;/code&gt; function that queries the database and returns all items from the &lt;code&gt;guestbook&lt;/code&gt; table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { query } from &apos;./_generated/server&apos;;
import { v } from &apos;convex/values&apos;;

export const get = query({
  // No arguments necessary here
  args: {},

  // handler is the function run
  // when accessing the GET endpoint
  handler: async ctx =&amp;gt; {
    // In context, we can query the `guestbook`
    // table and retrieve all entries
    return await ctx.db.query(&apos;guestbook&apos;).collect();
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, to use the API!&lt;/p&gt;
&lt;p&gt;I created a new file called &lt;code&gt;pages/experiments/guestbook.astro&lt;/code&gt; and imported the &lt;code&gt;ConvexHTTPClient&lt;/code&gt;, as well as the generated &lt;code&gt;api&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../../convex/_generated/api&apos;;
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;CONVEX_URL&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file will be used to instantiate a new instance of the &lt;code&gt;ConvexHTTPClient&lt;/code&gt;, to interact with the database from the component.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../../convex/_generated/api&apos;;

const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using &lt;code&gt;client&lt;/code&gt;, we can now query using the generated API endpoint &lt;code&gt;api.entries.get&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../../convex/_generated/api&apos;;

const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);
const entries = await client.query(api.entries.get);
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns all the entries in the &lt;code&gt;guestbook&lt;/code&gt; table and can now be rendered in the template.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../../convex/_generated/api&apos;;

const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);
const entries = await client.query(api.entries.get);
---

{
  entries.length &amp;amp;&amp;amp; entries.map(entry =&amp;gt; (
    //...Template
  ))
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Astro Actions&lt;/h3&gt;
&lt;p&gt;Ok, so now the entries are displaying on the page - what about &lt;em&gt;writing&lt;/em&gt; to the guestbook?&lt;/p&gt;
&lt;p&gt;We could probably use like a React or Vue component to do this, however Astro has a neat feature for those using server side rendering: Actions.&lt;/p&gt;
&lt;p&gt;Actions are a way to run functions server-side, so the idea here is to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fill out a form and submit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST&lt;/code&gt; the form data to a server action to handle&lt;/li&gt;
&lt;li&gt;The action submits the data to the Convex database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To create an Astro action, we need to create an &lt;code&gt;/actions&lt;/code&gt; folder and include an &lt;code&gt;index.ts&lt;/code&gt; (I&apos;m sure this could be a &lt;code&gt;.js&lt;/code&gt; file instead, I just &lt;a href=&quot;https://docs.astro.build/en/guides/actions/#basic-usage&quot;&gt;followed the docs&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;We&apos;ll add some tools from Astro:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;defineAction&lt;/code&gt; - let&apos;s us, well, define actions&lt;/li&gt;
&lt;li&gt;&lt;code&gt;z&lt;/code&gt; - Astro&apos;s type validator of choice, &lt;a href=&quot;https://zod.dev/&quot;&gt;Zod&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Actions work by defining them in a &lt;code&gt;server&lt;/code&gt; object, each action will have a unique property associated with it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    //...
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To set the type of data the action will accept, we can set the &lt;code&gt;accept&lt;/code&gt; property to &lt;code&gt;&apos;form&apos;&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    accept: &apos;form&apos;
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;input&lt;/code&gt; property is used to specify the data passed through the action. We can use &lt;code&gt;z&lt;/code&gt; to specify Zod type validations.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      message: z.string()
    })
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, to make the action do something, let&apos;s add a &lt;code&gt;handler&lt;/code&gt; property, which let&apos;s us do something with the &lt;code&gt;input&lt;/code&gt; data.&lt;/p&gt;
&lt;p&gt;We will want this to be an asynchronous function as we will be making a call to our Convex API to &lt;code&gt;insert&lt;/code&gt; data.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      message: z.string()
    }),
    handler: async (input) =&amp;gt; {
      // Do something! but... what?
    }
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The action is now in place, but it still doesn&apos;t quite do anything yet - let&apos;s fix that.&lt;/p&gt;
&lt;p&gt;The Convex API currently only has one endpoint, the previously created &lt;code&gt;query&lt;/code&gt;. Convex provides a method for creating &lt;code&gt;mutations&lt;/code&gt;, enabling data to change - including inserting data to our database.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Previously created query
export const get = query({
  args: {},
  handler: async ctx =&amp;gt; {
    return await ctx.db.query(&apos;guestbook&apos;).collect();
  },
});

// New mutation endpoint
export const createEntry = mutation({
  //...
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&apos;ve called this function &lt;code&gt;createEntry&lt;/code&gt; as it will be used to create a new entry in the database. Similar to our &lt;code&gt;get&lt;/code&gt; query function, arguments can be included - this time we want to receive the same items accepted by our Astro action.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Previously created query
export const get = query({
  args: {},
  handler: async ctx =&amp;gt; {
    return await ctx.db.query(&apos;guestbook&apos;).collect();
  },
});

// New mutation endpoint
export const createEntry = mutation({
  args: {
    name: v.string(),
    message: v.string(),
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, like our Astro action, let&apos;s add a handler to &lt;em&gt;do something&lt;/em&gt; with the data. What that something is: &lt;code&gt;insert&lt;/code&gt; data into the &lt;code&gt;guestbook&lt;/code&gt; table.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Previously created query
export const get = query({
  args: {},
  handler: async ctx =&amp;gt; {
    return await ctx.db.query(&apos;guestbook&apos;).collect();
  },
});

// New mutation endpoint
export const createEntry = mutation({
  args: {
    name: v.string(),
    message: v.string(),
  },
  handler: async (ctx, args) =&amp;gt; {
    return await ctx.db.insert(&apos;guestbook&apos;, {
      name: args.name,
      message: args.message,
    });
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, back in our &lt;code&gt;/actions/index.ts&lt;/code&gt; file, we can import and instantiate a new &lt;code&gt;ConvexHTTPClient&lt;/code&gt;, as well as import the generated API.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../convex/_generated/api&apos;;

// Instantiate ConvexHTTPClient using the `CONVEX_URL`
// in the `.env` file
const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      message: z.string()
    }),
    handler: async (input) =&amp;gt; {
      // Do something! but... what?
    }
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, inside the &lt;code&gt;handler&lt;/code&gt; we can use the &lt;code&gt;client&lt;/code&gt;&apos;s &lt;code&gt;mutate()&lt;/code&gt; method to run a Convex mutation. The first parameter is the mutation to run, found on the generated API: &lt;code&gt;api.entries.createEntry&lt;/code&gt;. The second parameter is the data to submit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../convex/_generated/api&apos;;

// Instantiate ConvexHTTPClient using the `CONVEX_URL`
// in the `.env` file
const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);

export const server = {
  // Defining a `guestbook` action
  guestbook: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      message: z.string()
    }),
    handler: async (input) =&amp;gt; {
      return await client.mutation(
        // Mutation defined in `/convex/entries.js`
        api.entries.createEntry,
        // Data to submit
        { name: input.name, message: input.message }
      );
    }
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, let&apos;s add a form to our Astro page and a script to trigger the Astro action when the form is submitted.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
// guestbook.astro
---

&amp;lt;form method=&quot;POST&quot; id=&quot;guestbook-form&quot;&amp;gt;
  &amp;lt;label for=&quot;author&quot;&amp;gt;
    Author
    &amp;lt;input id=&quot;author&quot; name=&quot;name&quot; required /&amp;gt;
  &amp;lt;/label&amp;gt;
  &amp;lt;label for=&quot;content&quot;&amp;gt;
    Message
    &amp;lt;textarea id=&quot;content&quot; name=&quot;message&quot; required&amp;gt;&amp;lt;/textarea&amp;gt;
  &amp;lt;/label&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;button type=&quot;submit&quot;&amp;gt;Leave your mark&amp;lt;/button&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/form&amp;gt;

&amp;lt;script&amp;gt;
  // Import Astro actions
  import { actions } from &apos;astro:actions&apos;;
  import { navigate } from &apos;astro:transitions/client&apos;;

  const form = document.querySelector(&apos;#guestbook-form&apos;);

  form?.addEventListener(&apos;submit&apos;, async event =&amp;gt; {
    event.preventDefault();

    // Capture form data
    const formData = new FormData(form);

    // Trigger the Astro action
    const { error } = await actions.guestbook(formData);

    // If no errors, we can refresh the page
    if (!error) navigate(&apos;/experiments/guestbook&apos;);
  });
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Including Akismet&lt;/h3&gt;
&lt;p&gt;In my previous article, I explain a bit on &lt;a href=&quot;https://ryantrimble.com/blog/creating-a-guestbook-with-astro-db#akismet-api&quot;&gt;how to add Akismet&lt;/a&gt; so that the guestbook does not receive unsolicited spam. The same thing can be done here!&lt;/p&gt;
&lt;p&gt;Here is the full file, including the code to implement Akismet:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineAction } from &apos;astro:actions&apos;;
import { z } from &apos;astro:schema&apos;;
import { ConvexHttpClient } from &apos;convex/browser&apos;;
import { api } from &apos;../../convex/_generated/api&apos;;
import { Blog, Client, Comment, Author, CheckResult } from &apos;@cedx/akismet&apos;;

const client = new ConvexHttpClient(import.meta.env.CONVEX_URL);

export const server = {
  guestbook: defineAction({
    accept: &apos;form&apos;,
    input: z.object({
      name: z.string(),
      message: z.string(),
    }),
    handler: async function (input) {
      let isValid;
      const blog = new Blog({ url: &apos;https://ryantrimble.com/&apos; });
      const akismet = new Client(import.meta.env.AKISMET_TOKEN, blog);

      try {
        isValid = await akismet.verifyKey();
      } catch (error) {
        return error;
      }

      if (isValid) {
        if (typeof input.name === &apos;string&apos; &amp;amp;&amp;amp; typeof input.message === &apos;string&apos;) {
          try {
            let author = new Author({
              name: input.name,
            });

            let comment = new Comment({
              author: author,
              content: input.message,
            });

            const result = await akismet.checkComment(comment);

            if (result === CheckResult.ham) {
              return await client.mutation(api.entries.createEntry, {
                name: input.name,
                message: input.message,
              });
            } else {
              throw new Error(&apos;This entry has not been submitted.&apos;);
            }
          } catch (error) {
            return error;
          }
        }
      }
    },
  }),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;Although unfortunate to see Astro Studio shutting down, it&apos;s easy enough to migrate our data to another service. Feel free to leave a message on the new &lt;a href=&quot;https://ryantrimble.com/guestbook&quot;&gt;guestbook&lt;/a&gt;, located here on my site!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #31</title><link>https://ryantrimble.com/blog/weekly-roundup-31/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-31/</guid><description>Black Friday Truck-a-thon sales event kicks off now through the holidays!</description><pubDate>Sat, 30 Nov 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://bsky.social/about/blog/11-29-2024-engagement&quot;&gt;The engagement is better on Bluesky&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://bsky.social/about/blog/&quot;&gt;The Bluesky Team&lt;/a&gt; on 11/29/2024&lt;/p&gt;
&lt;p&gt;The folks over at Bluesky released this post giving testimonials from several accounts claiming engagement is higher on the growing social network. My personal testimonial is that I have over 2,000 followers for some reasons, way more than ANY other platform.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://bell.bz/i-wrote-a-course-but-its-so-much-more-than-that/&quot;&gt;I wrote a course, but it&apos;s so much more than that&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt; on 11/29/2024&lt;/p&gt;
&lt;p&gt;Andy released a course this week (see &quot;&lt;a href=&quot;#cool-courses&quot;&gt;Cool Courses&lt;/a&gt;&quot;), here is a personal write up from him explaining the whats and whys. Don&apos;t worry, I already checked and there are no Rick-rolls.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://hidde.blog/please-make-ai-opt-in/&quot;&gt;Turn off AI features by default (to reduce their climate impact)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://hidde.blog/&quot;&gt;Hidde de Vries&lt;/a&gt; on 11/29/2024&lt;/p&gt;
&lt;p&gt;Excellent reminder from Hidde that if you aren&apos;t using AI features, consider opting-out of using them totally to help conserve energy. This feels like the digital version of recycling for some reason.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://cassidoo.co/post/side-project-haunting/&quot;&gt;Haunted by my own projects&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://cassidoo.co/&quot;&gt;Cassidy Williams&lt;/a&gt; on 11/26/2024&lt;/p&gt;
&lt;p&gt;Cassidy shares a familiar feeling for folks who build things, maintaining side-projects becoming a chore. I sometimes feel this way, but then realize no one really uses any of my side projects.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.wrecka.ge/against-the-dark-forest/&quot;&gt;Against the Dark Forest&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.wrecka.ge/&quot;&gt;Erin Kissane&lt;/a&gt; on 11/26/2024&lt;/p&gt;
&lt;p&gt;Erin continues her work exploring the &lt;em&gt;Dark Internet Forest&lt;/em&gt;, what it is and how it came to be. Fascinating read.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://danielmangum.com/posts/this-website-is-hosted-on-bluesky/&quot;&gt;This website is hosted on Bluesky&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://danielmangum.com/&quot;&gt;Daniel Mangum&lt;/a&gt; on 11/24/2024&lt;/p&gt;
&lt;p&gt;Daniel (no relation to &lt;a href=&quot;https://en.wikipedia.org/wiki/Jeff_Mangum&quot;&gt;Jeff&lt;/a&gt;) takes a look at the AT Protocol, discovering how to upload and host a web page. And here I thought Bluesky was just for shitposting.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Courses&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://complete-css.com/&quot;&gt;Complete CSS&lt;/a&gt; - I pre-ordered this and have been eagerly awaiting release. I haven&apos;t dug into it quite yet, but I looked through the list of lessons and it&apos;s (excitingly) &lt;em&gt;much more&lt;/em&gt; than I expected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Over on CSS-Tricks, I wrote a &lt;a href=&quot;https://css-tricks.com/follow-up-we-officially-have-a-css-logo/&quot;&gt;follow up post&lt;/a&gt; now that we officially have a new CSS logo!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vite.dev/blog/announcing-vite6&quot;&gt;Vite 6.0&lt;/a&gt; has been released, somehow it&apos;s even faster than before (which is crazy).&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #30</title><link>https://ryantrimble.com/blog/weekly-roundup-30/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-30/</guid><description>Celebrating 30 years of Weekly Roundups.</description><pubDate>Sat, 23 Nov 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I can&apos;t believe Thanksgiving is next week. I hope everyone has a wonderful time doing whatever it is you do, whether you celebrate the holiday with friends and family or don&apos;t celebrate at all.&lt;/p&gt;
&lt;p&gt;This month has been &lt;em&gt;crazy&lt;/em&gt; busy for me. I&apos;ve got some great updates to share soon!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://webkit.org/blog/16214/background-clip-border-area/&quot;&gt;Make creative borders with background-clip border-area&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jensimmons.com/&quot;&gt;Jen Simmons&lt;/a&gt; on 11/20/2024&lt;/p&gt;
&lt;p&gt;Safari&apos;s latest technology preview is out and Jen is here to demo an incredibly useful feature: adding a background to a border with &lt;code&gt;background-clip: border-area&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://jeremias.codes/2024/11/you-should-write-modern-css-today/&quot;&gt;You should write modern CSS, today&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jeremias.codes/&quot;&gt;Jeremias Menichelli&lt;/a&gt; on 11/20/2024&lt;/p&gt;
&lt;p&gt;This is a sentiment I can always get behind, Jeremias gives straightforward examples of some of the best modern features of CSS. I&apos;ve gotta look into that &lt;code&gt;@custom-media&lt;/code&gt; feature...&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://polypane.app/blog/the-devtools-features-you-wish-you-had-available-in-polypane/&quot;&gt;The devtools features you wish you had, available in Polypane&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://polypane.app/&quot;&gt;Kilian Valkhof&lt;/a&gt; on 11/19/2024&lt;/p&gt;
&lt;p&gt;I promise I don&apos;t get paid to keep touting Polypane, it&apos;s just that great. Kilian provides a great response, listing out the features you wish you had elsewhere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://alvaromontoro.com/blog/68044/playing-with-the-gamepad-api&quot;&gt;Playing with the Gamepad API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://alvaromontoro.com/&quot;&gt;Alvaro Montoro&lt;/a&gt; on 10/24/2024&lt;/p&gt;
&lt;p&gt;Neat write up on how to a surprisingly well-supported experimental API by Alvaro, now folks can &lt;em&gt;really&lt;/em&gt; add a &quot;Konami code&quot; easter egg to their sites.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://medienbaecker.com/articles/focus-outlines&quot;&gt;Beautiful focus outlines&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://medienbaecker.com/&quot;&gt;Thomas Günther&lt;/a&gt; on 5/11/2024&lt;/p&gt;
&lt;p&gt;Thomas gives a GREAT recommendation here, designing with usability considerations (such as focus rings) can be fun and helpful to folks that need it. Check out the outlines on my site, for example!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;p&gt;I love seeing the fun stuff folks are making with Bluesky integrations, reminiscent of the weird ol&apos; days.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bsky.app/profile/frontend.irish/post/3lbl4bl775s24&quot;&gt;a:\drian&lt;/a&gt; created a fantastic &lt;a href=&quot;https://bluesky-user-search.netlify.app/&quot;&gt;Bluesky user search tool&lt;/a&gt; (and even included me in the screenshot).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Meanwhile, &lt;a href=&quot;https://bsky.app/profile/bagpuss.org/post/3lbevpfmbis2a&quot;&gt;Dave Bagpuss Forsey&lt;/a&gt; built this hilarious &lt;a href=&quot;https://swearsky.bagpuss.org/&quot;&gt;SwearSky&lt;/a&gt; app that reads all the swears.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;United States Department of Justice wants Google to &lt;a href=&quot;https://www.theverge.com/2024/11/20/24300617/doj-google-search-antitrust-chrome-breakup&quot;&gt;sell Chrome&lt;/a&gt;. This feels odd, I&apos;m not quite sure who else could maintain Chrome at this point.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #29</title><link>https://ryantrimble.com/blog/weekly-roundup-29/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-29/</guid><description>Are these getting too long or are there just too many great articles to talk about?</description><pubDate>Sat, 16 Nov 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://hirok.io/posts/node-exports-guide&quot;&gt;Guide to the Node.js exports field&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://hirok.io/&quot;&gt;Hiroki Osame&lt;/a&gt; on 10/15/2024&lt;/p&gt;
&lt;p&gt;Hiroki shared this super helpful guide explaining what the export field does in your &lt;code&gt;package.json&lt;/code&gt; file. If you are making node packages, you probably want to know how this works (I usually just wing it).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://fluffyandflakey.blog/2024/11/14/five-common-html-myths/&quot;&gt;Six Common HTML Myths&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://fluffyandflakey.blog/2024/11/14/five-common-html-myths/&quot;&gt;Dennis Snell&lt;/a&gt; on 10/14/2024&lt;/p&gt;
&lt;p&gt;Dennis points out all the ways I&apos;ve been writing HTML incorrectly all this time. A great reminder that some of the habits from the old days are no longer necessary!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ethanmarcotte.com/wrote/books-no-longer-apart/&quot;&gt;Two books, no longer apart.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ethanmarcotte.com/&quot;&gt;Ethan Marcotte&lt;/a&gt; on 11/12/2024&lt;/p&gt;
&lt;p&gt;Ethan made two of best resources for responsive design free for everyone. You may remember earlier this year, &lt;a href=&quot;http://ryantrimble.com/blog/a-book-apart-books&quot;&gt;A Book Apart closed up shop&lt;/a&gt;, leaving authors scrambling to figure out what to do with their books. Thanks Ethan, for making these important pieces accessible to everyone!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://heather-buchel.com/blog/2024/11/carving-space/&quot;&gt;Carving your space&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://heather-buchel.com/&quot;&gt;Heather Buchel&lt;/a&gt; on 11/12/2024&lt;/p&gt;
&lt;p&gt;I&apos;m in a very similar place as Heather and this was helpful to read. The things I care about are rarely the things companies hire for, sometimes leaving me wondering if I&apos;m in the correct field. Heather is correct though, these things are important - even if you have to carve out the space to do it yourself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://motion.dev/blog/framer-motion-is-now-independent-introducing-motion&quot;&gt;Framer Motion is now independent, introducing Motion&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://motion.dev/&quot;&gt;Matt Perry&lt;/a&gt; on 11/12/2024&lt;/p&gt;
&lt;p&gt;Another shake up in the world of animation libraries as &lt;a href=&quot;https://motion.dev/&quot;&gt;Motion&lt;/a&gt; becomes independent from Framer! Congrats Matt on the achievement!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-br-element/&quot;&gt;The br element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on 11/12/2024&lt;/p&gt;
&lt;p&gt;Heydon makes up for skipping the &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; element, but in defense, I don&apos;t like this element very much either. It&apos;s one of those icky things, if I find myself reaching for &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt;, I&apos;ll question if there is an alternate approach.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/overflow-clip/&quot;&gt;Overflow Clip&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on 11/11/2024&lt;/p&gt;
&lt;p&gt;Ahmad&apos;s interactive articles are incredible and help explain so much, I always learn something! This time I was aware of &lt;code&gt;overflow: clip&lt;/code&gt;, but I did &lt;em&gt;not&lt;/em&gt; know about &lt;code&gt;overflow-clip-margin&lt;/code&gt; which is a super helpful addition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ericwbailey.website/published/dont-forget-to-localize-your-icons/&quot;&gt;Don&apos;t forget to localize your icons&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ericwbailey.website/&quot;&gt;Eric Bailey&lt;/a&gt; on 11/11/2024&lt;/p&gt;
&lt;p&gt;I haven&apos;t had the opportunity to work much with internationalization, but this is absolutely something I would have never thought to do! Luckily Eric has us covered, excellent explanations, and a great reference.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://tylersticka.com/journal/browsers-again/&quot;&gt;Browsers, Again&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://tylersticka.com/&quot;&gt;Tyler Sticka&lt;/a&gt; on 11/11/2024&lt;/p&gt;
&lt;p&gt;Why is finding a browser so hard? Tyler documents his latest switch to &lt;a href=&quot;https://vivaldi.com/&quot;&gt;Vivaldi&lt;/a&gt;. I&apos;m also trying to find a daily-driver and have been trying Vivaldi, but am overwhelmed by &lt;em&gt;how much&lt;/em&gt; you can customize (however not the things I &lt;em&gt;want&lt;/em&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.joshwcomeau.com/css/container-queries-introduction/&quot;&gt;A Friendly Introduction to Container Queries&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.joshwcomeau.com/&quot;&gt;Josh W. Comeau&lt;/a&gt; on 11/4/2024&lt;/p&gt;
&lt;p&gt;I&apos; ha&apos;ve often thought of writing an &lt;em&gt;un&lt;/em&gt;friendly introduction to container queries, thankfully Josh is kind enough to cover the friendly version. Everyone, with peace and love: use container queries!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.eff.org/deeplinks/2024/06/disability-rights-are-technology-rights&quot;&gt;Disability Rights Are Technology Rights&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.eff.org/about/staff/cory-doctorow&quot;&gt;Cory Doctorow&lt;/a&gt; on 10/24/2024&lt;/p&gt;
&lt;p&gt;Cory from the &lt;a href=&quot;https://www.eff.org/&quot;&gt;Electronic Frontier Foundation&lt;/a&gt; explains what technological self-determination is and the benefits for folks who may require assistive technologies.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.star-shaped.org/&quot;&gt;Aubrey&lt;/a&gt; shared a recording of her &lt;a href=&quot;https://www.drupalasheville.com/2024/session/color-css-using-new-spaces-functions-and-techniques-make-your-site-shine&quot;&gt;talk on color in CSS&lt;/a&gt; from &lt;a href=&quot;https://www.drupalasheville.com/&quot;&gt;Drupal Asheville&lt;/a&gt; over in the Frontend Horse Discord community!&lt;/li&gt;
&lt;li&gt;For even more information on color in CSS, &lt;a href=&quot;https://www.matuzo.at/&quot;&gt;Manuel Matuzović&lt;/a&gt;&apos;s &lt;a href=&quot;https://www.youtube.com/watch?v=9UyJe22WH58&quot;&gt;recorded talk from Beyond Tellerrand&lt;/a&gt; is now available!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://11ty.dev/&quot;&gt;11ty&lt;/a&gt; has a fancy new tool to help import all sorts of stuff: &lt;a href=&quot;https://github.com/11ty/eleventy-import&quot;&gt;11ty/eleventy-import&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;One of the few folks I trust for food tips, Lynn Fisher breaks down &lt;a href=&quot;https://lynnandtonicblog.com/2024/11/10/fave-things-i-ate-at-disneyland/&quot;&gt;her favorite things from a recent trip to Disneyland&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://theonion.com/heres-why-i-decided-to-buy-infowars/&quot;&gt;The Onion bought Infowars&lt;/a&gt;, I&apos;m excited to see what America&apos;s finest news source can do with America&apos;s most wretched news source.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #28</title><link>https://ryantrimble.com/blog/weekly-roundup-28/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-28/</guid><description>Yeah, I don&apos;t know what to say, let&apos;s focus on some interesting links this week.</description><pubDate>Sat, 09 Nov 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.joshtumath.uk/posts/2024-11-08-how-a-bbc-navigation-bar-component-broke-depending-on-which-external-monitor-it-was-on/&quot;&gt;How a BBC navigation bar component broke depending on which external monitor it was on&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.joshtumath.uk&quot;&gt;Josh Tumath&lt;/a&gt; on 11/8/2024&lt;/p&gt;
&lt;p&gt;Josh explains an incredibly odd bug they ran into over on the BBC&apos;s UK site involving multiple monitor setups. True story, &lt;em&gt;most&lt;/em&gt; problems we face in Frontend is due to monitors, as such we should work towards abolishing them. Yeah... that&apos;d solve everything.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-11-08-til-bracket-notation-object-declaration/&quot;&gt;TIL: Bracket notation during object declaration&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on 11/8/2024&lt;/p&gt;
&lt;p&gt;Jaime is sharing some wild stuff in her TIL (Today I Learned) series, including this method of using bracket notation in different ways with objects. I told her someday I will come across a use-case for this and happily have a resource for it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://bradfrost.com/blog/post/goodbye-twitter/&quot;&gt;Goodbye, Twitter.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://bradfrost.com/&quot;&gt;Brad Frost&lt;/a&gt; on 11/7/2024&lt;/p&gt;
&lt;p&gt;Brad shares a common sentiment amongst folks who used Twitter to develop their personal networks over the years, it&apos;s an end of an era for sure. This week I watched lots of folks converting to Bluesky, which I hope will fill the Twitter-shaped hole in our lives.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-button-element/&quot;&gt;The button element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on 11/4/2024&lt;/p&gt;
&lt;p&gt;Name a more misunderstood element than a button. Heydon does a great job, in their own way, explaining the history of buttons on the web and what they have become. My rule of thumb is &quot;links take you places, buttons do stuff&quot; which handles like most use cases.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://mayank.co/blog/css-reset-layer/&quot;&gt;Your CSS reset should be layered&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://mayank.co/&quot;&gt;Mayank&lt;/a&gt; on 11/2/2024&lt;/p&gt;
&lt;p&gt;I agree with Mayank&apos;s title, didn&apos;t even need to write the article. However, if you need convincing, you will learn why reading this. Also, checkout Mayank&apos;s &lt;code&gt;@acab/reset.css&lt;/code&gt; which I tend to use on personal projects (such as this website!).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://blog.stephaniestimac.com/posts/2024/10/html-details-and-summary-update/&quot;&gt;The details and summary elements are getting an upgrade&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://blog.stephaniestimac.com&quot;&gt;Stephanie Stimac&lt;/a&gt; on 11/1/2024&lt;/p&gt;
&lt;p&gt;Stephanie explains current issues when styling the &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt; elements and some proposed changes coming to help customization easier. As someone who constantly judges himself using these elements, I&apos;m excited to know if I should be using them or not.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.aleksandrhovhannisyan.com/blog/introduction-to-unicode/&quot;&gt;An Introduction to Unicode&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.aleksandrhovhannisyan.com&quot;&gt;Aleksandr Hovhannisyan&lt;/a&gt; on 7/28/2024&lt;/p&gt;
&lt;p&gt;This was shared recently on the Frontend Horse Discord and it&apos;s a &lt;em&gt;fantastic&lt;/em&gt; resource explaining how unicode works!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Beyond Tellerrand 2024 was this week, Hidde de Vries and &lt;a href=&quot;https://www.matuzo.at&quot;&gt;Manuel Matuzović&lt;/a&gt; &lt;a href=&quot;https://noti.st/events/PxHd6S/beyond-tellerrand&quot;&gt;shared their slides&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Chris Coyier released a written version of his conference talk &lt;a href=&quot;https://chriscoyier.net/2024/11/07/designing-dx/&quot;&gt;Designing DX&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I was SUPER excited for this one when it came through the CSS-Tricks submission desk, check out how you can use &lt;code&gt;clamp&lt;/code&gt; on other things, in &lt;a href=&quot;https://css-tricks.com/fluid-everything-else/&quot;&gt;Fluid Everything Else&lt;/a&gt; by &lt;a href=&quot;https://css-tricks.com/author/richardhubbard/&quot;&gt;Richard Hubbard&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Adam shares one of those &quot;why didn&apos;t I think of that&quot;-type tricks by matching &lt;code&gt;aspect-ratio&lt;/code&gt; based on the &lt;a href=&quot;https://nerdy.dev/matching-aspects&quot;&gt;orientation of the device&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The nightmare continues, Donald Trump won the U.S. Election this week. I have no words. Luckily Ken White had some in his article &quot;&lt;a href=&quot;https://www.popehat.com/p/and-yet-it-moves&quot;&gt;And Yet It Moves&lt;/a&gt;&quot; that sort of helps.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #27</title><link>https://ryantrimble.com/blog/weekly-roundup-27/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-27/</guid><description>I don&apos;t need to remind you that the U.S. election is happening on Tuesday, November 5th 2024 — but I&apos;m going to anyway.</description><pubDate>Sat, 02 Nov 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This past week I went to see Kamala Harris speak at the Farm Show complex in Harrisburg, PA! I&apos;ve never been to a political rally before, but this year is a bit different.&lt;/p&gt;
&lt;p&gt;In case you somehow missed it, Kamala is running for President of the United States in one of the most concerning U.S. Presidential elections I&apos;ve experienced in my thirty-odd rotations around the sun.&lt;/p&gt;
&lt;p&gt;Also, if you really somehow missed this: &lt;em&gt;please&lt;/em&gt;, I urge you to pay more attention, how could you have missed this, they are texting every god damned hour.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For my U.S. readers:&lt;/strong&gt; if this is the only reminder you see, allow me (your humble curator of interesting links) to proudly urge you to do your civic duty this coming Tuesday:&lt;/p&gt;
&lt;p&gt;&amp;lt;a href=&quot;https://vote.gov/&quot; class=&quot;text-step-5&quot; style=&quot;margin-inline: auto; font-weight: 900;&quot;&amp;gt;
VOTE!!!
&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Over on Bluesky, starter packs seem to be a winning strategy for expanding your network quickly. All of a sudden, I&apos;ve got more followers than I know what to do with!&lt;/p&gt;
&lt;p&gt;I created a starter pack for the &lt;a href=&quot;https://go.bsky.app/TUuRD73&quot;&gt;Frontend Horse community&lt;/a&gt; consisting of guests from the Twitch stream and the awesome frequent contributors in our Discord. These folks are some of the best I know and are totally worth a follow! &lt;a href=&quot;https://piccalil.li/&quot;&gt;Piccalilli&lt;/a&gt;&apos;s starter pack called &lt;a href=&quot;https://go.bsky.app/UUmcHf4&quot;&gt;Welcome to Bluesky, web friends&lt;/a&gt; will help get you going on Bluesky as well.&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-body-element/&quot;&gt;The body element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on 10/31/2024&lt;/p&gt;
&lt;p&gt;Heydon dropped another element explainer, this time talking about the &lt;code&gt;body&lt;/code&gt; element. Luckily, they made sure to spice it up with facts about hammerhead sharks and blobfish.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/state-of-css-2024-results/&quot;&gt;State of CSS 2024 Results&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://css-tricks.com/author/geoffgraham/&quot;&gt;Geoff Graham&lt;/a&gt; on 10/30/2024&lt;/p&gt;
&lt;p&gt;Geoff provides some analysis on interesting bits from the State of CSS 2024 survey. Love to see CSS-Tricks still ranking high!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://polypane.app/blog/clever-polypane-debugging-features-im-loving-by-ryan-trimble/&quot;&gt;Clever Polypane Debugging Features I&apos;m Loving by Ryan Trimble&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://polypane.app/&quot;&gt;Kilian Valkhof&lt;/a&gt; on 10/30/2024&lt;/p&gt;
&lt;p&gt;Kilian wrote an article about an article I wrote on Polypane (the best browser), so now I&apos;m telling you about it. Hell yeah, I&apos;m keeping this meta going. Thanks, Kilian!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/css-grid-masonry/&quot;&gt;Should masonry be part of CSS grid?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on 10/29/2024&lt;/p&gt;
&lt;p&gt;Ahmad explores the options for CSS Masonry with interactive examples. This was super helpful to visualize some use-cases outside of Pinterest.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://bradfrost.com/blog/post/design-system-governance-bugs-design-discrepancies-features-and-recipes/&quot;&gt;The design system isn&apos;t working for me!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://bradfrost.com/&quot;&gt;Brad Frost&lt;/a&gt; on 10/15/2024&lt;/p&gt;
&lt;p&gt;Brad explains situations when the design system may not be working for some and how to communicate changes and decisions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;With the rise in popularity of Bluesky, David Darnes released a web component to easily &lt;a href=&quot;https://darn.es/bluesky-post-web-component/&quot;&gt;embed Bluesky posts&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cnn.com/2024/10/31/tech/google-fines-russia/index.html&quot;&gt;Russia is suing Google for all the money&lt;/a&gt;, websites: make sure your overflows handle all them zeroes.&lt;/li&gt;
&lt;li&gt;Lynn Fisher &lt;a href=&quot;https://lynnandtonicblog.com/2024/10/28/meet-tater/&quot;&gt;introduced us to Tater&lt;/a&gt;, a rescue pup with stunning eyes.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #26</title><link>https://ryantrimble.com/blog/weekly-roundup-26/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-26/</guid><description>A day late and a dollar short, but there is still a lot to talk about this week.</description><pubDate>Sun, 27 Oct 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Apologies for the delay this week, my sister got married yesterday and I ended up being the wedding photographer. Congrats to the newly married couple!&lt;/p&gt;
&lt;p&gt;I&apos;ve got something neat cooking up as I&apos;ve been experimenting with CSS Anchor Positioning for a new article. Anchor positioning might change a lot of the ways we write CSS and feels like a super natural addition. The easiest way to summarize it might be: if &lt;code&gt;position: absolute&lt;/code&gt; did what you expect.&lt;/p&gt;
&lt;p&gt;Super excited to share more details soon!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/come-to-the-light-dark-side/&quot;&gt;Come to the light-dark() Side&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://sarajoy.dev/&quot;&gt;Sara Joy&lt;/a&gt; on 10/25/2024&lt;/p&gt;
&lt;p&gt;Sara explained &lt;a href=&quot;https://conf.11ty.dev/2024/light-mode-versus-dark-mode/&quot;&gt;light mode versus dark mode&lt;/a&gt; at the &lt;a href=&quot;https://conf.11ty.dev/&quot;&gt;11ty conference&lt;/a&gt; back in May, now she&apos;s written the book on it (well, a highly in-depth explainer on CSS-Tricks rather, but let&apos;s be real, she could totally write an actual book if she wanted).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://gomakethings.com/how-to-add-custom-events-to-web-components/&quot;&gt;How to add custom events to Web Components&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on 10/23/2024&lt;/p&gt;
&lt;p&gt;Chris released the final part in his YouTube series about building web apps using only JavaScript web components. This time he demonstrates how to add custom events using &lt;code&gt;emit()&lt;/code&gt; to extend your components even further.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://chadpeters.dev/blog/azure-storage-delete-md5hash&quot;&gt;Delete MD5 Hash from Azure Storage Blob using Azure CLI&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://chadpeters.dev/&quot;&gt;Chad Peters&lt;/a&gt; on 10/23/2024&lt;/p&gt;
&lt;p&gt;If you know Chad, you might be wondering what a post from a backend developer is doing on here. The lesson is universal, however: sometimes it&apos;s best to stop and read the documentation.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://kizu.dev/tree-counting-and-random/&quot;&gt;Possible Future CSS: Tree-Counting Functions and Random Values&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;publihsed by &lt;a href=&quot;https://kizu.dev/&quot;&gt;Roma Komarov&lt;/a&gt; on 10/22/2024&lt;/p&gt;
&lt;p&gt;Once again, Roma is out here breaking minds and prognosticating on the future of CSS. This time explaining the math behind how loops and randomness might work. Do I understand it? Not really. Am I still excited? Absolutely.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-10-21-vue-define-model/&quot;&gt;ELI5: What is defineModel in Vue?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jai.me/blog/2024-10-21-vue-define-model/&quot;&gt;Jaime Jones&lt;/a&gt; on 10/21/2024&lt;/p&gt;
&lt;p&gt;I was stoked when Evan You described &lt;code&gt;defineModel&lt;/code&gt; at the 2023 Vue Conf in New Orleans, however I never got a chance to check it out. Luckily, Jaime is excellent at breaking things down and wrote a whole ELI5 (explain like I&apos;m five) post!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.alwaystwisted.com/articles/creating-design-system-friendly-snowflakes-with-utility-classes&quot;&gt;Creating Design System-Friendly Snowflakes with Utility Classes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://www.alwaystwisted.com/&quot;&gt;Stu Robinson&lt;/a&gt; on 10/21/2024&lt;/p&gt;
&lt;p&gt;Stu shares a perfect example of extending a design system through the use of design tokens. Actually, Stu was on a tear and wrote &lt;em&gt;three&lt;/em&gt; articles explaining tokens this week, be sure to read all of them on his blog!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://daverupert.com/2024/10/super-web-components-sunshine/&quot;&gt;Where web components shine&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://daverupert.com/&quot;&gt;Dave Rupert&lt;/a&gt; on 10/21/2024&lt;/p&gt;
&lt;p&gt;As some folks seem to be confused on when may or may not be the time for a web component, Dave put together a couple lists detailing the good and bad parts. Remember, it&apos;s about using the best tool for the job.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Silvestar Bistrović created a neat VSCode extension called &lt;a href=&quot;https://www.silvestar.codes/articles/clamp-it/&quot;&gt;Clamp It!&lt;/a&gt; that let&apos;s you easily &lt;code&gt;clamp()&lt;/code&gt; values.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In &lt;em&gt;Good&lt;/em&gt; News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;I&apos;m excited to checkout Devon Persing&apos;s new book, &lt;a href=&quot;https://payhip.com/b/OSyLt&quot;&gt;The Accessibility Operations Guidebook&lt;/a&gt;, explaining how best to strategize and create accessibility programs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In &lt;em&gt;Other&lt;/em&gt; News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Matt Mullenweg took down &lt;a href=&quot;https://bullenweg.com/&quot;&gt;bullenweg.com&lt;/a&gt; by threatening legal action. Add hostile censorship to the pile, I guess.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #25</title><link>https://ryantrimble.com/blog/weekly-roundup-25/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-25/</guid><description>Three of the articles this week are about blockquotes, sorry - I added extra to make up for it though.</description><pubDate>Sat, 19 Oct 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Another milestone, I can&apos;t believe my little Roundup is already 25 years old. Or something. Not much to say this week, but a lot of awesome links!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://adhdftw.com/handbook/&quot;&gt;The ADHD Handbook&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on 10/18/2024&lt;/p&gt;
&lt;p&gt;Chris published this last night and it was the first thing I checked out this morning. Great insight as usual, especially as someone trying to navigate ADHD myself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://jakearchibald.com/2024/how-should-selectedoption-work/&quot;&gt;How should &amp;lt;selectedoption&amp;gt; work?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://jakearchibald.com/&quot;&gt;Jake Archibald&lt;/a&gt; on 10/18/2024&lt;/p&gt;
&lt;p&gt;Jake explains the landscape of a customizable &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; elements and is wondering what things to consider for the currently selected option, providing a few scenarios.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://niclake.me/7-9/&quot;&gt;7 == 9&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://niclake.me/&quot;&gt;Nic Lake&lt;/a&gt; on 10/17/2024&lt;/p&gt;
&lt;p&gt;Nic celebrates a recent shift in perspective thanks to an angry therapist. As I read this one, I thought of Harrison Ford in &lt;a href=&quot;https://en.wikipedia.org/wiki/Shrinking_(TV_series)&quot;&gt;Shrinking&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://sarahmhigley.com/writing/activedescendant/&quot;&gt;Aria-activedescendant is not focus&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://sarahmhigley.com/&quot;&gt;Sarah Higley&lt;/a&gt; on 10/16/2024&lt;/p&gt;
&lt;p&gt;Excellent write up by Sarah on what &lt;code&gt;aria-activedescendant&lt;/code&gt; even is and when exactly to use it, love learning about this kind of thing!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://dri.es/my-solar-powered-and-self-hosted-website&quot;&gt;My solar-powered and self-hosted website&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://dri.es/&quot;&gt;Dries Buytaert&lt;/a&gt; on 10/15/2024&lt;/p&gt;
&lt;p&gt;Dries, founder of &lt;a href=&quot;https://www.drupal.org/&quot;&gt;Drupal&lt;/a&gt;, put together a neat &lt;a href=&quot;https://solar.dri.es/&quot;&gt;solar-powered website&lt;/a&gt;, which is way more interesting than whatever Matt Mullenweg is doing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-irl.info/ive-been-doing-blockquotes-wrong/&quot;&gt;I&apos;ve Been Doing Blockquotes Wrong&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://css-irl.info/&quot;&gt;Michelle Barker&lt;/a&gt; on 10/16/2024&lt;/p&gt;
&lt;p&gt;This week everyone collectively realized we have been using blockquotes incorrectly this whole time. Michelle reacts to Heydon&apos;s latest article... speaking of which...&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-blockquote-element/&quot;&gt;The blockquote element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on 10/14/2024&lt;/p&gt;
&lt;p&gt;Heydon points out how one of the most boring HTML elements is actually super confusing, while kindly providing semantically correct alternatives. Kudos!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://adrianroselli.com/2023/07/blockquotes-in-screen-readers.html&quot;&gt;Blockquotes in Screen Readers&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;updated by &lt;a href=&quot;https://adrianroselli.com/&quot;&gt;Adrian Roselli&lt;/a&gt; on 10/14/2024&lt;/p&gt;
&lt;p&gt;Following the discussion on blockquotes further, Adrian shared a post from 2023, providing test scenarios for various patterns for screen readers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h3&gt;&lt;a href=&quot;https://robinrendle.com/notes/hire-html-people/&quot;&gt;Hire HTML and CSS people&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;published by &lt;a href=&quot;https://robinrendle.com/&quot;&gt;Robin Rendle&lt;/a&gt; on 9/21/2024&lt;/p&gt;
&lt;p&gt;Just a straightforward reminder from Robin that bugs and issues stem from not understanding the basics, HTML and CSS.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Chris Swithinbank has a new project aimed at bringing WordPress data into Astro, called &lt;a href=&quot;https://delucis.github.io/dewp/&quot;&gt;DeWP&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GSAP and Webflow are joining! I wrote about it &lt;a href=&quot;https://css-tricks.com/combining-forces-gsap-webflow/&quot;&gt;over on CSS-Tricks&lt;/a&gt;, but check out the &lt;a href=&quot;https://gsap.com/blog/webflow-GSAP/&quot;&gt;official announcement&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;𝕏 (the hellscape formerly known as Twitter) continues to freefall from public favor by introducing another dumb &quot;enhancement&quot; to make &lt;a href=&quot;https://x.com/XEng/status/1846605254864888180&quot;&gt;blocking accounts pointless&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Melanie Sumner shared their &lt;a href=&quot;https://noti.st/melsumner/7dgask/slides&quot;&gt;presentation slides&lt;/a&gt; from &lt;a href=&quot;https://emberfest.eu/&quot;&gt;EmberFest 2024&lt;/a&gt; taking a look at harmful, yet common, user-interface patterns.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #24</title><link>https://ryantrimble.com/blog/weekly-roundup-24/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-24/</guid><description>Lots of great links this week and oh, would you look at that, HTML is for people now.</description><pubDate>Sat, 12 Oct 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My personal developer &quot;sweet spot&quot; is the nexus of converting design to code for implementation, which is why I&apos;m a big fan of design systems. These types of roles seem to be much harder to come by, unfortunately, so I&apos;m left figuring out what to do next with my career.&lt;/p&gt;
&lt;p&gt;I feel the need to pivot into one of two directions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User Interface Designer (&lt;em&gt;no&lt;/em&gt; code) - these are the folks digging into Figma, making mockups and prototypes rather than scaffolding out some HTML.&lt;/li&gt;
&lt;li&gt;Fullstack Developer (&lt;em&gt;more&lt;/em&gt; code) - the one who can do it all, getting their hands dirty in the backend and the frontend.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem is that I&apos;m interested in design &lt;em&gt;and&lt;/em&gt; I enjoy coding and these companies only seem to want one or the other.&lt;/p&gt;
&lt;p&gt;So I&apos;m a little lost.&lt;/p&gt;
&lt;p&gt;I asked Mastodon if there were any good courses for design specifically, no coding involved, and, while I received a number of likes and shares (indicating this might be something more folks are interested in), only a couple of actual suggestions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mstdn.social/@bartekhejnowicz/113289299573342100&quot;&gt;bartekhejnowicz&lt;/a&gt; recommended &lt;a href=&quot;https://uxcel.com/&quot;&gt;Uxcel&lt;/a&gt; as a great way to learn UI/UX design.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vickerson.me/@josh/113289517558998708&quot;&gt;Josh &quot;Yoshi&quot; Vickerson&lt;/a&gt; reminded me of &quot;&lt;a href=&quot;https://www.refactoringui.com/&quot;&gt;Refactoring UI&lt;/a&gt;&quot; the book by Adam Wathan and Steve Schoger. I purchased this digitally a while ago and I do enjoy referencing this, especially the component library.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have any suggestions, please let me know. Anyway, let&apos;s get into this weeks links!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://htmlforpeople.com/&quot;&gt;HTML for people&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://blakewatson.com/&quot;&gt;Blake Watson&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Blake wonders why more people don&apos;t use HTML, this project is to help normies learn HTML. I&apos;ve often thought it would be good for folks to learn basic programming, so this is an excellent bridge.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://100daysof.blog/2024/10/10/im-okay-with.html&quot;&gt;I&apos;m okay with me.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://anniegreens.lol/&quot;&gt;Anne Sturdivant&lt;/a&gt; on October 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Lovely post and a great reminder that you are awesome as you are, no need to compare yourself to others. Thanks for the reminder, Annie!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://beeps.website/blog/2024-10-09-why-govuk-exit-this-page-doesnt-use-escape/#bonus%3A-why-does-it-redirect-the-user-to-bbc-weather%3F&quot;&gt;Why GOV.UK&apos;s Exit this Page component doesn&apos;t use the Escape key&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://beeps.website/&quot;&gt;beeps&lt;/a&gt; on October 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;beeps talks about the considerations that went into creating a useful &quot;Exit this page&quot; button, and the reasoning behind not using the escape key.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-10-08-development-philosophies/&quot;&gt;My development philosophy: KISS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime&lt;/a&gt; on October 8, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Jaime talks abstraction, readability, and taking the time do things correctly as her development philosophies. Also, check out that rad &lt;code&gt;blockquote&lt;/code&gt; styling!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/searching-for-a-new-css-logo/&quot;&gt;Searching for a New CSS Logo&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ryantrimble.com&quot;&gt;Ryan Trimble&lt;/a&gt; on October 8, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Earlier this week I wrote about why the CSS-Next community group is working on a new logo for CSS.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.a11y-collective.com/blog/accessible-carousel/&quot;&gt;How to Test and Improve Carousel Accessibility: A Complete Guide&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.a11y-collective.com/persons/florian-schroiff/&quot;&gt;Florian Schroiff&lt;/a&gt; on October 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Developers hate it, but marketing loves it: carousels. If you must, Florian has an awesome guide to do it accessibly.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://blog.dwac.dev/posts/html-whitespace/#html-whitespace-is-broken&quot;&gt;HTML Whitespace is Broken&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://blog.dwac.dev/&quot;&gt;Doug Parker&lt;/a&gt; on September 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Doug maps out all the gotchas with whitespace in HTML, how CSS and content management tools can affect it, and a suggestion on how to fix it going forward.&lt;/p&gt;
&lt;h2&gt;Tips &amp;amp; Tricks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/propjockey/css-sweeper?tab=readme-ov-file#css-is-a-programming-language-thanks-to-the-space-toggle-trick&quot;&gt;CSS Space Toggles&lt;/a&gt; - Neat trick to add a toggleable, condition based logic to custom properties to your CSS.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://css-tip.com/quantity-queries/&quot;&gt;Quantity queries using has() selector&lt;/a&gt; - Temani demonstrates how to select a specific number of child elements using &lt;code&gt;:has()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.fema.gov/disaster/current/hurricane-helene/rumor-response&quot;&gt;Hurricane Response Rumors&lt;/a&gt; - FEMA put up this page to combat disinformation regarding the recent hurricanes Helene and Milton.&lt;/li&gt;
&lt;li&gt;Matt Mullenweg added &lt;a href=&quot;https://wptavern.com/wordpress-org-login-gets-mandatory-affiliation-checkbox-following-wp-engine-dispute&quot;&gt;a dumb checkbox&lt;/a&gt; to the WordPress.org login page.&lt;/li&gt;
&lt;li&gt;Sara Joy now &lt;a href=&quot;https://front-end.social/@sarajw/113289529857183000&quot;&gt;has a sticker book&lt;/a&gt;, and I still have a sticker box.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stop what you are doing, watch &lt;a href=&quot;https://www.youtube.com/watch?v=0FwM8HdOY-A&quot;&gt;Erin Kissane&apos;s talk at XOXO Festival&lt;/a&gt;, then &lt;strong&gt;let&apos;s fix the fucking networks&lt;/strong&gt;!&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #23</title><link>https://ryantrimble.com/blog/weekly-roundup-23/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-23/</guid><description>This week&apos;s article has nothing to do with the 2007 film &quot;The Number 23&quot; even if it might seem that way.</description><pubDate>Sat, 05 Oct 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;While researching a topic I unintentionally formed an opinion over, I realized I really, really enjoy having my opinion changed.&lt;/p&gt;
&lt;p&gt;Changing my mind means I&apos;ve learned more about the situation, gained missing context, and most importantly, understand the reasoning behind it - and I think that is a good thing.&lt;/p&gt;
&lt;p&gt;I hope you learned something this week too, but if not - hopefully you will with this week&apos;s interesting links!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://frontendmasters.com/blog/web-components-are-bad-good-and-ok/&quot;&gt;Web Components are Bad, Good, and OK&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://frontendmasters.com/blog/author/chriscoyier/&quot;&gt;Chris Coyier&lt;/a&gt; on October 3, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Chris sums up this crazy debate about web components incredibly well. What a weird argument this has turned out to be.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/css-anchor-positioning-guide/&quot;&gt;CSS Anchor Positioning Guide&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.monknow.dev/en/&quot;&gt;Juan Diego Rodríguez&lt;/a&gt; on October 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;My friend Juan at CSS-Tricks released the ultimate guide to Anchor Positioning. I&apos;ve already bookmarked this, as I expect to return to it frequently.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-bdo-element/&quot;&gt;The bdo element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on October 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon, I doubt you read this, but... you&apos;ve really did it this time. There&apos;s no reason an article about an HTML element should be a masterpiece, but here we are. Also, I have a very strange definition of &quot;masterpiece.&quot;&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://sarajoy.dev/blog/see-and-point/&quot;&gt;Doug Engelbart or How We Learned to Stop Commanding and Love the Mouse&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://sarajoy.dev/blog/see-and-point/&quot;&gt;Sara Joy&lt;/a&gt; on September 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Sara gives us a history lesson on Apple&apos;s influence in user interface design, exploring Doug Engelbart who coined &quot;See and Point&quot; for mouse-driven interfaces.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-09-30-react-dependency-array/&quot;&gt;ELI5: What is a dependency array in React?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on September 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;m pretty sure Jaime wrote this article because I complain about dependency arrays every time I need to touch React. Why are they there? Why is it so easy to cause an infinite loop? Are people who like React OK?&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-bdi-element/&quot;&gt;The bdi element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on September 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;The first of the two articles released, Heydon was cooking this week. This one is ok, too.&lt;/p&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/11ty/eleventy/releases/tag/v3.0.0&quot;&gt;Eleventy v3.0.0&lt;/a&gt; was released - Possums, assemble!&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.mozilla.org/en/mozilla/improving-online-advertising/&quot;&gt;Mozilla isn&apos;t even trying anymore&lt;/a&gt; (but they are &lt;a href=&quot;https://connect.mozilla.org/t5/discussions/open-call-for-firefox-fan-art-help-us-celebrate-the-upcoming/m-p/72082#M27523&quot;&gt;looking for fan art&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Bunch of folks &lt;a href=&quot;https://techcrunch.com/2024/10/04/159-employees-are-leaving-automattic-as-ceos-fight-with-wp-engine-escalates/&quot;&gt;left Automattic&lt;/a&gt; due to the feud with WP Engine, though &lt;a href=&quot;https://zeldman.com/2024/10/04/i-stayed/&quot;&gt;some stayed&lt;/a&gt;. What a disappointing situation.&lt;/li&gt;
&lt;li&gt;Anh released a super spooky update to her &lt;a href=&quot;https://anhvn.com/&quot;&gt;personal website&lt;/a&gt;, be sure to try the light mode toggle!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://viteconf.org/&quot;&gt;Vite Conf&lt;/a&gt; was this week, whiteboard afficienado &lt;a href=&quot;https://bholmes.dev/&quot;&gt;Ben Holmes&lt;/a&gt; was there!&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #22</title><link>https://ryantrimble.com/blog/weekly-roundup-22/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-22/</guid><description>Work was stressful this week, thankfully my RSS reader was full of great articles. Thanks, everybody!</description><pubDate>Sat, 28 Sep 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There is a quote from author Mark Twain / normal guy Samuel Clemens:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Find a job you enjoy doing, and you will never have to work a day in your life.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really want that to be true.&lt;/p&gt;
&lt;p&gt;I love development, especially working with CSS - and yet, I have not quite figured out how to achieve that. Actually, in my current situation, I&apos;m unable to do virtually any of what I enjoy about development. The things I&apos;m passionate about, I&apos;m being asked to ignore &lt;em&gt;for the bottom line&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don&apos;t enjoy that.&lt;/li&gt;
&lt;li&gt;I don&apos;t want to do that.&lt;/li&gt;
&lt;li&gt;Please don&apos;t make me do that.&lt;/li&gt;
&lt;li&gt;You are killing my passion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thankfully, the development communities I find myself in help restore that passion. Revitalizing me with some great links, so let&apos;s dig in!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-b-element/&quot;&gt;The b element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on September 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon&apos;s article helped me figure out the differences between presentational elements, semantic elements, and chemical elements.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/a-guide-to-destructuring-in-javascript/&quot;&gt;A guide to destructuring in JavaScript&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://hire.wil.to/&quot;&gt;Mat “Wilto” Marquis&lt;/a&gt; on September 25, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Mat goes all out explaining the various ways you can destructure stuff and things in JavaScript. Turns out there are several ways, weird.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://clagnut.com/blog/2433/&quot;&gt;Introducing TODS – a typographic and OpenType default stylesheet&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://clagnut.com/&quot;&gt;Richard Rutter&lt;/a&gt; on September 22, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This was shared by &lt;a href=&quot;https://piccalil.li/links/introducing-tods-a-typographic-and-open-type-default-stylesheet/&quot;&gt;Andy on Piccalil.li&lt;/a&gt;, but this looks like a great way to kick off a stylesheet with great typographical defaults.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://whitep4nth3r.com/blog/work-is-meaningless/&quot;&gt;Work is meaningless, and it almost killed my husband&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://whitep4nth3r.com/&quot;&gt;Salma Alam-Naylor&lt;/a&gt; on September 22, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Salma posted quite the cautionary tale about her husband&apos;s health, and how you can&apos;t ignore your own health. I&apos;m glad to hear Richard is doing well.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tip.com/css-variables-range-slider/&quot;&gt;Update CSS variables using range slider&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://css-tip.com/&quot;&gt;Temani Afif&lt;/a&gt; on September 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This is &lt;em&gt;really&lt;/em&gt; neat, Temani gives a great tip on how to tie a range slider to the value of a CSS custom property.&lt;/p&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The Chrome team introduced &lt;a href=&quot;https://developer.chrome.com/docs/css-ui/animate-to-height-auto&quot;&gt;&lt;code&gt;interpolate-size&lt;/code&gt;&lt;/a&gt; as a progressive enhancement, making animating to &lt;code&gt;auto&lt;/code&gt; a whole lot easier.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://techcrunch.com/2024/09/27/wordpress-vs-wp-engine-drama-explained/&quot;&gt;WordPress Matt is pissed at WP Engine&lt;/a&gt;, apparently. Personally, I stopped using WordPress years ago as I was too broke to afford hosting.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #21</title><link>https://ryantrimble.com/blog/weekly-roundup-21/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-21/</guid><description>The 21st Roundup on the 21st day of the 21st month of the 21st century, wait actually I think that month part is wrong.</description><pubDate>Sat, 21 Sep 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What a week! I released &lt;a href=&quot;https://ryantrimble.com/blog/the-hd-remaster&quot;&gt;the HD remaster&lt;/a&gt; of my website last weekend and received some wonderful feedback, thanks to a supportive community!&lt;/p&gt;
&lt;p&gt;Also, I had a new article published over on CSS-Tricks - it&apos;s about some small features &lt;a href=&quot;https://css-tricks.com/clever-polypane-debugging-features-im-loving/&quot;&gt;I love about Polypane&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anyways, let&apos;s get into it!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ryanmulligan.dev/blog/password-input-components/&quot;&gt;Web Components for Password Input Enhancements&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ryanmulligan.dev/&quot;&gt;Ryan Mulligan&lt;/a&gt; on September 20, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;You gotta love to see well rounded, progressively enhanced, native custom web elements. Great real-world example and use-case, nice work Ryan!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://hazelweakly.me/blog/cache-me-not-cache-me-cache-me-not/&quot;&gt;Cache Me Not, Cache Me, Cache Me Not&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://hazelweakly.me/&quot;&gt;Hazel Weakly&lt;/a&gt; on September 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Hazel&apos;s pissed. And for good reason: &lt;em&gt;caching&lt;/em&gt;. So pissed in fact, she made up perfectly understandable terminology to explain how caching &lt;em&gt;should&lt;/em&gt; work.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/how-i-build-a-button-component/&quot;&gt;How I build a button component&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt; on September 18, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Thanks Andy explaining this one - I mean, yeah - &lt;em&gt;I know how to make a button&lt;/em&gt;, obviously, this is just for everyone else&apos;s sake... yeah... buttons.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://alistairshepherd.uk/writing/selling-web-project/&quot;&gt;Selling a small front-end web project — what I learned&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://alistairshepherd.uk/&quot;&gt;Alistair Shepherd&lt;/a&gt; on September 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Awesome write-up by Alistair, on the experience of being approached to sell an old side-project you forgot about - every developer&apos;s dream. Get that bag, Alistair!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://chriskirknielsen.com/blog/nth-next-sibling-no-need/&quot;&gt;:nth-next-sibling? No need.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://chriskirknielsen.com/&quot;&gt;Christopher Kirk-Nielson&lt;/a&gt; on September 15, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Chris exlpains a neat CSS selector technique he figured out that lets you grab any number of elements following a specified element.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Nice, Chris! */
li:nth-child(-n + 3 of .el ~ *) { ... }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.zachleat.com/web/symbiotic-open-source/&quot;&gt;Open Source Needs to be Financially Symbiotic&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.zachleat.com/&quot;&gt;Zach Leatherman&lt;/a&gt; on September 13, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Great post by Zach, explaining the situation with 11ty and how popular open source projects need to be financially secure enough to be maintainable.&lt;/p&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft wants to &lt;a href=&quot;https://www.theverge.com/2024/9/20/24249770/microsoft-three-mile-island-nuclear-power-plant-deal-ai-data-centers&quot;&gt;revive the Three Mile Island&lt;/a&gt; nuclear power plant to provide power to AI - &lt;em&gt;wait that&apos;s like 5 mins away from me...&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;The folks over at Chrome are &lt;a href=&quot;https://developer.chrome.com/blog/masonry-syntax&quot;&gt;requesting feedback&lt;/a&gt; on CSS masonry implmentations proposed by the CSS Working Group.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://localghost.dev/blog/new-garden-theme/&quot;&gt;Sophie Koonin&lt;/a&gt; added a new theme to her site, and this time: it&apos;s &lt;em&gt;garden&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>The HD Remaster</title><link>https://ryantrimble.com/blog/the-hd-remaster/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-hd-remaster/</guid><description>My personal website received a fresh coat of paint and some new features!</description><pubDate>Sat, 14 Sep 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For the last few weeks I&apos;ve been working on the latest iteration of my site, the one you are looking at now!&lt;/p&gt;
&lt;p&gt;Yeah, I know, it doesn&apos;t seem &lt;em&gt;much&lt;/em&gt; different - however, I assure you it was basically rebuilt from the ground up. I didn&apos;t really update the &quot;branding&quot; so-to-speak, rather overhauled the code. Cleaned up a lot of styling, updated designs where it seemed appropriate, as well as worked on adding in some new things.&lt;/p&gt;
&lt;p&gt;I&apos;m calling it the &lt;em&gt;HD Remaster&lt;/em&gt; as it&apos;s very much the same website, just enhanced.&lt;/p&gt;
&lt;p&gt;The key reasons I decided to change things include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Previously, I built my website very much for &lt;em&gt;blogging&lt;/em&gt;, not expecting to do much else with it. Well, I have plans now and I wanted to make my layouts a bit more flexible for new types of things.&lt;/li&gt;
&lt;li&gt;Enhanced accessibility, I focused a lot on making sure my site is highly navigable by keyboard, screen readers, and other assistive devices that handle navigating by focus, headings, landmarks, links.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;ve updated every page on the site, made new pages, and included new features!&lt;/p&gt;
&lt;h2&gt;Updated Pages!&lt;/h2&gt;
&lt;h3&gt;Home Page&lt;/h3&gt;
&lt;p&gt;My homepage was a bit too repetitive and had more static than dynamic content.&lt;/p&gt;
&lt;p&gt;I changed it up a bit this time, hoping to have the homepage a little more lively. I still feature the same sections as before, but more tailored to the section.&lt;/p&gt;
&lt;p&gt;I also added a new section, the &quot;published elsewhere&quot; section. The idea here is if I publish articles elsewhere, I can still feature the articles here on my own site.&lt;/p&gt;
&lt;h3&gt;Now&lt;/h3&gt;
&lt;p&gt;I&apos;ve expanded the &lt;code&gt;/now&lt;/code&gt; page to show more things.&lt;/p&gt;
&lt;p&gt;I&apos;ll have a message for folks visiting the page, information on my current roles, as well as all the fun stuff like books, music, movies, and games.&lt;/p&gt;
&lt;p&gt;I have some other plans for this page, but I need to make sure it doesn&apos;t get &lt;em&gt;too&lt;/em&gt; busy.&lt;/p&gt;
&lt;h2&gt;New Features!&lt;/h2&gt;
&lt;h3&gt;Blog roll&lt;/h3&gt;
&lt;p&gt;The first blog roll I remember seeing is over on &lt;a href=&quot;https://benmyers.dev/blogroll/&quot;&gt;Ben Myer&apos;s site&lt;/a&gt; and I thought that was &lt;em&gt;rad&lt;/em&gt; way to feature the great writing from folks in the dev community.&lt;/p&gt;
&lt;p&gt;Also, I love sharing awesome things I&apos;ve come across, I do it every week in my &lt;em&gt;Weekly Roundup&lt;/em&gt; post. Most of those articles happen to come from my RSS reader, as I&apos;m subscribed to some amazing feeds.&lt;/p&gt;
&lt;p&gt;It only made sense to put together a blog roll, definitely check it out! If you want to be included, feel free to reach out!&lt;/p&gt;
&lt;h3&gt;Pagination&lt;/h3&gt;
&lt;p&gt;I don&apos;t think I imagined I would have enough articles to warrant pagination last time I re-built the site. I&apos;d tried blogging before, but it never really stuck.&lt;/p&gt;
&lt;p&gt;Turns out, I have written a lot of articles, not even including all the Roundups. So it seemed like a good idea to break up the &lt;code&gt;/blog&lt;/code&gt; page as to not load a bunch of articles at once.&lt;/p&gt;
&lt;h3&gt;Search&lt;/h3&gt;
&lt;p&gt;Again, didn&apos;t think I&apos;d need search previously and also I don&apos;t believe &lt;a href=&quot;https://pagefind.app/&quot;&gt;Pagefind&lt;/a&gt; existed when I built the site before. But now I do and luckily it does.&lt;/p&gt;
&lt;p&gt;Pagefind is a super simple way to add search to static sites, you don&apos;t have to install any packages and it&apos;s all local to your project, so it doesn&apos;t need to go out to some third-party service.&lt;/p&gt;
&lt;h2&gt;Hope you like it!&lt;/h2&gt;
&lt;p&gt;Websites are never &quot;done,&quot; and I&apos;ve still got more things to do here.&lt;/p&gt;
&lt;p&gt;I hope you like the changes, feel free to let me know if you spot anything out of place or whether you like it or absolutely hate it!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #20</title><link>https://ryantrimble.com/blog/weekly-roundup-20/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-20/</guid><description>Absolutely massive week this week, lots of links, exciting news, conferences and a new course to check out!</description><pubDate>Sat, 14 Sep 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Happy roundup day, everyone! I&apos;m inches away from releasing the HD remaster of this site, hoping that will get merged sometime this weekend. I was aiming to release it with this Weekly Roundup and not say anything, but it didn&apos;t time up unfortunately.&lt;/p&gt;
&lt;p&gt;Anyways, lots to talk about this week. Some exciting news, great conferences to check out, a new course, as well as lots of interesting links!&lt;/p&gt;
&lt;h2&gt;New Course&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Andy Bell has a limited pre-order sale up on for his new CSS course coming later this year, &lt;a href=&quot;https://piccalil.li/blog/introducing-complete-css/&quot;&gt;Complete CSS&lt;/a&gt;. I am most confident with CSS, yet I still preordered this course.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://typetura.com/blog/unit-division-with-css-and-fallbacks/&quot;&gt;How unit division works in CSS, and how to use it today&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://typetura.com/&quot;&gt;Scott Kellum&lt;/a&gt; on September 13, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Scott over at Typetura is talking unit division in CSS, which is good, because I didn&apos;t know what that was until now. Really neat demo!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://daverupert.com/2024/09/good-forms/&quot;&gt;Good forms&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://daverupert.com/&quot;&gt;Dave Rupert&lt;/a&gt; on September 13, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If you know me, you know I like a good form, in fact I don&apos;t like bad forms at all! Good thing Dave put together this great list describing what good forms do.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-09-10-exporting-top-level-dynamic-components/&quot;&gt;Exporting top level dynamically generated components&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on September 11, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Jaime is cooking up something neat in this article on dynamically generating noodles, I mean components.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://chriscoyier.net/2024/09/11/the-west-just-burns-now/&quot;&gt;The West Just Burns Now&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://chriscoyier.net/&quot;&gt;Chris Coyier&lt;/a&gt; on September 11, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I complain a lot about how Pennsylvania is tropical climate now, but at least I can say we aren&apos;t on fire (yet). Chris describes the dire situation over on the west coast.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-audio-element/&quot;&gt;The audio element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on September 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;There are few instances when I see code and be glad there isn&apos;t a demo attached, such as this example, Heydon describing the &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element with erotic squelching.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.miriamsuzanne.com/2024/09/09/embed-pen/&quot;&gt;A web component for CodePen embeds?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.miriamsuzanne.com/&quot;&gt;Miriam Suzanne&lt;/a&gt; on September 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Miriam took inspo from David Darnes&apos; &lt;code&gt;&amp;lt;code-pen&amp;gt;&lt;/code&gt; web component, and created &lt;code&gt;&amp;lt;embed-pen&amp;gt;&lt;/code&gt; to easily embed a CodePen. Soon we will have web components for all aspects of CodePen and I&apos;m here for it.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://mxb.dev/blog/buildless/&quot;&gt;Going Buildless&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://mxb.dev/&quot;&gt;Max Böck&lt;/a&gt; on September 8, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;m not sure how Max knew &lt;em&gt;exactly&lt;/em&gt; what I was doing in 2005, but here he explains how to achieve &lt;s&gt;nirvana&lt;/s&gt; buildless workflow.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://rimdev.io/adding-googles-recaptcha-to-your-form/&quot;&gt;Adding Google&apos;s reCAPTCHA To Your Form&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://rimdev.io/&quot;&gt;Ted Krueger&lt;/a&gt; on September 6, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Ted put together a straightforward, simple, quick guide on how to add reCAPTCHA to forms over on our dev team&apos;s blog.&lt;/p&gt;
&lt;h2&gt;In Other News&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Whoa, &lt;a href=&quot;https://blog.fontawesome.com/eleventy-joins-font-awesome/&quot;&gt;11ty joined FontAwesome&lt;/a&gt;! I&apos;m stoked Zach found a great open-source partner to keep 11ty thriving!&lt;/li&gt;
&lt;li&gt;Una Kravets &lt;a href=&quot;https://developer.chrome.com/blog/rfc-customizable-select&quot;&gt;posted on the Chrome Dev&lt;/a&gt; blog asking for feedback on, get ready for this, a &lt;em&gt;customizable select&lt;/em&gt; element.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cool Conferences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Inclusive Design 24 took place on September 12, 2024, be sure to check out the 24-hour &lt;a href=&quot;https://www.youtube.com/playlist?list=PLn7dsvRdQEfFompoGO_CE5z-_HjEdgVit&quot;&gt;playlist available on YouTube&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Dave Letory and crew are putting on another awesome &lt;a href=&quot;https://2024.stateofthebrowser.com/organisers/&quot;&gt;State of the Browser&lt;/a&gt; today, which I&apos;m watching as I write this actually.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #19</title><link>https://ryantrimble.com/blog/weekly-roundup-19/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-19/</guid><description>You really never know what you are going to find on reddit dot com.</description><pubDate>Sat, 07 Sep 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m about 75% complete on my website refresh, also I&apos;m terrible at estimating. It&apos;s was a busy week though, as the job hunt continues and I passed my allergy test. I realize that isn&apos;t a pass/fail type of test, but I&apos;m not allergic to anything, so I think that means I scored a 100%. Lots of percentage based jokes today, I&apos;m sorry.&lt;/p&gt;
&lt;p&gt;I know what you are really here for though, let&apos;s get into it.&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/display-contents/&quot;&gt;CSS display contents&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on September 4, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Do you know what &lt;code&gt;display: contents;&lt;/code&gt; does? Yeah, I was in the same boat once too - before I read this one by Ahmad. Check it out if you wanna learn something.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://modem.io/blog/blog-monetization/&quot;&gt;How to Monetize a Blog&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://modem.io/&quot;&gt;Tyler (?)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Wild one I came across on reddit, love the creativity here, but content warning: &lt;strong&gt;insufferable nature of capitalism&lt;/strong&gt;. Rad stuff. I hope you&apos;re monetizing this blog somehow, Tyler (if that is your real name (I genuinely don&apos;t know)), get that bag.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://daverupert.com/2024/09/dev-tools-performance-monitor-panel/&quot;&gt;The Dev Tools Performance Monitor Panel&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://daverupert.com/&quot;&gt;Dave Rupert&lt;/a&gt; on September 3, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Now that I&apos;ve read this piece on the performance monitor panel, I&apos;m both curious and terrified to check out our applications at work. Great write up Dave!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://briefs.video/videos/what-is-react/&quot;&gt;What is React.js?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://briefs.video/&quot;&gt;Heydon Pickering&lt;/a&gt; on September 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Sadly, it seems Heydon broke the weekly alphabetical HTML article streak - gladly though, as they dropped an absolute banger on Webbed Briefs. The wife and I watched this along with breakfast.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ryanmulligan.dev/blog/css-property-new-style/&quot;&gt;CSS @property and the New Style&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ryanmulligan.dev/&quot;&gt;Ryan Mulligan&lt;/a&gt; on September 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If you&apos;re looking for actual, quality information from someone named &lt;em&gt;Ryan&lt;/em&gt;, check out Ryan Mulligan&apos;s write up on &lt;code&gt;@property&lt;/code&gt;. Demonstrating a neat use-case by making a super rare, shiny call-to-action.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://chriskirknielsen.com/blog/my-under-engineered-way-to-avoid-a-flash-of-inaccurate-color-theme/&quot;&gt;My under-engineered way to avoid a Flash of inAccurate coloR Theme (FART)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://chriskirknielsen.com/&quot;&gt;Christopher Kirk-Nielsen&lt;/a&gt; on September 1, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Christopher provides a giggle-worthy headline and timely advice. I&apos;m cooking up the HD remaster of this website, and color themes are on the to-do list.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #17</title><link>https://ryantrimble.com/blog/weekly-roundup-17/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-17/</guid><description>This was a hell of a week, but we made it. Happy Saturday, I&apos;ve got a bunch great links for ya!</description><pubDate>Sat, 24 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ericwbailey.website/published/basic-keyboard-shortcut-support-for-focused-links/&quot;&gt;Basic keyboard shortcut support for focused links&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ericwbailey.website/&quot;&gt;Eric W. Bailey&lt;/a&gt; on August 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Eric has assembled an amazing reference explaining the intricacies of keyboard shortcuts available on focused links, and how different browser engines handle them.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-08-21-vue-custom-element-internal-methods/&quot;&gt;Exposing internal methods on Vue custom elements&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on August 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If you wrap a Vue component up as a custom element, you may want to use it&apos;s methods outside the component, so Jaime is here to explain how!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/on-the-ground-at-frostapalooza/&quot;&gt;On the Ground at Frostapalooza&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://css-tricks.com/author/ryantrimble/&quot;&gt;Ryan Trimble&lt;/a&gt; on August 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Last week I talked about heading out to Pittsburgh for &lt;a href=&quot;https://frostapalooza.bradfrost.com/&quot;&gt;Frostapalooza&lt;/a&gt;, find out how that went over on CSS-Tricks! Spoiler alert: it was rad.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-article-element/&quot;&gt;The article element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on August 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon continues to make it easy for me by ensuring a spot in the weekly roundup, this article on &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; is the latest entry in Heydon&apos;s alphabetical journey through HTML.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://darthmall.net/notes/2024/some-git-tips/&quot;&gt;Some Git Tips&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://darthmall.net/&quot;&gt;Evan Sheehan&lt;/a&gt; on August 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;My friend Evan shares a few git tips he came across recently, I&apos;m bookmarking this as I only have like 3 git commands &lt;em&gt;commited&lt;/em&gt; (get it?) to memory.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://survey.devographics.com/en-US/survey/state-of-css/2024&quot;&gt;The State of CSS 2024&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted on August 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;It&apos;s that time of year, &lt;em&gt;survey time&lt;/em&gt;! This is pretty much the only survey about CSS (that I know of?), so it&apos;s a good one to spend a few minutes filling out.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://andrewwalpole.com/blog/custom-top-and-bottom-css-container-masks/&quot;&gt;Custom Top and Bottom CSS Container Masks&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://andrewwalpole.com/&quot;&gt;Andrew Walpole&lt;/a&gt; on May 29, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This was shared over on Mastodon, Andrew explains how to use masks to create awesome wavy and other custom shapes for webpages.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #18</title><link>https://ryantrimble.com/blog/weekly-roundup-18/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-18/</guid><description>I still haven&apos;t decided what the summary of this post should be.</description><pubDate>Sat, 24 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hey everybody, I hope you had a great week!&lt;/p&gt;
&lt;p&gt;I checked out a new branch and began working on a refresh for the personal website. It&apos;s not going to be drastically different, but I&apos;m hoping to clean up the styles a bit. Look forward to some new features that I never got around to implementing on this current iteration, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Search!&lt;/li&gt;
&lt;li&gt;Pagination!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I think that is it actually. Anyway, here are some amazing links from this past week:&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.bram.us/2024/08/31/introducing-bramus-style-observer-a-mutationobserver-for-css/&quot;&gt;Introducing &lt;code&gt;@bramus/style-observer&lt;/code&gt;, a MutationObserver for CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://bram.us/&quot;&gt;Bramus Van Damme&lt;/a&gt; on August 31, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Interesting new package by Bramus, gives you the ability to watch for CSS style changes and fire a callback. This gives me a few ideas...&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-08-30-vue-3-template-refs/&quot;&gt;Using template refs in Vue 3 with Composition API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on August 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Interesting fact: I sometimes get to read Jaime&apos;s posts ahead of time, this time I got to suggest the cool little sunglass emoji 😎.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://nerdy.dev/text-box-ftw&quot;&gt;text-box ftw&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://nerdy.dev&quot;&gt;Adam Argyle&lt;/a&gt; on August 29, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Adam gives a sneak peek at the &lt;code&gt;text-box&lt;/code&gt; property, demoing some neat centering techniques. Check it out in Safari or Chrome Canary!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-aside-element/&quot;&gt;The aside element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on August 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;As a personal &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt;, I&apos;d like to say I&apos;m excited to see how Heydon tackles the &lt;code&gt;&amp;lt;dl&amp;gt;&lt;/code&gt; tag. Do you wait to talk about &lt;code&gt;&amp;lt;dd&amp;gt;&lt;/code&gt;? or just do them all at once?&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://eieio.games/essays/the-secret-in-one-million-checkboxes/&quot;&gt;The secret inside One Million Checkboxes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;eieio&lt;/a&gt; on August 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This is a wild internet story, an example of what is cool about technology, and the power of a small group of Discord users.&lt;/p&gt;
</content:encoded></item><item><title>Introducing &lt;skelly-wc&gt;</title><link>https://ryantrimble.com/blog/introducing-skelly-wc/</link><guid isPermaLink="true">https://ryantrimble.com/blog/introducing-skelly-wc/</guid><description>I created a weird little library a while ago, now I&apos;ve upgraded that weird little library.</description><pubDate>Fri, 23 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A while ago, I created a little library at work to make those &quot;skeleton screens&quot; that I&apos;m not sure anyone likes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: A skeleton screen is used as a placeholder while users wait for a page to load. This progress indicator is used for full page loads and reduces the perception of a long loading time by providing clues for how the page will ultimately look.
— &lt;a href=&quot;https://www.nngroup.com/articles/skeleton-screens/&quot;&gt;Nielsen Norman Group&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We named it &lt;a href=&quot;https://github.com/ritterim/skellyCSS&quot;&gt;&lt;code&gt;skellyCSS&lt;/code&gt;&lt;/a&gt; because... skeletons and CSS, I guess. We still aren&apos;t even really using it very much, but it was fun to do and it was the first node package I made myself (for the most part). It&apos;s still available on &lt;a href=&quot;https://github.com/ritterim/skellyCSS&quot;&gt;GitHub&lt;/a&gt; and &lt;a href=&quot;https://www.npmjs.com/package/@ritterim/skellycss&quot;&gt;npmjs.com&lt;/a&gt; if you wanna check it out.&lt;/p&gt;
&lt;p&gt;Now I&apos;ve upgraded (sidegraded?) &lt;code&gt;skellyCSS&lt;/code&gt; into &lt;a href=&quot;https://github.com/mrtrimble/skelly-wc&quot;&gt;&lt;code&gt;skelly-wc&lt;/code&gt;&lt;/a&gt; (the &quot;wc&quot; stands for web component).&lt;/p&gt;
&lt;h2&gt;Why web components?&lt;/h2&gt;
&lt;p&gt;I&apos;m doing a deep dive with &lt;a href=&quot;https://scottjehl.com/&quot;&gt;Scott Jehl&lt;/a&gt;&apos;s new course, &quot;&lt;a href=&quot;https://scottjehl.com/learn/webcomponentsdemystified/&quot;&gt;Web Components: Demystified&lt;/a&gt;&quot; and wanted to build something. So, call it practice.&lt;/p&gt;
&lt;p&gt;I remembered this weird little package and thought it&apos;d be fun to redo as a weird little web component.&lt;/p&gt;
&lt;h2&gt;What does it do?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;skelly-wc&lt;/code&gt; makes skeleton screens, basically.&lt;/p&gt;
&lt;p&gt;There&apos;s only one component so far, &lt;code&gt;&amp;lt;skelly-text&amp;gt;&lt;/code&gt; which replicates paragraphs. The stunning key features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can tell it how many lines to show.&lt;/li&gt;
&lt;li&gt;Change it&apos;s color if you&apos;d like.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How does it work?&lt;/h2&gt;
&lt;p&gt;I&apos;ve got the full instructions in the repo&apos;s &lt;a href=&quot;https://github.com/mrtrimble/skelly-wc/blob/main/README.md&quot;&gt;README.md&lt;/a&gt; file, but let&apos;s do it the quick way.&lt;/p&gt;
&lt;p&gt;Include the &lt;code&gt;skelly-wc.js&lt;/code&gt; file via content delivery network at the end of your document, like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;     &amp;lt;!-- ... --&amp;gt;
    &amp;lt;script
      type=&quot;module&quot;
      src=&quot;https://cdn.jsdelivr.net/npm/@mrtrimble/skelly-wc/dist/skelly-wc.js&quot;
    &amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then you use it wherever you need it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;
  &amp;lt;skelly-text&amp;gt;&amp;lt;/skelly-text&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;ll output 5 gray lines in the rough shape of a paragraph.&lt;/p&gt;
&lt;p&gt;Earlier I mentioned the two stunning key features of setting the number of lines and changing skelly&apos;s color, that works like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;
  &amp;lt;skelly-text line-count=&quot;3&quot; line-color=&quot;tomato&quot;&amp;gt; &amp;lt;/skelly-text&amp;gt;
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s right, &lt;em&gt;attributes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here&apos;s a demo I made on CodePen:&lt;/p&gt;
&lt;p&gt;&amp;lt;p
class=&quot;codepen&quot;
data-height=&quot;650&quot;
data-theme-id=&quot;default&quot;
data-default-tab=&quot;result&quot;
data-slug-hash=&quot;VwJXQZJ&quot;
data-pen-title=&quot;skelly-wc&quot;
data-user=&quot;mrtrimble&quot;
data-token=&quot;4499796d2b5cb87dda1ed5bb2b1f392c&quot;
style=&quot;height: 650px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;span&amp;gt;
See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/VwJXQZJ/4499796d2b5cb87dda1ed5bb2b1f392c&quot;&amp;gt;skelly-wc&amp;lt;/a&amp;gt; by
Ryan Trimble (&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;script async src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #16</title><link>https://ryantrimble.com/blog/weekly-roundup-16/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-16/</guid><description>A weekend in Pittsburgh, an interesting use-case for color fonts, and 50 tips for documentation!</description><pubDate>Sat, 17 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m heading to Pittsburgh this weekend for &lt;a href=&quot;https://frostapalooza.bradfrost.com/&quot;&gt;Frostapalooza&lt;/a&gt;, Brad Frost&apos;s benefit concert-slash-party to celebrate his birthday!&lt;/p&gt;
&lt;p&gt;If you are also attending, definitely say hi if you see me — I&apos;m hoping to meet a few online friends in real life for the first time!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-area-element/&quot;&gt;The Area element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on August 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon&apos;s posts are teaching my non-existent children the alphabet. This time their talking about a relic from the glory days, &lt;code&gt;&amp;lt;area&amp;gt;&lt;/code&gt;. Wow, I haven&apos;t thought of this element since &lt;em&gt;I&lt;/em&gt; was a non-existent child.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://blog.glyphdrawing.club/font-with-built-in-syntax-highlighting/&quot;&gt;Font with built-in syntax highlighting&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://blog.glyphdrawing.club/&quot;&gt;Heikki Lotvonen&lt;/a&gt; on August 14, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heikki has added to the possible use-cases for color fonts, bringing us to a grand total of &lt;em&gt;one&lt;/em&gt; use-case. Kidding of course, this is insanely impressive and I&apos;m excited to give this a go!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.rainsberger.ca/blog/50-docs-tips-in-50-days/&quot;&gt;50 Docs tips in 50 days&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.rainsberger.ca/&quot;&gt;Sarah Rainsberger&lt;/a&gt; on August 12, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Astro documentation fairy godmother, Sarah Rainsberger, set out on a mission to write 50 technical documentation tips in 50 days and she just wrapped up #50 recently. Also, how cool is it that Sarah uses &lt;a href=&quot;https://starlight.astro.build/&quot;&gt;Starlight&lt;/a&gt; for her personal site.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://dgerrells.com/blog/how-not-to-use-box-shadows&quot;&gt;How not to use box shadows&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://dgerrells.com/&quot;&gt;David Gerrells&lt;/a&gt; on July 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;David shows us lots of ways &lt;em&gt;not&lt;/em&gt; to use a box-shadow, but somehow missed a very important way:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.element {
  box-shadow: 3 3 3 gray;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See, you need to specify a unit, otherwise it won&apos;t work very well.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #15</title><link>https://ryantrimble.com/blog/weekly-roundup-15/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-15/</guid><description>In this week&apos;s episode: CSS-Tricks makes it official, while Alex faces off in his greatest challenge yet.</description><pubDate>Sat, 10 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/css-chronicles-xlii/&quot;&gt;CSS Chronicles XLII&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://css-tricks.com/author/geoffgraham/&quot;&gt;Geoff Graham&lt;/a&gt; on August 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Geoff&apos;s making it clear that CSS-Tricks is alive, also &lt;em&gt;waitaminute&lt;/em&gt; — he&apos;s talking about me in there! Like many others, I&apos;ve been a fan of CSS-Tricks for a long time and I&apos;m super excited to be helping out. Thanks for the kind welcoming, Geoff!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://hidde.blog/re-global-design-system/&quot;&gt;Comparing design systems to find the best qualities&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://hidde.blog/&quot;&gt;Hidde de Vries&lt;/a&gt; on August 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Hidde chimes in with a friendly perspective shift on the global design system conversation. Rather than jumping directly into implementation, let&apos;s pause and figure out the most common attributes and establish a component&apos;s meaning. The real global design system is the friend&apos;s we&apos;ve made along the way.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wPL13VR88iY&quot;&gt;Build an e-commerce site... with a twist&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.learnwithjason.dev/&quot;&gt;Jason Lengstorf&lt;/a&gt; on August 7, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Jason does a web dev challenge series over on YouTube, what an awesome format for a show. &lt;strong&gt;More importantly,&lt;/strong&gt; my friend &lt;a href=&quot;https://trost.codes/&quot;&gt;Alex Trost&lt;/a&gt; got to participate! Root on Alex while watching the latest episode!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-abbr-element/&quot;&gt;The abbr element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on August 7, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon appears to be on an alphabetical mission to inform folks on HTML elements. This week&apos;s target is &lt;code&gt;&amp;lt;abbr&amp;gt;&lt;/code&gt; and he certainly cleared up a few things for me. I&apos;m wondering how Heydon will maintain sanity writing about different headings for 6 weeks straight.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.zachleat.com/web/serverless-cost/&quot;&gt;The Sneaky Costs of Scaling Serverless&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.zachleat.com/&quot;&gt;Zach Leatherman&lt;/a&gt; on August 5, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Zach did some cost analysis, &lt;em&gt;so you don&apos;t have to!&lt;/em&gt; Serverless has a cheap barrier for entry, but we&apos;ve all heard horror stories of developers receiving inexplicably inflated hosting bills. Good things to keep in mind when planning your deployment strategy.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://everythingchanges.us/blog/make-kin-not-nets/&quot;&gt;Make kin not nets&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://everythingchanges.us/&quot;&gt;Mandy Brown&lt;/a&gt; on July 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Really enjoyed this post by Mandy. I&apos;m quite the social recluse, so networking never feels quite right (this is why LinkedIn is so gross). I feel more reward in maintaining friendships than meeting people for the sake of expanding a contacts list.&lt;/p&gt;
&lt;h2&gt;Special Shoutouts&lt;/h2&gt;
&lt;p&gt;I want to send a massive thank you to &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes&lt;/a&gt; and &lt;a href=&quot;https://sia.codes/&quot;&gt;Sia Karamalegos&lt;/a&gt; (who both have awesome domain names) for including my blog in their blogrolls this week!&lt;/p&gt;
&lt;p&gt;If you are unfamiliar, blogrolls are a super kind way for authors to share and promote the blogs they follow. I&apos;ve added &quot;build a blogroll&quot; to my to-do list.&lt;/p&gt;
&lt;p&gt;Check out David&apos;s blogroll here:
https://darn.es/blogroll/&lt;/p&gt;
&lt;p&gt;Check out Sia&apos;s blogroll here:
https://sia.codes/rolls/&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #14</title><link>https://ryantrimble.com/blog/weekly-roundup-14/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-14/</guid><description>Learn about the anchor tag, awesome web components, and an exciting announcement about porffor.</description><pubDate>Sat, 03 Aug 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had an absolutely stacked week this week, but for good reasons!&lt;/p&gt;
&lt;p&gt;One exciting thing is that I&apos;ll be helping &lt;a href=&quot;https://geoffgraham.me/&quot;&gt;Geoff Graham&lt;/a&gt; out over on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt;, providing some updates to out-of-date articles.&lt;/p&gt;
&lt;p&gt;You may see some new posts from me over there as well, but don&apos;t worry – I&apos;ll still be posting interesting links right here each week!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://public.work/&quot;&gt;Public Work&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Really neat idea for a way to search public domain content, the multidirectional scroll is impressively smooth.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/the-anchor-element/&quot;&gt;The Anchor Element&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on August 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;ve been adding event listeners to &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s like a chump, you mean to tell me there&apos;s a HTML with navigation &lt;em&gt;built-in?&lt;/em&gt; Wow, it even has: focus order &lt;em&gt;built-in&lt;/em&gt;, keyboard control &lt;em&gt;built-in&lt;/em&gt;, role semantics &lt;em&gt;built-in&lt;/em&gt; – Thanks, Heydon, for showing me the way!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://astro.party/&quot;&gt;Astro Party&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jason.energy/&quot;&gt;Jason Lengstorf&lt;/a&gt; on August 2, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If you would like to learn how to build websites using Astro (like the very website you are on right now), keep an eye out for Astro Party, a new course by Jason Lengstorf!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://darn.es/awesome-standalones/&quot;&gt;Awesome Standalones&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes&lt;/a&gt; on July 31, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Name a more iconic duo than David Darnes and web components. Oh yeah, maybe &lt;a href=&quot;https://daverupert.com/&quot;&gt;Dave Rupert&lt;/a&gt; and web components. They are working together now? Name a more iconic trio. Check out the &lt;a href=&quot;https://github.com/davatron5000/awesome-standalones&quot;&gt;Awesome Standalones&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/a-handful-of-reasons-javascript-wont-be-available/&quot;&gt;A handful of reasons JavaScript won&apos;t be available&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt; on July 31, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Andy provides us with fifteen excellent reasons why JavaScript might fail, which really makes you stop and think about what we&apos;ve been doing the past few years.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://goose.icu/porffor/&quot;&gt;A new chapter for Porffor&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://goose.icu/&quot;&gt;CanadaHonk&lt;/a&gt; on July 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Oliver (CanadaHonk) has been keeping us folks on the Frontend Horse Discord updated on all the awesome news about &lt;a href=&quot;https://porffor.dev/&quot;&gt;porffor&lt;/a&gt; and excitingly, they get to work on it &lt;strong&gt;full-time!&lt;/strong&gt; Congrats to the goose!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #13</title><link>https://ryantrimble.com/blog/weekly-roundup-13/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-13/</guid><description>I&apos;m back from LA and found some cool links! Check out the latest articles from Roma, Steph, and Ahmad!</description><pubDate>Sat, 27 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This week I returned from &lt;a href=&quot;https://ryantrimble.com/blog/surviving-los-angeles/&quot;&gt;Los Angeles&lt;/a&gt; and worked on how to find &lt;a href=&quot;https://ryantrimble.com/blog/a-book-apart-books/&quot;&gt;A Book Apart Books&lt;/a&gt; now that they have closed up shop.&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://moderncss.dev/providing-type-definitions-for-css-with-at-property/&quot;&gt;Providing Type Definitions for CSS with &lt;code&gt;@property&lt;/code&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://moderncss.dev/&quot;&gt;Stephanie Eckles&lt;/a&gt; on July 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Steph provides a deep dive into the &lt;code&gt;@property&lt;/code&gt; at-rule, which is now available in all major browsers. The &lt;code&gt;@property&lt;/code&gt; helps ensure CSS custom properties are properly used with type definitions. I&apos;m calling this &lt;em&gt;Typestyles&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://kizu.dev/fit-to-width/&quot;&gt;Fit-to-Width Text: A New Technique&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://kizu.dev/&quot;&gt;Roma Komarov&lt;/a&gt; on July 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Roma&apos;s experiments with CSS are as impressive to read about as they are to experience. Roma has solved the longstanding issues of native, CSS only, fit-to-width text.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-07-19-til-crypto-random-uuid/&quot;&gt;TIL: &lt;code&gt;crypto.randomUUID&lt;/code&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on July 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Today I learned that Jaime is sharing what she learns! In this first post of her series, Jaime descibes how to generate a unique identifier with vanilla JavaScript.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/css-grid-area/&quot;&gt;CSS Grid Areas&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on July 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Ahmad is back with a rad interactive article describing how to use CSS Grid Areas. Thank you, Ahmad for these great articles, I find myself using these are resources often.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.matuzo.at/blog/2024/100daysof-day107&quot;&gt;Day 107: the light-dark() color function&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.matuzo.at/&quot;&gt;Manuel Matuzović&lt;/a&gt; on July 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;For the 107th day of Manuel&apos;s 100 day challenge, he&apos;s explaining the &lt;code&gt;light-dark()&lt;/code&gt; feature. I am super excited to use this in a project! Also, Manuel just released a book, &lt;a href=&quot;https://accessibility-cookbook.com/&quot;&gt;Web Accessibility Cookbook&lt;/a&gt;, check it out!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/styling-tables-the-modern-css-way/&quot;&gt;Styling Tables the Modern CSS Way&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Michelle Barker&lt;/a&gt; on July 18, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Over on Piccalilli, Michelle wrote an awesome walkthrough for styling tables using modern techniques. I appreciate the attention to detail here, specifically text alignment in cells.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ericwbailey.website/published/dungeons-and-dragons-taught-me-how-to-write-alt-text/&quot;&gt;Dungeons &amp;amp; Dragons taught me how to write alt text&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ericwbailey.website/&quot;&gt;Eric W. Bailey&lt;/a&gt; on July 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;What a brilliant connection, writing descriptive alt text from lessons learned playing pen-and-paper roleplaying games. Eric explains how to provide context, tone, and mood when describing your images.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://polypane.app/blog/getting-stuck-all-the-ways-position-sticky-can-fail/&quot;&gt;Getting stuck: all the ways position:sticky can fail&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://polypane.app/&quot;&gt;Polypane&lt;/a&gt; on July 14, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;postion: sticky&lt;/code&gt; is one of those CSS properties that I &lt;em&gt;think&lt;/em&gt; I understand, but need a refresher each time I attempt to use it. Thankfully, Kilian provided this awesome primer on the ways you might get stuck with sticky.&lt;/p&gt;
&lt;h2&gt;Special Shout Out&lt;/h2&gt;
&lt;p&gt;I met this amazing lady on the plane ride home, Nadina.&lt;/p&gt;
&lt;p&gt;Nadina is on a mission to save Hawaiian forests, but the way she goes about it is great, as she&apos;s an &lt;a href=&quot;https://nadinascremes.com/pages/nadinas-mission&quot;&gt;ally to some great causes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nadina makes cremes and lotions distributed in handmade ceramic jars. Check out her site, &lt;a href=&quot;https://nadinascremes.com/&quot;&gt;Nadina&apos;s Cremes&lt;/a&gt;, to order some!&lt;/p&gt;
</content:encoded></item><item><title>A Book Apart Books</title><link>https://ryantrimble.com/blog/a-book-apart-books/</link><guid isPermaLink="true">https://ryantrimble.com/blog/a-book-apart-books/</guid><description>Foolishly, I never managed to get the complete collection of A Book Apart books.</description><pubDate>Tue, 23 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have mentioned that I am not much of a &lt;em&gt;book&lt;/em&gt;-reader before, and while I am trying to improve that, this means I was never much of a book-&lt;em&gt;buyer&lt;/em&gt; either.&lt;/p&gt;
&lt;p&gt;Earlier this year, I did manage to snag 20 of the &lt;em&gt;A Book Apart&lt;/em&gt; books through their incredible &quot;20 for $100&quot; deal they were running.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Unfortunately&lt;/strong&gt;, A Book Apart is &lt;a href=&quot;https://abookapart.com/pages/about/&quot;&gt;no longer selling books&lt;/a&gt; and I never managed to get a complete collection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fortunately&lt;/strong&gt;, the authors of each book seem to be in control of what happens to their books, meaning their books are potentially &lt;em&gt;still&lt;/em&gt; available in some way.&lt;/p&gt;
&lt;h2&gt;Still Available A Book Apart Books&lt;/h2&gt;
&lt;p&gt;Here is a list of the books I&apos;ve found so far:&lt;/p&gt;
&lt;h3&gt;Books&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://html5forwebdesigners.com/&quot;&gt;#1 HTML5 For Web Designers&lt;/a&gt; by Jeremy Keith (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://elements-of-content-strategy.abookapart.com/&quot;&gt;#3 The Elements of Content Strategy&lt;/a&gt; by Erin Kissane (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethanmarcotte.com/books/responsive-web-design/&quot;&gt;#4 Responsive Web Design&lt;/a&gt; by Ethan Marcotte (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mobile-first.abookapart.com/&quot;&gt;#6 Mobile First&lt;/a&gt; by Luke Wroblewski (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.designisajob.com/&quot;&gt;#7 Design is a Job&lt;/a&gt; by Mike Monteiro (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://shop.ingramspark.com/b/084?aOlKUb5NlPMogt9kFHpjoMMb7MMkvacuQYbFrA57Oed&quot;&gt;#9 Just Enough Research&lt;/a&gt; by Erika Hall (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://jasonsantamaria.com/#on-web-typography&quot;&gt;#11 On Web Typography&lt;/a&gt; by Jason Santa Maria (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://buttondown.email/muledesign/archive/books-are-cooking/&quot;&gt;#12 You&apos;re My Favorite Client&lt;/a&gt; by Mike Monteiro (Free Online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethanmarcotte.com/books/responsive-design-patterns-and-principles/&quot;&gt;#15 Responsive Design: Patterns &amp;amp; Principles&lt;/a&gt; by Ethan Marcotte (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://goingresponsive.netlify.app/&quot;&gt;#16 Going Responsive&lt;/a&gt; by Karen McGrane (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bookshop.org/p/books/git-for-humans-david-demaree/20097170&quot;&gt;#17 Git for Humans&lt;/a&gt; by David Demaree (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://abookdeparts-dfrl.netlify.app/&quot;&gt;#18 Design for Real Life&lt;/a&gt; by Eric Meyer and Sara Wachter-Boettcher (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://practical-svg.chriscoyier.net/&quot;&gt;#19 Practical SVG&lt;/a&gt; by Chris Coyier (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://abookdeparts.netlify.app/&quot;&gt;#20 JavaScript for Web Designers&lt;/a&gt; by Mat Marquis (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://demystifying-public-speaking.com/&quot;&gt;#21 Demystifying Public Speaking&lt;/a&gt; by Lara Callender Hogan (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accessibilityforeveryone.site/&quot;&gt;#23 Accessibility for Everyone&lt;/a&gt; by Laura Kalbag (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.muledesign.com/blog/conversational-design-for-you&quot;&gt;#25 Conversational Design&lt;/a&gt; by Erika Hall (For purchase/free)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tbrown.org/notes/2024/10/26/flexible-typesetting/&quot;&gt;#27 Flexible Typesetting&lt;/a&gt; by Tim Brown (Free online)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://everydayia.com/&quot;&gt;#29 Everyday Information Architecture&lt;/a&gt; by Lisa Maria Marquis (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://resilient-management.com/&quot;&gt;#30 Resilient Management&lt;/a&gt; by Lara Hogan (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.amazon.com/DESIGN-COGNITIVE-David-Dylan-Thomas/dp/1937557979/&quot;&gt;#33 Design for Cognitive Bias&lt;/a&gt; by David Dylan Thomas (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.etsy.com/listing/1744304352/better-onboarding-original-print-edition?dd_referrer=https://alandalton.github.io/&quot;&gt;#35 Better Onboarding&lt;/a&gt; by Krystal Higgins (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.rachelmcconnell.me/leadingcontentdesign&quot;&gt;#41 Leading Content Design&lt;/a&gt; by Rachel McConnell (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://samkapila.com/books/#where-to-buy-inclusive-design-communities&quot;&gt;#42 Inclusive Design Communities&lt;/a&gt; by Sameera Kapila (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://balsamiq.com/learn/wireframing-book/&quot;&gt;#45 Wireframing for Everyone&lt;/a&gt; by Michael Angeles, Leon Barnard, and Billy Carlson (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethanmarcotte.com/books/you-deserve-a-tech-union/&quot;&gt;#47 You Deserve a Tech Union&lt;/a&gt; by Ethan Marcotte (For purchase)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://survivingchangeatwork.com/&quot;&gt;#48 Surviving Change at Work&lt;/a&gt; by Vanessa Gennarelli (For purchase)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Briefs&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.bethdunn.com/book&quot;&gt;#12 Cultivating Content Design&lt;/a&gt; by Beth Dunn (Free online)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Special Note&lt;/h2&gt;
&lt;p&gt;I&apos;ve purposefully avoided linking to Amazon, many of these books are available there. I have only linked to pages that either provide the free online version, or have multiple purchase options &lt;em&gt;other than&lt;/em&gt; A Book Apart (since they are no longer selling them, duh).&lt;/p&gt;
&lt;p&gt;Let me know if I have missed any, I&apos;ll keep updating this list as I find more! I wanna see these authors continue to get paid for their work!&lt;/p&gt;
&lt;h2&gt;Special Thanks&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Shout out to &lt;a href=&quot;https://yatil.net/&quot;&gt;Eric Eggert&lt;/a&gt;, &lt;a href=&quot;https://jason.cosper.me/&quot;&gt;Jason Cosper&lt;/a&gt;, &lt;a href=&quot;https://coordinate.systems/&quot;&gt;Max Fenton&lt;/a&gt;, and &lt;a href=&quot;https://thefutureislikepie.com/&quot;&gt;Lisa Maria Marquis&lt;/a&gt; for contributing to the list!&lt;/li&gt;
&lt;li&gt;Alan Dalton is putting together a list of the books as well, &lt;a href=&quot;https://alandalton.github.io/Authors-Apart/&quot;&gt;check it out&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>The Bumpkin&apos;s Guide to Surviving Los Angeles</title><link>https://ryantrimble.com/blog/surviving-los-angeles/</link><guid isPermaLink="true">https://ryantrimble.com/blog/surviving-los-angeles/</guid><description>I never expected to visit LA, but now that I&apos;m here, I keep getting excited over street names.</description><pubDate>Sun, 21 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If I were left alone, I probably wouldn&apos;t do much of anything (&lt;em&gt;except&lt;/em&gt; coding). My best friend and partner, Vickie, prompts me to do more - challenging me to break out of my comfort zone. Many of the amazing things I have done in the past few years was due to her support, strength, and love.&lt;/p&gt;
&lt;p&gt;Traveling is one of those things that, without her support, I wouldn&apos;t do. I am an anxious homebody and airport security is one of my worst fears. Once I&apos;m on the plane, I am fine, just the lead up is the worst.&lt;/p&gt;
&lt;p&gt;Now, if you are a follower of my blog, you may think:&lt;/p&gt;
&lt;p&gt;&quot;Ryan, didn&apos;t you go to &lt;a href=&quot;https://ryantrimble.com/blog/london-calling/&quot;&gt;London&lt;/a&gt;, &lt;a href=&quot;https://ryantrimble.com/blog/vue-conf-recap&quot;&gt;New Orleans&lt;/a&gt;, and &lt;a href=&quot;https://ryantrimble.com/blog/visiting-amsterdam-for-css-day&quot;&gt;Amsterdam&lt;/a&gt; in the same year?&quot;&lt;/p&gt;
&lt;p&gt;Why yes, yes I did, and I was terrified to travel those times too. London marked my first trip on a plane &lt;em&gt;ever&lt;/em&gt; in my 30 some years of existence.&lt;/p&gt;
&lt;h2&gt;Flying to the City of Angels&lt;/h2&gt;
&lt;p&gt;This flight was an interesting one. First off, &lt;a href=&quot;https://en.wikipedia.org/wiki/Pete_Buttigieg&quot;&gt;Pete Buttigieg&lt;/a&gt; was a fellow passenger. I wanted to shake his hand, but Vickie advised me not to bother him.&lt;/p&gt;
&lt;p&gt;I hoped with the U.S. Secretary of Transportation on board, it would be a smooth flight, however mother nature had other plans. A rather nasty storm belt came through right as we were boarding the flight, we stayed seated in the plane, on the airport tarmac for roughly two hours before taking off.&lt;/p&gt;
&lt;p&gt;The flight itself was quite eventful as well. You know how in movies, when a passenger is having a medical emergency, the attendants will ask if anyone is a doctor? That played out right in front of us.&lt;/p&gt;
&lt;p&gt;A man in the row ahead passed out mid-conversation with an attendant and she quickly alerted everyone on board. Turns out, the lady in the aisle opposite him was, infact, a doctor and sprung to action immediately. It was both scary seeing the man pass out and awesome seeing the doctor take charge of the situation.&lt;/p&gt;
&lt;p&gt;What was supposed to be a 5-hour flight turned into an &lt;em&gt;almost&lt;/em&gt; 9-hour flight as we were once again delayed on the tarmac after arriving at Los Angeles International Airport. An Alaskan flight broke down at the gate we were to depart at, then the tug vehicle dispatched to move the plane &lt;em&gt;also&lt;/em&gt; broke down.&lt;/p&gt;
&lt;p&gt;I almost gave up hope of getting off that plane, but as we stepped off, it really sank in, we finally made it to Los Angeles.&lt;/p&gt;
&lt;h2&gt;Fear and Anxiety in Los Angeles&lt;/h2&gt;
&lt;p&gt;I am from a &lt;em&gt;very&lt;/em&gt; small town in Pennsylvania, think two streets with an estimated population of about 200 people (according to Wikipedia). It&apos;s a small farm town that contrasts heavily against Los Angeles&apos;s &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_streets_in_Los_Angeles&quot;&gt;30+ arterial thoroughfares&lt;/a&gt;, commercial roads, alleyways and population of 3.8 &lt;em&gt;million&lt;/em&gt; people.&lt;/p&gt;
&lt;p&gt;The trip itself is to celebrate my wife&apos;s birthday, we got to meet her good friend from New Zealand and together they are going to see their favorite band in concert. I&apos;m so happy we were able to accomplish this trip as it seems to be one of those once-in-a-lifetime, stars-aligned, kill-three-birds-with-one-stone type situations.&lt;/p&gt;
&lt;p&gt;I, on the otherhand, feel out of my depth here. Ashamedly, I am quite afraid of many places in the United States. This country is a powder-keg that could go off at anytime, traveling to Europe feels much safer in comparison.&lt;/p&gt;
&lt;p&gt;On top of that, I&apos;ve heard horror stories about Los Angeles &lt;em&gt;my whole life&lt;/em&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rude people&lt;/li&gt;
&lt;li&gt;Worst traffic imaginable&lt;/li&gt;
&lt;li&gt;High crime rates&lt;/li&gt;
&lt;li&gt;Egregious homelessness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Though there is definite truth to these claims, I am finding the experience &lt;em&gt;not as bad&lt;/em&gt; as expected.&lt;/p&gt;
&lt;h2&gt;Cool Places to Visit&lt;/h2&gt;
&lt;p&gt;We decided to stay in Santa Monica for our trip, it&apos;s a rather decent part of L.A. county, with easy access to &lt;a href=&quot;https://www.santamonicapier.org/&quot;&gt;Santa Monica Pier&lt;/a&gt; and beach.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Santa Monica Pier&lt;/h3&gt;
&lt;p&gt;The pier is &lt;em&gt;really&lt;/em&gt; nice, especially if you head down early in the morning.&lt;/p&gt;
&lt;p&gt;Shops on the pier were just opening up and we managed to get amazing breakfast sandwiches from &lt;a href=&quot;https://www.pierburger.com/&quot;&gt;Pier Burger&lt;/a&gt; and iced coffees from the &lt;a href=&quot;https://pacpark.com/restaurants-santa-monica-pier/coffee-bean-tea-leaf/&quot;&gt;Coffee Bean &amp;amp; Tea Leaf&lt;/a&gt; shop.&lt;/p&gt;
&lt;p&gt;After that we decided to drive north on &lt;a href=&quot;https://en.wikipedia.org/wiki/California_State_Route_1&quot;&gt;California State Route 1&lt;/a&gt;, also known as the Pacific Coast Highway, and see some sights. We didn&apos;t plan for anywhere in particular, just headed towards Malibu. The drive is beautiful and I would love to have kept going, but we turned back around as our next stop was Disneyland.&lt;/p&gt;
&lt;h3&gt;Disneyland&lt;/h3&gt;
&lt;p&gt;I&apos;m not particularly a fan of Disney, with one massive exception: &lt;em&gt;Star Wars&lt;/em&gt;. And, even though this was primarily a trip for the wife&apos;s birthday, she managed to &lt;em&gt;surprise me&lt;/em&gt; with tickets to Disneyland and a reservation to build my own &lt;em&gt;Lightsaber&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;After entering the park, the main street is beautiful, though quite crowded. Tons of souvenir shops lining the path until you reach the Walt Disney statue. We were headed for Galaxy&apos;s Edge, the Star Wars portion of the theme park.&lt;/p&gt;
&lt;p&gt;Everything about Galaxy&apos;s Edge is highly detailed to match the look and feel of a location found in the Star Wars universe. It was &lt;em&gt;rad&lt;/em&gt; and I got to see the Millenium Falcon in-person.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Only a couple of complaints here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Signage in Disneyland is awful. I feel like the scheme is that they want you download their app to navigate the park, but I didn&apos;t want to do that. There are paper maps, but figuring out where things are is still difficult.&lt;/li&gt;
&lt;li&gt;Asking cast members questions really takes the magic out the place. I&apos;ve never built a lightsaber before, not sure how many people have, so I was a little confused on where to start - asking questions was met with annoyed answers.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nonetheless, the interactive experience of building a Lightsaber is &lt;em&gt;awesome&lt;/em&gt;. The experience starts at Savi&apos;s Workshop, a small building where cast members perform, guiding you through the build process. You get to select parts and pieces, even choosing a Kyber Crystal to give color to the Lightsaber&apos;s blade. I built a very Sith-inspired Lightsaber, with a red blade.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Griffith Park Observatory&lt;/h3&gt;
&lt;p&gt;One of the places I am familiar with and was hoping to visit was the Observatory at Griffith Park.&lt;/p&gt;
&lt;p&gt;As we climbed the mountain where the Observatory resides, my excitement grew, but was quickly snuffed out due to the parking situation up there. I suppose this is my own fault for not researching ahead, but it turns out the parking seems to be paid street parking, which had cars lined up from the top of the mountain, the whole way down to the bottom.&lt;/p&gt;
&lt;p&gt;We saw the Observatory in all it&apos;s glory from a neighboring ridge, but we were facing quite a hike to see it in-person, so we kept on driving.&lt;/p&gt;
&lt;h3&gt;La Brea Tarpits&lt;/h3&gt;
&lt;p&gt;Another spot I heard about, and luckily quite accessible, is the La Brea Tarpits. These are active pits of liquid asphalt, the crudest of crude oils, that has been capturing animals since the Ice Age. This site is an active paleontological research site, where researchers are working to uncover many fossils in the tar. One room contained 3.5 million fossil specimens.&lt;/p&gt;
&lt;p&gt;When we reached the first tar pit, it really just looked like a pond of water. I can totally understand how animals found themselves caught in the pits, mistaking it for a watering hole. The smell is the first clue though, it does not smell great.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The museum at the Tarpits was interesting and informative. Full skeletal remains of Mastodons, giant sloths, sabre-toothed tigers, condors, even Dire Wolves (which I didn&apos;t know were a real thing, I was only aware of them from &lt;em&gt;Game of Thrones&lt;/em&gt;) and so much more.&lt;/p&gt;
&lt;h3&gt;The Man Behind Winkie&apos;s&lt;/h3&gt;
&lt;p&gt;This was very much a &lt;em&gt;me thing&lt;/em&gt; and I&apos;m not sure I&apos;d recommend it to others, unless you happen to be a fan of director David Lynch&apos;s 2001 film, &lt;a href=&quot;https://en.wikipedia.org/wiki/Mulholland_Drive_(film)&quot;&gt;&lt;em&gt;Mulholland Drive&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the movie, the character of Dan (portrayed by &lt;a href=&quot;https://www.imdb.com/name/nm0279209/&quot;&gt;Patrick Fischler&lt;/a&gt;) meets his psychiatrist at a restaurant called &lt;em&gt;Winkie&apos;s&lt;/em&gt;. Dan describes a dream he had of being in the diner and a terrible vision of a &lt;em&gt;man behind Winkie&apos;s&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;As his psychiatrist pays for their meal, Dan realizes the situation is playing out exactly as it did in his dream. The two men take a walk behind the restaurant to see if there actually is a man back there and... &lt;a href=&quot;https://www.youtube.com/watch?v=UozhOo0Dt4o&quot;&gt;I won&apos;t spoil the reveal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The real-life filming location was a &lt;em&gt;Caesar&apos;s&lt;/em&gt; restaurant, on West El Segundo Boulevard, and I was determined to see for myself if there really was a man behind Winkie&apos;s.&lt;/p&gt;
&lt;p&gt;The area is a bit sketchy, but honestly most of L.A. seems sketchy.&lt;/p&gt;
&lt;p&gt;The Caeser&apos;s restaurant is still standing, though time has taken it&apos;s toll. It no longer operates as a restaurant as it&apos;s boarded up, but still recognizable from the film. The steps on the corner of the parking lot lead to the back of the building, where the man behind Winkie&apos;s should be, and to my relief, was vacant &lt;em&gt;this time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Tips to Survive L.A.&lt;/h2&gt;
&lt;p&gt;I&apos;m not an expert on Los Angeles, traveling, or... anything &lt;em&gt;really&lt;/em&gt;, so take the following advice lightly as your experience may vary. Here are some things I have learned:&lt;/p&gt;
&lt;h3&gt;Traffic is fine, rent a car&lt;/h3&gt;
&lt;p&gt;If you are going to LA, I suggest renting a car for your trip if you can. Of course some spots might have heavier traffic at times, but driving is maybe the easiest way to get around in my opinion.&lt;/p&gt;
&lt;p&gt;Public transportation, ride-sharing apps, and electric scooters are totally an option, so don&apos;t worry if you don&apos;t drive. Prices for Uber and Lyft seem a bit steeper here, though.&lt;/p&gt;
&lt;p&gt;If you do decide to drive, you will need to get good at driving around stuff. Street-parked cars, pedestrians, bus stops, and many other random things jump in front of your car at anytime, so stay alert.&lt;/p&gt;
&lt;p&gt;If you are reading this and happen to be a resident of Los Angeles county: please use your turn signals, they are the thing that lets other dtivers know you are about to cut them off.&lt;/p&gt;
&lt;p&gt;The one caveat to renting a car is parking. Always check if your destination has parking, either on-site or a nearby lot. We have only paid for parking twice so far, which sucks, but a surprising amount of places have free lots. Also, parking spots are SUPER tight here, so consider a smaller rental vehicle. We got a hybrid Toyota with awesome gas-mileage.&lt;/p&gt;
&lt;p&gt;Exploring the area by car is actually super fun. We have mostly opt to &quot;avoid highways&quot; when navigating to a location using Google Maps, which gives us a much better feel for the various cities that make up Los Angeles county. There are a lot of really beautiful neighborhoods here, with lush greenery and tall palm trees. One of our best experiences was driving up the Pacific Coast Highway towards Malibu.&lt;/p&gt;
&lt;p&gt;If you ever played &lt;a href=&quot;https://www.youtube.com/watch?v=QkkoHAzjnUs&quot;&gt;Grand Theft Auto V&lt;/a&gt;, you will recognize &lt;em&gt;a lot&lt;/em&gt; of the city.&lt;/p&gt;
&lt;h3&gt;Research Hotels&lt;/h3&gt;
&lt;p&gt;If you plan on staying in a hotel, definitely do some research on the area surrounding the hotel. You may not end up with the cheapest rates, but it may be worthwile for your personal safety and security.&lt;/p&gt;
&lt;p&gt;Along with making sure a hotel is safe, make sure there is on-site parking in some way.&lt;/p&gt;
&lt;p&gt;We have stayed in two hotels on our trip:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.santamonicahotel.com/&quot;&gt;Santa Monica Hotel&lt;/a&gt; - The first hotel was right next to the Pier, so we had easy access to the beach. Parking was tight and you could hear through the walls, but it was mostly nice.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://foundhotels.com/cities/santa-monica/&quot;&gt;FOUND Hotel&lt;/a&gt; - The second hotel is great and if I were to come back, I would probably opt to stay here again. The one downside is the parking situation, they have a limited parking garage under the building, first come, first serve style. There is also on-street parking and a garage, however it seemed to be a twenty-minute walk away.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We were originally going to stay in a different hotel more towards downtown L.A., however upon looking at reviews, the place seemed rather unsavory.&lt;/p&gt;
&lt;h3&gt;Ralphs vs. Whole Foods&lt;/h3&gt;
&lt;p&gt;The two primary grocery stores in Los Angeles are Ralphs and Whole Foods. I&apos;m not about to compare prices, almost certainly Whole Foods will be more expensive, but Ralphs is an experience all on it&apos;s own.&lt;/p&gt;
&lt;p&gt;I only went to Whole Foods once so far, it reminded me of Wegman&apos;s, which is what I&apos;m used to back home. The store was nice and clean, easy to get in and out.&lt;/p&gt;
&lt;p&gt;Ralphs on the other hand is wild. There are lots of these stores throughout the area, and are generally open later than Whole Foods - so I managed to go more than once.&lt;/p&gt;
&lt;p&gt;Each Ralphs store I went in had similar setups of the entrance being blocked. This requires you enter through the exit and down one of the cashier aisles. It feels like you are breaking some unwritten law.&lt;/p&gt;
&lt;h3&gt;Don&apos;t go to Olive Garden&lt;/h3&gt;
&lt;p&gt;This is just life advice, really, it is not a good restaurant - however, everything is made better with friends.&lt;/p&gt;
&lt;p&gt;It turns out there aren&apos;t any Olive Garden restaurants in New Zealand (which is for the best), but the reputation of it being &quot;good&quot; reached our kiwi friends who wanted to give it a try.&lt;/p&gt;
&lt;p&gt;Food aside, it was quite fun to hang out and hear other&apos;s experiences visiting the country. Also, our waitress was wonderful!&lt;/p&gt;
&lt;h3&gt;Fast Food is everywhere&lt;/h3&gt;
&lt;p&gt;L.A. is home to every fast food chain available. You have the normal ones: McDonald&apos;s, Burger King, Taco Bell, etc... but there are so many more.&lt;/p&gt;
&lt;p&gt;Region specific chains such as In-n-Out, Jack in the Box, El Pollo Loco are everywhere, but the surprising part is how many small business restaurants compete against these larger chains. Maybe my definition of &quot;fast food&quot; is skewed, I consider restaurants with a drive-thru lane to be fast food.&lt;/p&gt;
&lt;p&gt;I tried &lt;a href=&quot;https://www.in-n-out.com/&quot;&gt;In-n-out&lt;/a&gt;, &lt;a href=&quot;https://www.jackinthebox.com/&quot;&gt;Jack in the Box&lt;/a&gt;, and &lt;a href=&quot;https://www.elpolloloco.com/&quot;&gt;El Pollo Loco&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-n-out, I ordered their #1 combo - a double cheeseburger with fries. The burger wasn&apos;t much to write home about, but the fries are great! They remind me of boardwalk fries.&lt;/li&gt;
&lt;li&gt;Jack in the Box currently has a spicy chicken tenders meal promoting the new Deadpool movie. These were pretty decent, though I couldn&apos;t quite eat all of them. Jack&apos;s curly fries were decent, but were cold by the time I got back to my hotel.&lt;/li&gt;
&lt;li&gt;El Pollo Loco was honestly great. It&apos;s pretty similar to KFC, but they give you tortillas for some reason, and I really liked their hot sauce. Now, have I been confusing this chain for the fictitious chain, &quot;Los Pollos Hermanos&quot; managed by &lt;em&gt;Gustavo Fring&lt;/em&gt; from Vince Gilligan&apos;s &lt;em&gt;Breaking Bad&lt;/em&gt;? Absolutely.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Taco Trucks&lt;/h3&gt;
&lt;p&gt;Another option for food, and one of my favorite things about the trip, is all the food trucks.&lt;/p&gt;
&lt;p&gt;In Pennsylvania, food trucks aren&apos;t the same thing as what happens here. PA Food Trucks are kind of like mobile catering services, where you might invite them to an event or workplace for folks to enjoy.&lt;/p&gt;
&lt;p&gt;In Los Angeles, food trucks are conveniently located on many streets. There are a variety of different cuisines available, but Mexican seems to be the most popular as Taco Trucks are &lt;em&gt;most places&lt;/em&gt; that we explored.&lt;/p&gt;
&lt;p&gt;We ordered from a Taco Truck right outside our hotel one night, it was fantastic!&lt;/p&gt;
&lt;h2&gt;Returning Home&lt;/h2&gt;
&lt;p&gt;Today is my last day here in Los Angeles, and while it has been a super interesting trip, I miss my pets a lot. I&apos;ll be super happy to see them when we get back to PA.&lt;/p&gt;
&lt;p&gt;I&apos;ll be catching a flight back to Baltimore early tomorrow morning, hoping for a much smoother flight!&lt;/p&gt;
</content:encoded></item><item><title>What&apos;s cool about Coolify?</title><link>https://ryantrimble.com/blog/whats-cool-about-coolify/</link><guid isPermaLink="true">https://ryantrimble.com/blog/whats-cool-about-coolify/</guid><description>I heard about Coolify at the beginning of the week and had to wait the whole week in order to try it out, but I finally did and it&apos;s awesome.</description><pubDate>Sun, 14 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I haven&apos;t thought about hosting in a long time, as my default solution is &lt;a href=&quot;https://netlify.com/&quot;&gt;Netlify&lt;/a&gt;. I&apos;ve been happily using their services for a few years now, but lately have been wondering about alternatives.&lt;/p&gt;
&lt;p&gt;In more recent years I&apos;ve noticed Netlify become more &lt;em&gt;enterprise&lt;/em&gt;, no more &lt;em&gt;&quot;JAMstack&quot;&lt;/em&gt;, and the layoffs... I feel for the folks affected. From a customer standpoint, I don&apos;t see them doing the fun things they used to. Looking at the landscape of similarly functioning hosting providers, it&apos;s not much better. In fact, I&apos;d still argue Netlify is the best option between other popular solutions.&lt;/p&gt;
&lt;p&gt;Vercel is Netlify&apos;s largest competition and if you happen to be a NextJS developer, their vendor-provided-ecosystem certainly has everything you need to work efficiently there. Of course, being a NextJS developer is not a requirement (I am not one), but their products are understandably tailored towards that experience.&lt;/p&gt;
&lt;p&gt;All that to say, I haven&apos;t really thought about it in a while - until recently, when I came across &lt;a href=&quot;https://coolify.io/&quot;&gt;Coolify&lt;/a&gt; on a &lt;a href=&quot;https://mastodon.social/@inkyvoxel/112751969545914492&quot;&gt;Mastodon post by Mark Brady&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Wtf is Coolify?&lt;/h2&gt;
&lt;p&gt;That was my first question when I read the post. It turns out it is a &quot;Netlify-in-a-box&quot; tool. Many of the neat features Netlify makes so easy, all built into one application!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Administrator dashboard to manage projects&lt;/li&gt;
&lt;li&gt;Per project deployment configurations&lt;/li&gt;
&lt;li&gt;Connects to git repositories for pull request deployments&lt;/li&gt;
&lt;li&gt;Automatic SSL certification management though &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let&apos;s Encrypt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;and a bunch more stuff!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why it is so interesting to me is that it&apos;s open-source with a self-hosted version available. Actually, it seems like the self-hosted version is the preferred approach.&lt;/p&gt;
&lt;p&gt;I haven&apos;t managed my own servers in a while. Before making the career switch to development, I worked as a network engineer who helped manage many different servers for many different things.&lt;/p&gt;
&lt;p&gt;When I started coding, I managed a few &lt;em&gt;virtual private servers&lt;/em&gt; (VPS) for hosting &lt;em&gt;WordPress&lt;/em&gt; and other PHP applications. Once &lt;em&gt;JAMstack&lt;/em&gt; became popular though, I haven&apos;t a need to concern myself with this part of it, so &lt;em&gt;do I still remember even how to do that?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, yeah &lt;em&gt;I&lt;/em&gt; do, &lt;em&gt;I worked with this stuff for many years&lt;/em&gt; - your experience may vary though, but I promise it&apos;s not that difficult. Let me show you!&lt;/p&gt;
&lt;h2&gt;Setting up a Server&lt;/h2&gt;
&lt;p&gt;First thing, we need a server. I went with a &lt;a href=&quot;https://digitalocean.com/&quot;&gt;Digital Ocean&lt;/a&gt; droplet. I like Digital Ocean compared to things like &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;Amazon Web Services&lt;/a&gt; (AWS), as I find AWS fairly confusing compared to Digital Ocean&apos;s user-friendly approach. Researching providers is always a good idea, some tools may provide better pricing options than others as well.&lt;/p&gt;
&lt;p&gt;To create a droplet on Digital Ocean, click the &lt;strong&gt;Create&lt;/strong&gt; button in the top navigation, then select &lt;strong&gt;Droplet&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;On the next page, you will get to select server configuration options. On &lt;a href=&quot;https://coolify.io/docs/installation&quot;&gt;Coolify&apos;s documentation site&lt;/a&gt;, you can see the requirements for a Coolify instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Debian, RedHat, Arch, Suse, or Raspberry Pi&apos;s Raspbian flavors of Linux are supported&lt;/li&gt;
&lt;li&gt;AMD64 or ARM64 architectures&lt;/li&gt;
&lt;li&gt;Recommended: 2 CPUs, 2GB memory, 30+ GB of storage for Docker images&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now if the words in that list did not mean anything to you, then here is exactly what I selected on the droplet create form:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Region: select the area closest to you, though it shouldn&apos;t matter which region you select.&lt;/li&gt;
&lt;li&gt;Datacenter: select the datacenter closest to you&lt;/li&gt;
&lt;li&gt;Choose an Image: Ubuntu 24.04 (LTS) x64&lt;/li&gt;
&lt;li&gt;Droplet Type: Basic&lt;/li&gt;
&lt;li&gt;CPU Options: Regular - Disk Type SSD&lt;/li&gt;
&lt;li&gt;Server Option: $18/mo option which includes
&lt;ul&gt;
&lt;li&gt;2GB RAM&lt;/li&gt;
&lt;li&gt;2 CPUs&lt;/li&gt;
&lt;li&gt;60GB SSD Disk&lt;/li&gt;
&lt;li&gt;3TB transfer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Backups are optional, if you are launching a production site I&apos;d recommend enabling backups or finding an alternative strategy.&lt;/li&gt;
&lt;li&gt;Choose Authentication Method: Password (Enter a strong password, this will be your &lt;code&gt;root&lt;/code&gt; user password)&lt;/li&gt;
&lt;li&gt;Provide a hostname to identify your server, or just leave the randomly generated name&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All other choices are optional, but feel free to customize your server for your needs.&lt;/p&gt;
&lt;p&gt;Once all choices have been made, click &lt;strong&gt;Create Droplet&lt;/strong&gt;. You can easily adjust the droplets settings later, if you find your choices don&apos;t seem to have enough resources.&lt;/p&gt;
&lt;p&gt;After Digital Ocean finishes launching your new server, you can connect to it via the browser by clicking the &lt;strong&gt;Console&lt;/strong&gt; button. You will be presented with the Linux terminal command line interface, this is where we will run commands to set up Coolify!&lt;/p&gt;
&lt;h2&gt;Installing Coolify&lt;/h2&gt;
&lt;p&gt;I cannot express how simple this part is, the folks at coolLabs Technologies should be proud of themselves for this one.&lt;/p&gt;
&lt;p&gt;On the Linux command line, we can run this command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This install script will setup everything we need for Coolify, give it some time, make a coffee - although it is rather fast to complete.&lt;/p&gt;
&lt;p&gt;You will know it is finished when you are returned to the command line prompt. I did not encounter any errors running this command, though if you happen to experience issues, double check permissions before running the command again.&lt;/p&gt;
&lt;p&gt;You should now be able to browse to the Coolify instance by entering your droplet&apos;s public IP address, on port &lt;code&gt;8000&lt;/code&gt;, into your browser.&lt;/p&gt;
&lt;h2&gt;Setting up a Project&lt;/h2&gt;
&lt;p&gt;The first time you access the Coolify instance, it will ask you to setup an account. Keep in mind this is not an account through some external service, this is an account to manage the Coolify administrator dashboard. This account is local to your server. I say this as I&apos;m sure some folks may be cautious setting up another account for something.&lt;/p&gt;
&lt;p&gt;Once you are in, Coolify will provide a small tutorial to help acclimate you to the dashboard. I followed through these prompts to understand how to use the interface and found it quite helpful.&lt;/p&gt;
&lt;p&gt;One thing that sort of confused me was how I set up a project, then inside I needed to create another object, a &lt;code&gt;resource&lt;/code&gt;, which is where my application would reside. I didn&apos;t quite grasp this initially as I expected a project to equal an application. This is actually &lt;em&gt;cooler&lt;/em&gt; as I can independently deploy related parts of an application. There is a few scenarios that came to mind.&lt;/p&gt;
&lt;p&gt;One example might be to create various environments for an application. A project might contain resources like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Production server&lt;/li&gt;
&lt;li&gt;Staging Server&lt;/li&gt;
&lt;li&gt;Development Server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alternatively, you could house a full stack application with resources such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frontend interface, like a reactive framework or single page application.&lt;/li&gt;
&lt;li&gt;Backend to deliver application endpoints&lt;/li&gt;
&lt;li&gt;Database to store data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When setting up a resource, there are a few approaches. I selected the option to deploy from a private repository on GitHub. I wanted to test Coolify out by deploying my personal website through the application.&lt;/p&gt;
&lt;p&gt;During this step, I had expected to be able to select the repo from a list of my repositories in order to deploy the application. I was interrupted in this process as Coolify has to set up your GitHub account as a &lt;strong&gt;source&lt;/strong&gt;. This seemed to make sense, so I followed the prompts to connect my GitHub account to the Coolify instance.&lt;/p&gt;
&lt;p&gt;After enabling GitHub as a source, I was then able to select my personal website as a project resource. I used all default options and watched in anticipation as it attempted it&apos;s deployment.&lt;/p&gt;
&lt;p&gt;It failed spectacularly. I don&apos;t blame it, I&apos;m not sure why I expected anything different. There are a couple of things to figure out.&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;Build Pack&lt;/strong&gt;, I used the default selection of &lt;code&gt;Nixpacks&lt;/code&gt; which is a tool used to &lt;a href=&quot;https://nixpacks.com/docs&quot;&gt;build an application as a container&lt;/a&gt; (such as a Docker image).&lt;/p&gt;
&lt;p&gt;Down in the &lt;strong&gt;Build&lt;/strong&gt; section, I noticed where I could add commands for &lt;code&gt;Install&lt;/code&gt;, &lt;code&gt;Build&lt;/code&gt;, and &lt;code&gt;Start&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I have been using &lt;code&gt;pnpm&lt;/code&gt; lately, so for the installation command, I set it as &lt;code&gt;pnpm install&lt;/code&gt;. Similarly for the build command: &lt;code&gt;pnpm build&lt;/code&gt;. For the Start command, I did not quite know what to say.&lt;/p&gt;
&lt;p&gt;My website is powered by Astro and as I&apos;m currently using Netlify, the lovely Netlify adapter provided by Astro sort of handles that for me. I realized this was one of the first things I would need to sort out to properly deploy my website, but as I was just testing things, I added &lt;code&gt;pnpm start&lt;/code&gt; as the start command.&lt;/p&gt;
&lt;p&gt;I also ensured that the &lt;strong&gt;Base Directory&lt;/strong&gt; and &lt;strong&gt;Publish Directory&lt;/strong&gt; were both set accordingly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Base Directory: &lt;code&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pubslish Directory: &lt;code&gt;/dist&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One more thing, under the &lt;strong&gt;Network&lt;/strong&gt; heading, you need to set the proper port to expose where your application is running. For Astro, they cheekingly use the port of &lt;code&gt;:4321&lt;/code&gt; to signify the takeoff of a new website. With the port set, I could now attempt a re-deploy.&lt;/p&gt;
&lt;p&gt;This time I watched in amazement as it actually kind of worked. My website infact did deploy, and as expected it was in &lt;code&gt;development&lt;/code&gt; mode. I was running the Astro dev server on my Coolify instance and that felt like progress!&lt;/p&gt;
&lt;h2&gt;Converting My Website&lt;/h2&gt;
&lt;p&gt;So, first thing first - I created a new branch of my website&apos;s repository, there are a few things I&apos;m going to need to change that I don&apos;t necessarily want to affect my &lt;em&gt;actual&lt;/em&gt; website. Coolify lets you deploy from specified branches within a selected repository, so I can safely perform some conversions without harming my Netlify hosted site.&lt;/p&gt;
&lt;p&gt;Next, I removed the Astro Netlify adapter using &lt;code&gt;pnpm&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pnpm uninstall @astrojs/netlify&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;astro.config.mjs&lt;/code&gt;, I needed to remove references to the Netlify adapter package, so I deleted the line importing it and removed the &lt;code&gt;adapter: netlify()&lt;/code&gt; key/value pair from my &lt;code&gt;defineConfig&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;If I were to generate my website as a 100% static website, I wouldn&apos;t necessarily need to worry about this part, however I like to take advantage of Astro&apos;s server side rendering functionality, but I wasn&apos;t clear on how to make that happen &lt;em&gt;without&lt;/em&gt; Netlify. The &lt;code&gt;@astrojs/netlify&lt;/code&gt; adapter kind of just &lt;em&gt;does things&lt;/em&gt; for me without me worrying about that. Astro provides a much more &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/node/&quot;&gt;generic adapter integration&lt;/a&gt; to run itself as a plain Node application, which also supports server side rendering.&lt;/p&gt;
&lt;p&gt;I installed the &lt;code&gt;@astrojs/node&lt;/code&gt; adapter by running:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pnpm astro add node
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This prompted me to add the adapter to my &lt;code&gt;astro.config.mjs&lt;/code&gt; file, which I agreed to.&lt;/p&gt;
&lt;p&gt;This still doesn&apos;t quite answer what that start command should be, but it has gotten us closer. Checking out the Astro docs site for the &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/node/&quot;&gt;Node adapter&lt;/a&gt;, you can run the application in &lt;code&gt;standalone&lt;/code&gt; mode or as &lt;code&gt;middleware&lt;/code&gt;, like if you needed to use &lt;a href=&quot;https://expressjs.com/&quot;&gt;Express&lt;/a&gt; or &lt;a href=&quot;https://fastify.dev/&quot;&gt;Fastify&lt;/a&gt; to do some things ahead of rendering a page.&lt;/p&gt;
&lt;p&gt;I messed around with the &lt;code&gt;middleware&lt;/code&gt; option for a moment, though I could not successully figure it out/ I wasn&apos;t too concerned as it wasn&apos;t necessary for this particular project, so I switched back to &lt;code&gt;standalone&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, we finally have our answer on how to start the site. With the Node adapter in place, running the build command will create the &lt;code&gt;/dist&lt;/code&gt; folder containing &lt;code&gt;client&lt;/code&gt; and &lt;code&gt;server&lt;/code&gt; directories. Inside the &lt;code&gt;server&lt;/code&gt; path, is the &lt;code&gt;entry.mjs&lt;/code&gt; file which can be used to start the server.&lt;/p&gt;
&lt;p&gt;Now to launch the production built version of the website, &lt;em&gt;with server side rendering&lt;/em&gt;, I can run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node ./dist/server/client.js`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And it works!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Two things seem broken though: A missing environment variable and the contact form no longer processes submissions.&lt;/p&gt;
&lt;p&gt;Over on my &lt;a href=&quot;/now&quot;&gt;/now&lt;/a&gt; page, I have an Astro component that connects to the &lt;a href=&quot;https://last.fm/&quot;&gt;LastFM&lt;/a&gt; API and pulls in my most recently listened to track. On Netlify, I store my API key as an environment variable. And on Coolify, I can do the same thing!&lt;/p&gt;
&lt;p&gt;There is an &lt;strong&gt;Environment Variables&lt;/strong&gt; option in the project configuration, I added the same key here matching my Netlify deployment:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;A redeploy of the site corrects the bug present on the &lt;code&gt;/now&lt;/code&gt; page.&lt;/p&gt;
&lt;p&gt;The form processing bit is where the problem of vendor lock-in comes in. I use Netlify&apos;s forms feature to process form submissions. I have a few ideas in mind on how to handle this, but for the time being I do not need my test site to submit forms.&lt;/p&gt;
&lt;p&gt;Other than the forms, my site was working as intended. Now the only odd thing was the domain. I had been using the randomly generated domain name that Coolify provided to the instance, which looked like this: &lt;code&gt;https://ryan-trimble.174.138.64.40.sslip.io/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This URL address consisted of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The project name&lt;/li&gt;
&lt;li&gt;My droplet&apos;s IP addres&lt;/li&gt;
&lt;li&gt;and &lt;code&gt;sslip.io&lt;/code&gt; - which I hadn&apos;t heard of&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Turns out, &lt;a href=&quot;https://sslip.io&quot;&gt;sslip.io&lt;/a&gt; is a simple domain name service that returns the site of whatever the embedded IP address is. Now, how would that make it different from just typing in the IP address of the droplet you may be wondering, well that is where the project name in the URL comes in as a subdomain. Coolify is already managing the routing for my server, so I just needed to add a real domain.&lt;/p&gt;
&lt;h2&gt;Managing Domains&lt;/h2&gt;
&lt;p&gt;If you, like me, previously used Google as a domain name registrar, you might have to log into &lt;a href=&quot;https://squarespace.com/&quot;&gt;Squarespace&lt;/a&gt; now to manage your domains.&lt;/p&gt;
&lt;p&gt;I own both &lt;code&gt;ryantrimble.com&lt;/code&gt; and &lt;code&gt;ryantrimble.dev&lt;/code&gt; domains. I like to use the &lt;code&gt;.dev&lt;/code&gt; domain to do weird experiments (like the topic of this post), but usually end up forwarding it back to the &lt;code&gt;.com&lt;/code&gt; address. So for my purposes, I&apos;m going to use my &lt;code&gt;.dev&lt;/code&gt; domain to point to my Digital Ocean droplet, the Coolify instance. These instructions will work for new domains as well, but for existing domains I have a bit of a warning:&lt;/p&gt;
&lt;p&gt;We will need to tell our domain name registrar where to point the domain. In this case, I will be telling Squarespace that I want Digital Ocean to be managing the domain name records by using their nameservers. If your existing domain has a more complicated DNS record configuration, I would recommend an alternate approach as this will break those records.&lt;/p&gt;
&lt;p&gt;In Squarespace, I clicked &lt;strong&gt;Domains&lt;/strong&gt;, chose the domain I wanted to manage, then &lt;strong&gt;DNS&lt;/strong&gt; in the side navigation. The sidebar navigation expands and provides more options, I selected &lt;strong&gt;Domain Nameservers&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Enable custom nameservers, here we will need to enter Digital Ocean&apos;s nameserver addresses, provided in their documentation. Their nameservers are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ns1.digitalocean.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ns2.digitalocean.com&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ns3.digitalocean.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After these nameservers are set, we can switch over to the Digital Ocean side to add the domain to our droplet. In the Digital Ocean administration panel, click &lt;strong&gt;Networking&lt;/strong&gt; in the left navigation, then choose the &lt;strong&gt;Domains&lt;/strong&gt; tab within the page.&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;Add a domain&lt;/strong&gt; input, I entered my domain and my droplet was preselected, as that was my only droplet. Click &lt;strong&gt;Add Domain&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By default, I saw three DNS records already in place, all &lt;code&gt;NS&lt;/code&gt; records directed from the Digital Ocean nameservers.&lt;/p&gt;
&lt;p&gt;I wanted my Coolify instance to be accessible from a subdomain, so I added an &lt;code&gt;A&lt;/code&gt; record for &lt;code&gt;coolify.ryantrimble.dev&lt;/code&gt; that points to my instance. This worked nearly instantly, I was sort of surprised as domain name propagation sometimes takes a while. Browsing to: &lt;code&gt;https://coolify.ryantrimble.dev/&lt;/code&gt; brought me right to the Coolify dashboard.&lt;/p&gt;
&lt;p&gt;I made a mistake here, only to realize later (maybe to my benefit) that I did not actually set a DNS record for the plain &lt;code&gt;ryantrimble.dev&lt;/code&gt; domain. Had I done this at this point, I believe it would have worked exactly the same as the subdomain I set up first.&lt;/p&gt;
&lt;p&gt;Instead, I navigated my way to my project&apos;s settings and attempted to add it as the domain there. Navigating to &lt;code&gt;ryantrimble.dev&lt;/code&gt; failed to return anything at all and this is when I realized the error.&lt;/p&gt;
&lt;p&gt;Back on the Digital Ocean domain management page, I added the naked domain &lt;code&gt;A&lt;/code&gt; record using &lt;code&gt;@&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Since I already set the domain within the project on Coolify, things started working almost right away. I think there was a caching issue on my laptop, as it did not load immediately there, but testing on my mobile device yielded my website in all it&apos;s glory.&lt;/p&gt;
&lt;p&gt;You can try it out yourself by browsing to &lt;a href=&quot;https://ryantrimble.dev/&quot;&gt;ryantrimble.dev&lt;/a&gt; - you will see my website exactly as it is here (though maybe without this particular post). One thing to note is that I still haven&apos;t fixed the forms, so attempting to submit a contact request from that site will fail.&lt;/p&gt;
&lt;h2&gt;Setting up a Firewall&lt;/h2&gt;
&lt;p&gt;A very brief note about securing your droplet. If you are using Digital Ocean, they seem to have made Firewall management ridiculously easier than the last time I messed around with these things.&lt;/p&gt;
&lt;p&gt;Browse to &lt;strong&gt;Networking&lt;/strong&gt;, then click the &lt;strong&gt;Create Firewall&lt;/strong&gt; button. By default it&apos;ll have a very locked down configuration, in fact you won&apos;t even be able to browse to your site now if you try.&lt;/p&gt;
&lt;p&gt;Within the &lt;strong&gt;Inbound Rules&lt;/strong&gt; section, there should be a pre-defined rule for SSH (port &lt;code&gt;22&lt;/code&gt;). This is necessary for you to be able to actually remotely control your droplet, so do not delete this. Instead, we want to add a couple of rules to enable visitors to view our websites.&lt;/p&gt;
&lt;p&gt;I added &lt;code&gt;HTTP&lt;/code&gt; and &lt;code&gt;HTTPS&lt;/code&gt; (ports &lt;code&gt;80&lt;/code&gt; and &lt;code&gt;443&lt;/code&gt;) to the Firewall, which now allowed traffic into my server, and the website became accessible again.&lt;/p&gt;
&lt;p&gt;Another rule I added, which is totally up to you, is &lt;code&gt;ICMP&lt;/code&gt; as that refers to the common networking protocol of &lt;code&gt;ping&lt;/code&gt;. If I were to see my website as non-responsive, I can &lt;code&gt;ping ryantrimble.dev&lt;/code&gt; in my terminal to see if I get any response, helping debug if it is a browser, network, or connection related issue.&lt;/p&gt;
&lt;p&gt;You may need to adjust the firewall for your use-case, but keeping it slim and locked down is a good step towards server security.&lt;/p&gt;
&lt;h2&gt;My Plan&lt;/h2&gt;
&lt;p&gt;At this moment, I&apos;m still hosting my website on Netlify. I&apos;m super impressed with Coolify and I think I&apos;m going to make the plunge. I&apos;ll obviously need to figure out an alternative to Netlify forms, but that should not be difficult.&lt;/p&gt;
&lt;p&gt;Another consideration now is storage space. I was able to host as many websites as I wanted on Netlify, however there is a hard storage limit on my droplet, unless I want to pay more.&lt;/p&gt;
&lt;p&gt;I most likely will keep the few client sites I run on Netlify for the time being, or possibly set up a separate Coolify instance for them. I don&apos;t want my personal website / experiments affecting my client&apos;s sites.&lt;/p&gt;
&lt;p&gt;Let me know if you have been enjoying Coolify or are interested to find out more information about it!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #12</title><link>https://ryantrimble.com/blog/weekly-roundup-12/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-12/</guid><description>Mia got the CSS zoomies, considerations for HTML web components, and a list of great accessibility resources!</description><pubDate>Sat, 13 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;What a week! Next week is looking pretty stacked as well, as I&apos;m headed off to sunny Los Angeles for a few days. Let me know if you have any suggestions for things to check out, I&apos;m currently planning to find out &lt;a href=&quot;https://www.youtube.com/watch?v=3Tb06kMIQCY&quot;&gt;if there really is a man behind Winkies&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://knowler.dev/blog/a-custom-element-smoke-test&quot;&gt;A custom element smoke test&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://knowler.dev/&quot;&gt;Nathan Knowler&lt;/a&gt; on July 11, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Interesting considerations for the &quot;HTML Web Components&quot; conversation, Nathan demonstrates some pitfalls developers may fall into while performing light DOM operations inside web components.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.oddbird.net/2024/07/09/zoomies/&quot;&gt;Zoom, zoom, and zoom&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.miriamsuzanne.com/&quot;&gt;Miriam Suzanne&lt;/a&gt; on July 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Mia explains the three types of zoom an author of CSS might contend with, don&apos;t tell Mia about my secret &lt;em&gt;fourth zoom&lt;/em&gt; (I get really close to my monitor).&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://jai.me/blog/2024-07-06-vue-3-shadow-root/&quot;&gt;Getting to the (shadow)root of Vue 3 custom elements&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jai.me/&quot;&gt;Jaime Jones&lt;/a&gt; on July 6, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;In case you missed it, last weekend I helped my friend and co-worker, Jaime, launch her new website! This was the first post in her new digs.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://reactormag.com/furiosa-and-the-disability-wasteland/&quot;&gt;Furiosa and the Disability Wasteland&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://reactormag.com/author/elsa-sjunneson-henry/&quot;&gt;Elsa Sjunneson&lt;/a&gt; on June 12, 2024&lt;/p&gt;
&lt;p&gt;shared by &lt;a href=&quot;https://stephaniewalter.design/blog/pixels-of-the-week-july-7-2024/&quot;&gt;Stephanie Walter&lt;/a&gt; on July 7, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Stef Walter shared this awesome piece discussing the parallels of George Miller&apos;s film &lt;em&gt;Furiosa&lt;/em&gt; to that of folks with disabilities. Consider subscribing to &lt;a href=&quot;https://stephaniewalter.design/subscribe-to-the-blog-updates/&quot;&gt;Stef&apos;s newsletter&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; go watch &lt;em&gt;Furiosa&lt;/em&gt;, it&apos;s rad!&lt;/p&gt;
&lt;h2&gt;Accessibility Resources&lt;/h2&gt;
&lt;p&gt;Some fine folks in the Frontend Horse community shared several great resources to dig into accessibility.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/fundamentals/&quot;&gt;Accessibility Fundamentals Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/WAI/courses/foundations-course/&quot;&gt;Digital Accessibility Foundations
Free Online Course&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://a11yphant.com/&quot;&gt;a11yphant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/curriculum/core/accessibility/&quot;&gt;MDN Curriculum - Accessibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.a11yproject.com/resources/&quot;&gt;The A11y Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://inclusivedesignprinciples.info/&quot;&gt;Inclusive Design Principles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks for sharing these great links, &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; and &lt;a href=&quot;https://sarajoy.dev/&quot;&gt;Sara Joy&lt;/a&gt;!&lt;/p&gt;
</content:encoded></item><item><title>New Website: Jaime Jones</title><link>https://ryantrimble.com/blog/new-website-jaime-jones/</link><guid isPermaLink="true">https://ryantrimble.com/blog/new-website-jaime-jones/</guid><description>My friend (and co-worker) Jaime expressed interest in blogging again, so I helped her out by redesigning her site! Everybody say &quot;Hi Jaime!&quot;</description><pubDate>Sat, 06 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the past few weekends, I have been putting together a redesign for my friend Jaime&apos;s blog! I&apos;m not like &lt;em&gt;done&lt;/em&gt; done with it, there are a few rough edges to smooth out yet - also, I have a couple of fun surprises that I know she will appreciate. All that to say, the website is now &lt;a href=&quot;https://jai.me/&quot;&gt;live&lt;/a&gt;! (with a &lt;em&gt;sick&lt;/em&gt; domain name, might I add.)&lt;/p&gt;
&lt;p&gt;I have been focusing a lot on building design systems lately, so it was super fun to build off of that knowledge in a bit of a scaled back way. I used lots of modern CSS techniques with the design and I&apos;m quite happy with how it turned out.&lt;/p&gt;
&lt;p&gt;For the framework, I used &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;. I am an Astro fanboy, however if you know Jaime, you know know she is &lt;em&gt;big fan&lt;/em&gt; of &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt;. I think Astro is a great choice for her as she can write posts and experiment with the Vue &lt;em&gt;at the same time&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Over the past few years, Jaime has helped me out so much at work and this was a chance to pay her back!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #11</title><link>https://ryantrimble.com/blog/weekly-roundup-11/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-11/</guid><description>This week I&apos;m diving deep into practical accessibility and read a bunch of interesting posts!</description><pubDate>Sat, 06 Jul 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As someone who claims to be an advocate for accessibility, I want to take a moment to shout out &lt;a href=&quot;https://www.sarasoueidan.com/&quot;&gt;Sarah Soueidan&apos;s&lt;/a&gt; &lt;a href=&quot;https://practical-accessibility.today/&quot;&gt;&lt;em&gt;Practical Accessibility&lt;/em&gt;&lt;/a&gt; course, which I began this week.&lt;/p&gt;
&lt;p&gt;I purchased the course when Sarah initially put it on sale, though it was not quite complete yet, so I held off learning until now.&lt;/p&gt;
&lt;p&gt;I am maybe like 10% of the way through and I&apos;m learning lots and lots already!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://gkeenan.co/avgb/an-alarmingly-concise-and-very-hinged-summary-of-what-it-was-like-to-build-this-site-from-scratch/&quot;&gt;An alarmingly concise and very hinged summary of what it was like to build this site from scratch&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://gkeenan.co/&quot;&gt;Keenan&lt;/a&gt; on July 3, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Building your site from scratch is no easy task, but it is one of the best ways to learn! Keenan has made the jump from Squarespace to 11ty and provides a fun and informative write up on that experience.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://lea.verou.me/blog/2024/engage-dont-show/&quot;&gt;Forget &quot;show don&apos;t tell&quot;. Engage, don&apos;t show!&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://lea.verou.me/&quot;&gt;Lea Verou&lt;/a&gt; on July 3, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Lea proposes an alternative to the old saying of &quot;show, don&apos;t tell&quot; by explaining how to engage and motivate an audience - whether that be through a blog post, conference talk, or API documentation!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.jameskerr.blog/posts/3-types-of-css-utility-classes/&quot;&gt;The 3 Types of CSS Utility Classes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.jameskerr.blog/&quot;&gt;James Kerr&lt;/a&gt; on July 1, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;James provides a summary of what he is considering as the three types of utility classes. I tend to think utility classes definitely need more organization, so I&apos;m liking what James is suggesting here.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://brandur.org/fragments/dark-mode-notes&quot;&gt;Notes on implementing dark mode&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://brandur.org/&quot;&gt;Brandur&lt;/a&gt; on May 23, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Great write up by Brandur on how they implemented light, dark, and automatic color-schemes to their blog, including several great tips along the way.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.jakerobins.com/blog/accessible-svg-forms/&quot;&gt;Accessible SVG Forms&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.jakerobins.com/&quot;&gt;Jake Robins&lt;/a&gt; on May 13, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Came across this via &lt;a href=&quot;https://piccalil.li/links/accessible-svg-forms&quot;&gt;Piccalilli&lt;/a&gt;, but it&apos;s such a great example of seeing an idea all the way through. Brilliant breakdown of how to implement a neat, SVG map-based user interface while addressing accessibility concerns.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://sarahmhigley.com/writing/playing-with-state/&quot;&gt;Playing with state&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://sarahmhigley.com/&quot;&gt;Sarah Higley&lt;/a&gt; on November 4, 2019.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This was shared by &lt;a href=&quot;https://a11y.info/@ben/112707042157117714&quot;&gt;Ben over on Mastodon&lt;/a&gt;, while explaining how &lt;code&gt;aria-pressed&lt;/code&gt; is used on their site. This is an interesting approach to managing state with semantic controls.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #10</title><link>https://ryantrimble.com/blog/weekly-roundup-10/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-10/</guid><description>CSS-Tricks returns? Anchor positioning has other uses? We made it to week 10!</description><pubDate>Sat, 29 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://css-tricks.com/transitioning-to-auto-height/&quot;&gt;Transitioning to Auto Height&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://geoffgraham.me/&quot;&gt;Geoff Graham&lt;/a&gt; on &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt; on June 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Have you all heard of this new resource out there called &lt;a href=&quot;https://css-tricks.com/&quot;&gt;CSS-Tricks&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;This &lt;em&gt;Geoff Graham&lt;/em&gt; fellow seems to know what he&apos;s talking about too, maybe he should &lt;a href=&quot;https://thebasics.dev/&quot;&gt;teach a course&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We&apos;re so back.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://tylersticka.com/journal/burned-by-my-own-hot-take/&quot;&gt;Burned by My Own Hot Take&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://tylersticka.com/&quot;&gt;Tyler Sticka&lt;/a&gt; on June 27, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Tyler shares thoughtful retrospective on his popular article &lt;a href=&quot;https://cloudfour.com/thinks/seriously-dont-use-icon-fonts/&quot;&gt;Seriously, Don&apos;t Use Icon Fonts&lt;/a&gt;. This influential post certainly helped me understand the pitfalls of icon fonts and how easy solutions aren&apos;t always the best. Thank you for sharing your knowledge with us Tyler, apreciate ya!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/figma/sds&quot;&gt;Figma SDS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;released by &lt;a href=&quot;https://figma.com&quot;&gt;Figma&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Simple Design System is a new tool released by Figma to help folks get a jumpstart on build fully integrated design system. This repo demonstrates how Figma design and React can work well together.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://yatil.net/blog/non-text-contrast-in-detail-ui-components&quot;&gt;In detail: 1.4.11 Non-Text Contrast (User Interface Components)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://yatil.net/&quot;&gt;Eric Eggert&lt;/a&gt; on June 23, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Excellent article by Eric and great reminder that it&apos;s &lt;em&gt;not just&lt;/em&gt; text that benefits from high contrast. Eric includes a section questioning whether considerations in the demo is &quot;good design&quot; and delivers a perfect answer.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://coryrylan.com/blog/flow-charts-with-css-anchor-positioning&quot;&gt;Flow Charts with CSS Anchor Positioning&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://coryrylan.com/&quot;&gt;Cory Rylan&lt;/a&gt; on May 31, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Umm, I thought CSS Anchor positioning was for tooltips &lt;em&gt;only&lt;/em&gt;, so it&apos;s exciting to see it has a second purpose! I&apos;ve been keeping an eye on this feature, and it&apos;s awesome to see possible use-cases for it.&lt;/p&gt;
&lt;h2&gt;New Challenges&lt;/h2&gt;
&lt;p&gt;I don&apos;t really know how to do things like this, but I wanted to put out into the universe that I&apos;m searching for new opportunities and challenges.&lt;/p&gt;
&lt;p&gt;If you read my site, you will get an idea on what I care about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Web Standards:&lt;/strong&gt; HTML, CSS, JavaScript, SVG&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Best Practices:&lt;/strong&gt; Accessibility, optimization, responsive design&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creative Design:&lt;/strong&gt; Web animations, typography, meaningful interaction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Awesome Technology:&lt;/strong&gt; Site generators, reactive frameworks, bundlers&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knowledgesharing:&lt;/strong&gt; Blogging and technical writing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Building Stuff:&lt;/strong&gt; Design systems, websites, web applications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, I don&apos;t mean to brag, but I&apos;ve gotten pretty good at compiling lists of awesome links &lt;a href=&quot;https://ryantrimble.com/blog/category/weekly-roundups/&quot;&gt;over the past 10 weeks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you happen to be reading this and have an open spot on your team, please don&apos;t hesitate to reach out, I&apos;d love to find out more!&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #9</title><link>https://ryantrimble.com/blog/weekly-roundup-9/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-9/</guid><description>I&apos;m proud of everyone this week, you all did great work.</description><pubDate>Sat, 22 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The next part of &lt;em&gt;Better Know a Design System&lt;/em&gt; series is actively being written, however it is turning out much longer than expected. I may refactor into smaller posts if I can figure out a sensible way to break it up.&lt;/p&gt;
&lt;p&gt;I&apos;ve been trying, with &lt;em&gt;mild&lt;/em&gt; success, to focus myself on more creative endeavors as it usually keeps my mind busy and distracted from other problems. The issue with that (at the moment) is I&apos;ve got too many ideas cooking in my head.&lt;/p&gt;
&lt;p&gt;Next week will be the 10th week in a row for the Weekly Roundups - I&apos;m surprised I have managed to keep going this long without missing a week. I really enjoy doing these, as it gives me time to reflect back on what I have learned and a chance to thank the folks who taught me. I think &lt;a href=&quot;https://front-end.social/@anarodrigues/112585708652201906&quot;&gt;Ana said it best&lt;/a&gt; about these types of things.&lt;/p&gt;
&lt;p&gt;Anyway, let&apos;s get to the cool stuff!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://noahliebman.net/2024/06/cascading-solar-system/&quot;&gt;Cascading Solar System&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://noahliebman.net/&quot;&gt;Noah Liebman&lt;/a&gt; on June 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Yesterday was the CSS science fair, and Noah brought a &lt;em&gt;rad&lt;/em&gt; solar system diaroma. I always thought CSS was &lt;em&gt;out of this world&lt;/em&gt;, but Noah has proven it!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://darn.es/the-case-for-web-components/&quot;&gt;The Case for Web Components&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes&lt;/a&gt; on June 19, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;David wrote a book about Web Components! Now I can finally refer to David by saying &quot;David wrote &lt;em&gt;the book&lt;/em&gt; on Web Components,&quot; and other people will be like, &quot;who are you?&quot;&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.mayank.co/notes/against-the-backdrop/&quot;&gt;Against the backdrop&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; on June 18, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I completely agree with Mayank, working with &lt;code&gt;::backdrop&lt;/code&gt; can be especially annoying when animating &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;. Also Mayank, thanks for answering all my questions!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://codepen.io/argyleink/pen/PovOMYy&quot;&gt;Sticky Header Calendar Grid Prototype&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; on June 14, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Really neat HTML and CSS powered calendar by Adam that inspired &lt;a href=&quot;https://tbeseda.com/&quot;&gt;Taylor Beseda&lt;/a&gt; to make &lt;a href=&quot;https://indieweb.social/@tbeseda/112616937643568666&quot;&gt;a more dynamic version&lt;/a&gt;. I love seeing the community build off of each others ideas.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.smashingmagazine.com/2018/06/placeholder-attribute/&quot;&gt;Don&apos;t Use The Placeholder Attribute&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ericwbailey.design/&quot;&gt;Eric Bailey&lt;/a&gt; on June 20, 2018.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Eric wrote this six years ago, and &lt;a href=&quot;https://social.ericwbailey.website/@eric/112649944638728047&quot;&gt;still stands by it&lt;/a&gt;. I remember reading this awesome advice &lt;em&gt;nine&lt;/em&gt; years ago, so either Eric is a time traveler or I am bad remembering things (spoiler alert, I am &lt;em&gt;downright awful&lt;/em&gt; at remembering things).&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #8</title><link>https://ryantrimble.com/blog/weekly-roundup-8/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-8/</guid><description>I&apos;m proud of everyone this week, you all did great work.</description><pubDate>Sat, 15 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been info-dumping about Design Systems on my blog this week. Sorry. Wait, no I&apos;m not. Well, maybe a little, I don&apos;t intend to be spammy.&lt;/p&gt;
&lt;p&gt;I talk about design systems a lot at work, as I help develop ours and it&apos;s my favorite type of thing to work on - however this topic was seemingly absent from my blog. Shout out to my lead, Kevin, for the recommendation to change that!&lt;/p&gt;
&lt;p&gt;I have more things to share about design systems as I continue my series, &lt;em&gt;Better Know a Design System&lt;/em&gt;. Thank you to Stephen Colbert for informing about congressional districts all those years ago, and &lt;a href=&quot;https://en.wikipedia.org/wiki/Better_Know_a_District&quot;&gt;inspiring the title&lt;/a&gt; for this blog series.&lt;/p&gt;
&lt;p&gt;Oh, and this week I also pushed an update to my &lt;code&gt;/robots.txt&lt;/code&gt; &lt;a href=&quot;/robots.txt&quot;&gt;file&lt;/a&gt; to (hopefully) help prevent AI and LLMs from scraping my website. Checkout the &lt;a href=&quot;https://github.com/ai-robots-txt/ai.robots.txt&quot;&gt;ai.robots.txt&lt;/a&gt; repo on GitHub for an up-to-date list of bots to block and instructions for how to block them.&lt;/p&gt;
&lt;p&gt;To quote Ethan Marcotte:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;i really wish i didn&apos;t have to think about any of this
— &lt;a href=&quot;https://follow.ethanmarcotte.com/@beep/112259090670376068&quot;&gt;@beep&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://multipa.ge/l/1&quot;&gt;We Fucked Up Headings&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;order fulfilled by &lt;a href=&quot;https://front-end.social/@Wilto/112616374473360666&quot;&gt;Multipage Version Fulfillment Department&lt;/a&gt; on June 14, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I received my copy of &lt;a href=&quot;https://multipage.gumroad.com/l/1&quot;&gt;Multipage Version&lt;/a&gt;&apos;s issue #1, a zine about HTML elements compiled by &lt;a href=&quot;https://front-end.social/@Wilto&quot;&gt;Mat &quot;Wilto&quot; Marquis&lt;/a&gt;. There is some gorgeous art in here from artists in the developer community, I love seeing all the interesting things this community is capable of!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.oddbird.net/2024/06/13/css-layout/&quot;&gt;Learn Grid Now, Container Queries Can Wait&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.oddbird.net/&quot;&gt;Miriam Suzanne&lt;/a&gt; on June 13, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Mia helps us navigate all these fancy new CSS features coming out and what might be helpful to learn &lt;em&gt;now&lt;/em&gt;. I also recommend learning grid as I really 💜 it.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.kevinpowell.co/article/my-experience-talking-at-css-day-2024/&quot;&gt;My experience talking at CSS Day 2024&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.kevinpowell.co/&quot;&gt;Kevin Powell&lt;/a&gt; on June 12, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I really enjoyed this write up from Kevin Powell on his experience speaking at CSS Day, very inspiring as someday I, too, hope to hear Kevin speak at CSS Day.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://darthmall.net/weblog/2024/forgetful-tools/&quot;&gt;Forgetful Tools&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://darthmall.net/&quot;&gt;Evan Sheehan&lt;/a&gt; on June 11, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Interesting and thoughtful write up by Evan, and as a self-described data-hoarder, this definitely gave me some things to consider.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://adrianroselli.com/2024/06/youtube-and-vimeo-web-component.html#comment-295078&quot;&gt;YouTube and Vimeo Web Component&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://adrianroselli.com/&quot;&gt;Adrian Roselli&lt;/a&gt; on June 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;You love to see useful web components and Adrian shared this great example, with &lt;a href=&quot;https://toot.cafe/@aardrian/112592231371023824&quot;&gt;perfect code and no errors whatsoever&lt;/a&gt;, for embedding YouTube or Vimeo videos.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://codepen.io/michellebarker/details/PovbBdK&quot;&gt;Anchor positioning popovers with pseudo elements&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Michelle Barker&lt;/a&gt; on May 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If you need just an all around solid example of tooltips using new browser feature &lt;code&gt;popover&lt;/code&gt; and CSS anchor positioning, look no further than this example by Michelle.&lt;/p&gt;
</content:encoded></item><item><title>Better Know a Design System - CSS Frameworks!</title><link>https://ryantrimble.com/blog/design-system-css-frameworks/</link><guid isPermaLink="true">https://ryantrimble.com/blog/design-system-css-frameworks/</guid><description>Let&apos;s learn about CSS Frameworks and how they fit into design systems, better known as... The Fightin&apos; Framework!</description><pubDate>Thu, 13 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Remember when Bootstrap came out and changed the web for bit there?&lt;/p&gt;
&lt;p&gt;Well, Bootstrap is a &lt;em&gt;CSS Framework&lt;/em&gt;, essentially a distributable stylesheet that contains everything you might need to get your projects up and running quickly.&lt;/p&gt;
&lt;p&gt;Third party CSS frameworks like Bootstrap gained so much popularity that websites began looking very similar, leading organizations and developers to differentiate themselves by building their own CSS frameworks as part of their overall design systems.&lt;/p&gt;
&lt;p&gt;Arguably, CSS frameworks &lt;em&gt;are&lt;/em&gt; design systems for the web - they contain everything the design system outlines, allowing developers to dig right into whatever project they are working on without needing to think much about styling.&lt;/p&gt;
&lt;p&gt;A CSS framework may contain one or more of the following parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CSS Reset&lt;/strong&gt; - standardizes default stylings across browsers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component Stylings&lt;/strong&gt; - styles to describe components used within the design system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design Tokens&lt;/strong&gt; - brings in the organization&apos;s branding and flair.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global Styles&lt;/strong&gt; - styles that have broadest specificity, such as element styles, layouts, spacing, typography.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Utility Classes&lt;/strong&gt; - small, generally single-use CSS classes that help make minor adjustments to user interfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Scaffolding a Framework&lt;/h2&gt;
&lt;p&gt;When scaffolding out a CSS framework, think about all the different parts that might need to be included to determine how best to structure the project.&lt;/p&gt;
&lt;h3&gt;CSS Resets&lt;/h3&gt;
&lt;p&gt;All major browsers ship with some default styles, though these styles may differ between browsers. This can lead to some unexpected behavior in some browsers, while working fine in others.&lt;/p&gt;
&lt;p&gt;CSS resets are a concept to help prevent unwanted style disputes caused by these browser default stylings, resetting the default styles to match consistently across browsers.&lt;/p&gt;
&lt;p&gt;Writing your own CSS reset is a viable option, especially if you have very specific needs you are hoping to accomplish. Personally, I like to use a pre-defined CSS reset, though I may make some modifications as necessary.&lt;/p&gt;
&lt;p&gt;Three excellent examples of CSS resets:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/mayank99/reset.css&quot;&gt;reset.css&lt;/a&gt; - created by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt;, this is a very modern approach to a CSS reset. I like it as it bakes in light mode / dark mode, uses the CSS &lt;code&gt;where()&lt;/code&gt; selector for zero-specificity, and includes a &lt;code&gt;.visually-hidden&lt;/code&gt; class, which I generally like to include anyway.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://piccalil.li/blog/a-more-modern-css-reset/&quot;&gt;Andy Bell&apos;s CSS Reset&lt;/a&gt; - Another modern reset by &lt;a href=&quot;https://piccalil.li/author/andy-bell&quot;&gt;Andy Bell&lt;/a&gt; which works well for his projects at &lt;a href=&quot;https://set.studio/&quot;&gt;Set Studio&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://meyerweb.com/eric/tools/css/reset/&quot;&gt;Eric Meyer&apos;s CSS Reset&lt;/a&gt; - One of the, if not &lt;em&gt;the&lt;/em&gt;, original CSS resets.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Components&lt;/h3&gt;
&lt;p&gt;Component stylings may be found as part of the CSS framework, though an alternative approach may be to contain component stylings within a component library.&lt;/p&gt;
&lt;p&gt;I like to include components as part of the CSS framework as it allows for me to be slightly more flexible in how I implement components.&lt;/p&gt;
&lt;p&gt;If I don&apos;t have a component library available or decide installing the component library may be too much, I can still quickly sketch out the component in HTML, so having the styles included is helpful.&lt;/p&gt;
&lt;p&gt;Look forward to a dedicated post on components and building component libraries!&lt;/p&gt;
&lt;h3&gt;Design Tokens&lt;/h3&gt;
&lt;p&gt;If you have been following along with the &lt;em&gt;Better Know a Design System&lt;/em&gt; series, you&apos;ll know we have discussed Design Tokens in-depth already. If you haven&apos;t read that post yet, the short summary is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Design Tokens are variables that contain important values to describe our designs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Design tokens typically hold brand or theme values which can be used throughout a CSS framework for coloring, spacing, typography, and much more.&lt;/p&gt;
&lt;p&gt;Design tokens might also be useful in creating utility classes based on token values, or adding finishing touches onto a component.&lt;/p&gt;
&lt;h3&gt;Global Styles&lt;/h3&gt;
&lt;p&gt;The framework&apos;s global styles refers to styling that generally has the broadest impact. For these styles, I like to write them as the browser&apos;s mentor, not a micromanager.&lt;/p&gt;
&lt;p&gt;Types of most useful to include in your global styles might include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Classless elements&lt;/strong&gt; - Describes default styles on how common HTML elements look when they have no other classes applied, such as the list elements, block quotes, form inputs, and more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Layouts&lt;/strong&gt; - Common layouts used to scaffold websites or applications, may include dynamic layout tools using CSS Flexbox and Grid.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spacing&lt;/strong&gt; - Typically a scale providing various, consistent options for applying spacing to elements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typography&lt;/strong&gt; - Touches virtually everything else in the framework, definitely important to configure globally.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an aside, I use https://utopia.fyi/ to calculate spacing and typographical scales. They have a great Sass package which helps you dynamically generate these scales within your code.&lt;/p&gt;
&lt;h3&gt;Utilities&lt;/h3&gt;
&lt;p&gt;Utility classes are generally small, single-use CSS classes that are used to make minor adjustments to a design.&lt;/p&gt;
&lt;p&gt;I have a love/hate relationship with utility classes. As a personal preference, I enjoy writing CSS and figuring out ways to make styles more flexible, keeping utility classes to a minimum. That being said, they can come in &lt;em&gt;very handy&lt;/em&gt; when necessary.&lt;/p&gt;
&lt;p&gt;Too many utility classes can bloat your compiled CSS file, so finding a balance of what is most useful versus what isn&apos;t can be difficult. This is why it is important to periodically check in with folks using the design system, determine what is used most and potentially prune some cruft.&lt;/p&gt;
&lt;p&gt;One alternate approach to utility classes comes from Andy Bell, who has written about how &lt;a href=&quot;https://piccalil.li/blog/cube-css/&quot;&gt;he utilizes Tailwind as an on-demand utility class generator&lt;/a&gt;. While I&apos;m not the biggest fan of Tailwind, this makes a lot of sense to me. Tailwind is very good at being a utility class framework and as it only outputs what you use, you end up with a much cleaner CSS file in the end.&lt;/p&gt;
&lt;h2&gt;Organizing the Layers&lt;/h2&gt;
&lt;p&gt;My favorite way to organize CSS is by using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@layer&quot;&gt;CSS Layers&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CSS Layers are a newer feature, so you may need to make sure browser support is available, but they help you organize your code in many different ways.&lt;/p&gt;
&lt;p&gt;Let&apos;s see how they work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* To define a layer, we can use the @layer directive: */

@layer reset;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The above creates a CSS layer named &lt;code&gt;reset&lt;/code&gt; - and guess what it might contain? That&apos;s right, we can place the contents of our CSS reset within that layer.&lt;/p&gt;
&lt;p&gt;We can use multiple layers or even nest layers within other layers! It&apos;s layers the whole way down!&lt;/p&gt;
&lt;p&gt;The order of precedence when creating layers follows the cascade in general, layers created first will have lower precedence than layers later on in the stylesheet. We can define our layer precedence by declaring all the layers on a single line, such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@layer reset, global, utilties, themes;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, &lt;code&gt;reset&lt;/code&gt; has the lowest precedence and &lt;code&gt;themes&lt;/code&gt; has the highest.&lt;/p&gt;
&lt;p&gt;To actually add styles to a layer, you open up the layer similar to how you would define any CSS class:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@layer reset, global, utilities, themes;

@layer reset {
  /* Reset styles go here! */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you happen to be using Sass, you might be writing styles in many different files. One way to implement CSS layers within Sass is by using the &lt;code&gt;meta.load-css&lt;/code&gt; function Sass provides to load CSS files directly within layers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@use &apos;sass:meta&apos;;

@layer reset, global, utilities, themes;

@layer reset {
  @include meta.load-css(&apos;path/to/reset.css&apos;);
}

@layer global {
  @include meta.load-css(&apos;path/to/global.css&apos;);
}

@layer utilities {
  @include meta.load-css(&apos;path/to/utilities.css&apos;);
}

@layer themes {
  @include meta.load-css(&apos;path/to/themes.css&apos;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The neat bonus that CSS layers provides occurs within browser development tools. When inspecting an element, in the CSS pane you should now be able to view which layer styles originate from, which may help in locating troublesome code or while debugging.&lt;/p&gt;
&lt;h2&gt;Optimizing and Bundling&lt;/h2&gt;
&lt;p&gt;Before we talk about &lt;em&gt;using&lt;/em&gt; the CSS framework, there are a few things that we can do to optimize the code to provide the lightest bundle possible.&lt;/p&gt;
&lt;p&gt;PostCSS is a tool that runs &lt;em&gt;after&lt;/em&gt; CSS is compiled, that can host a pipeline of processes to clean up, minify, and more. Similar to Tailwind, there are PostCSS plugins available that can scan your project and deliver a CSS file containing only the styles you used, rather than a heavy file that contains &lt;em&gt;everything&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;A newer tool, LightningCSS, also provides some post-build magic to enhance your CSS. LightningCSS reminds me a bit of babel from the JavaScript world, as it can take modern CSS techniques and try to make them more backwards compatible for larger browser support.&lt;/p&gt;
&lt;p&gt;To really make everything work together though, we might want to include a bundler tool.&lt;/p&gt;
&lt;p&gt;Some bundlers provide everything you need to make your development experience better. Vite is my favorite tool as it is fast, easy to configure, and has support for CSS pre-processors, JavaScript, Typescript, PostCSS, Lightning CSS, and has an excellent developer community. Other options might be Webpack, Gulp, or Parcel.&lt;/p&gt;
&lt;p&gt;If configured properly, you can produce a well optimized and organized CSS Framework.&lt;/p&gt;
&lt;h2&gt;Publishing&lt;/h2&gt;
&lt;p&gt;Similar to Design Tokens from a previous post, we can publish the CSS Framework to package registries such as npm or an organization&apos;s private package registry to make available for developers on your team.&lt;/p&gt;
&lt;p&gt;Publishing your CSS framework to a package registry enables developers to easily install the CSS framework into their projects. Content delivery networks unpkg and JSdelivr automatically host packages listed on npm, making dropping the CSS framework into a Codepen easy.&lt;/p&gt;
&lt;h2&gt;Learn More&lt;/h2&gt;
&lt;h3&gt;Tools Mentioned&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://sass-lang.com/&quot;&gt;Sass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://utopia.fyi/&quot;&gt;Utopia.fyi&lt;/a&gt; - by James Gilyead and Trys Mudford, &lt;em&gt;Clearleft&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://postcss.org/&quot;&gt;PostCSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a&gt;LightningCSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vitejs.dev/&quot;&gt;Vite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://webpack.js.org/&quot;&gt;Webpack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gulpjs.com/docs/en/getting-started/quick-start/&quot;&gt;Gulp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://parceljs.org/&quot;&gt;Parcel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Better Know a Design System - Design Tokens!</title><link>https://ryantrimble.com/blog/design-system-tokens/</link><guid isPermaLink="true">https://ryantrimble.com/blog/design-system-tokens/</guid><description>Adding onto the Better Know a Design System series, this time we are talking about Design Tokens, a.k.a... The Fightin&apos; Tokens!</description><pubDate>Wed, 12 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In programming, we have the ability to store bits of data as variables, which help us remember certain values, easily make updates, or just happens to contain a constant source of truth. Essentially, this is what Design Tokens are: variables that contain important values to describe our designs - however they aren&apos;t &lt;em&gt;just&lt;/em&gt; for developers.&lt;/p&gt;
&lt;p&gt;Designers and developers can take advantage of design tokens as part of your organization&apos;s design system.&lt;/p&gt;
&lt;p&gt;Designers work with design tokens in design tools such as Figma, where values stored as tokens can be re-used throughout designs. Tokens can be used within any type of design - print, web, mobile applications, and more. This makes changes and updates to the design easier by simply swapping around tokens.&lt;/p&gt;
&lt;p&gt;Developers use design tokens while implementing styles in websites and applications, usually through the use of CSS custom properties, JavaScript variables. Similarly, changes and updates become a lot easier and cascade through designs by modifying tokens.&lt;/p&gt;
&lt;p&gt;Design Tokens might hold things related to the organization&apos;s branding or style choices based upon shared design principles. Things like colors, fonts, spacing, or whatever else needed to pass along uniformity across projects. Think of design tokens as a single source of truth that can be made available in a variety of formats.&lt;/p&gt;
&lt;h2&gt;Types of tokens&lt;/h2&gt;
&lt;p&gt;Tokens can be used in a variety of different ways. Some might be used to store values that need to be available globally, or tokens specific to certain sections, or tokens based on the specific feature being created.&lt;/p&gt;
&lt;h3&gt;Global tokens&lt;/h3&gt;
&lt;p&gt;Generic tokens that can be used anywhere within a design. Things like colors, fonts make for great global tokens.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--color-red
--color-orange
--color-yellow
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Semantic tokens&lt;/h3&gt;
&lt;p&gt;Tokens that might be more related to how something works may be considered semantic tokens, named for what the token is used for as well as possible states.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--link-default
--link-hover
--link-focus
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Component tokens&lt;/h3&gt;
&lt;p&gt;Components may have tokens only used within tokens. Usually prefixed with the component it belongs to, these tokens help describe how a component might look, feel, and possibly behave.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;--accordion-padding-block
--modal-backdrop-color
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Naming design tokens&lt;/h2&gt;
&lt;p&gt;You know the old adage:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Naming things is the easiest part of computer science.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is a joke, of course - while naming things may technically be a simple task, it can be difficult to come up with a meaningful convention to describe tokens. I want to say &quot;keep it simple&quot; but my idea of simple may be different than your idea of simple.&lt;/p&gt;
&lt;p&gt;If you are working on a team, it is important to come together and discuss the naming convention for tokens. This helps clear up confusion and hopefully helps set a pattern for how all your tokens can be named.&lt;/p&gt;
&lt;p&gt;If you are working by yourself, be clear and concise with how you name your tokens. Document the naming conventions you use to make sure you understand it if you need to come back to it later.&lt;/p&gt;
&lt;h3&gt;What works for me&lt;/h3&gt;
&lt;p&gt;I try to limit the number of global design tokens necessary, it is easy for the number of tokens to balloon to something unwieldy. Tokens like colors, fonts, and spacing, the things generally considered globally available, I like to put what they are right up front - literally, as prefixes!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Colors&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Colors typically begin with `color` */
--color-blue

/* If I have multiple shades of the same color I will tack a weight onto it: */
--color-blue-100
--color-blue-200
--color-blue-300
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Fonts&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* I normally restrict font palette into heading and body families */
--font-heading
--font-body

/* For font sizes, I lean towards T-Shirt sizes to name the different levels: */
--font-size-sm
--font-size-md
--font-size-lg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Spacing&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Similar to font sizes, spacing also gets represented in T-Shirt sizes: */
--spacing-sm
--spacing-md
--spacing-lg
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Creating Tokens&lt;/h2&gt;
&lt;p&gt;So how do we go about creating tokens? Where do these things live?&lt;/p&gt;
&lt;p&gt;This entirely depends on where you might be working. If you are a designer building things in Figma, chances are you want your design tokens available there. Similarly, developers may look to their style sheets for design tokens.&lt;/p&gt;
&lt;p&gt;Let&apos;s explore how to create design tokens in both of these places.&lt;/p&gt;
&lt;h3&gt;How to create within Figma&lt;/h3&gt;
&lt;p&gt;Figma features an asset library which can be used to store reusable pieces, such as shapes, components, text styles, and other types of variables, making it the perfect spot to setup design tokens.&lt;/p&gt;
&lt;p&gt;You can add to the asset library in a variety of ways, but the simplest method I know of happens when you are setting values for designs. Once you have set the value, click the &lt;em&gt;Styles and variables&lt;/em&gt; button, select &lt;em&gt;Libraries&lt;/em&gt; in the popup context menu, and click the &lt;code&gt;+&lt;/code&gt; plus sign button to add the value to the library.&lt;/p&gt;
&lt;p&gt;Now, instead of manually selecting values, we can choose to select a variable from the asset library, representing a design token value.&lt;/p&gt;
&lt;h3&gt;How to create with CSS&lt;/h3&gt;
&lt;p&gt;We can utilize CSS custom properties to store design tokens within CSS. We can make globally available design tokens by placing their CSS custom properties within the &lt;code&gt;:root&lt;/code&gt; selector:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:root {
  /* Colors */
  --color-blue-100: #f4f8fb;
  --color-blue-200: #54a9fa;
  --color-blue-300: #4178ff;

  /* Font Families */
  --font-heading: &apos;Whirly Birdie&apos;;
  --font-body: system-ui;

  /* Font Sizes */
  --font-size-sm: 0.5rem;
  --font-size-md: 1rem;
  --font-size-lg: 2rem;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, you can manually add design tokens by defining them as custom properties within CSS. Keeping the number of global design tokens to a minimum will help keep this organized, adding lots of tokens may become difficult to work with.&lt;/p&gt;
&lt;p&gt;Alternatively, instead of vanilla CSS, you can utilize CSS preprocessors such as Sass to store design tokens as Sass maps or variables for use within your projects.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Stored as a Sass Map */
$colors: (100: &apos;#F4F8FB&apos;, 200: &apos;#54A9FA&apos;, 300: &apos;#4178FF&apos;);

$font: (&apos;heading&apos;: &apos;Whirly Birdie&apos;, &apos;body&apos;: &apos;system-ui&apos;);

$fontSize: (&apos;sm&apos;: &apos;0.5rem&apos;, &apos;md&apos;: &apos;1rem&apos;, &apos;lg&apos;: &apos;2rem&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Storing design tokens as Sass maps allows you to loop through them later.&lt;/p&gt;
&lt;h2&gt;Tools for managing Design Tokens&lt;/h2&gt;
&lt;p&gt;As mentioned, the more you grow your design tokens, the more cumbersome they may become to manage. There are a few tools out there that help with managing design tokens:&lt;/p&gt;
&lt;h3&gt;Style Dictionary&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://amzn.github.io/style-dictionary/&quot;&gt;Style Dictionary&lt;/a&gt; is an open source build tool developed by the folks over at Amazon.&lt;/p&gt;
&lt;p&gt;This is a neat tool for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Design Tokens can be organized in separate JSON formatted files.&lt;/li&gt;
&lt;li&gt;Style Dictionary can be wired up as part of your build process, so that tokens can be generated when the project builds.&lt;/li&gt;
&lt;li&gt;Tokens can be defined and configured for multiple output formats including: CSS custom properties, Sass variables, JavaScript variables, variables for usage within mobile app development on Android and iOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tokens Studio&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://tokens.studio/&quot;&gt;Tokens Studio&lt;/a&gt; is a plugin for Figma for more advanced control over design tokens.&lt;/p&gt;
&lt;p&gt;Token Studio integrates directly into your design files, enabling you to work with tokens. Token Studio also lets your synchronize your design tokens with other services, such as pushing the tokens to a GitHub repository.&lt;/p&gt;
&lt;p&gt;Tokens can also be exported from Tokens Studio to be used within your projects.&lt;/p&gt;
&lt;h3&gt;Zeroheight&lt;/h3&gt;
&lt;p&gt;Another tool, &lt;a href=&quot;https://zeroheight.com/&quot;&gt;Zeroheight&lt;/a&gt;, is a one-stop-shop for all your design system related needs. This is a cloud based tool for documenting features within your design system.&lt;/p&gt;
&lt;p&gt;Zeroheight has a built-in design token manager tool for managing design tokens found in your design system. Tokens can be imported and exported into different formats.&lt;/p&gt;
&lt;h2&gt;Publishing tokens&lt;/h2&gt;
&lt;p&gt;To make tokens available to others on the team, or even for public consumption, we need a place to publish them.&lt;/p&gt;
&lt;p&gt;Figma&apos;s asset library is the perfect place for a designer as that can be made accessible to other designers on the team, but it&apos;s not quite as simple for developers.&lt;/p&gt;
&lt;p&gt;Instead, a package registry such as &lt;a href=&quot;https://www.npmjs.com/&quot;&gt;npm&lt;/a&gt; might make reaching for tokens a bit easier to developers, who can install tokens directly into their projects. Tokens published on npm automatically become available through free content delivery network tools unpkg and JSDelivr, making them even easier to grab for quick prototyping.&lt;/p&gt;
&lt;h2&gt;Using tokens in projects&lt;/h2&gt;
&lt;p&gt;Now that we have published our design tokens to a package registry, how might we go about using them in a project?&lt;/p&gt;
&lt;h3&gt;Node-based projects&lt;/h3&gt;
&lt;p&gt;If your project is built with Vue, React, or some other framework such as Astro, you can install your design token package directly to your project.&lt;/p&gt;
&lt;p&gt;Navigate to your project directory and in the terminal, install your package by running the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install --save-dev *your-package-name*
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If successful, the package will be included in our &lt;code&gt;package.json&lt;/code&gt; file, found in the root of the project.&lt;/p&gt;
&lt;p&gt;There are several ways to import tokens for use within projects. If your package builds out to a single CSS file, it can be included in your bundler&apos;s main entry (something like a &lt;code&gt;main.js&lt;/code&gt; with Vite) file or by importing in your CSS.&lt;/p&gt;
&lt;p&gt;In JavaScript, we can import packages directly:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &apos;package-name.css&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In CSS, we can load it as an &lt;code&gt;@import&lt;/code&gt; statement:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@import url(&apos;path/to/package/package-name.css&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By including the CSS file in your project, you can now access tokens in other CSS files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.card {
	font-size: var(--font-size-md);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Learn more&lt;/h2&gt;
&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.uxpin.com/studio/blog/what-are-design-tokens/&quot;&gt;What are design tokens?&lt;/a&gt; - by UXPin&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://uxdesign.cc/naming-design-tokens-347f630ba4f9&quot;&gt;Naming Design Tokens&lt;/a&gt; - by Zara Soltani, UX Collective&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tools Mentioned&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/&quot;&gt;Figma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sass-lang.com/&quot;&gt;Sass&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://amzn.github.io/style-dictionary/&quot;&gt;Style Dictionary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tokens.studio/&quot;&gt;Token Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zeroheight.com/&quot;&gt;Zeroheight&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Better Know a Design System - Discovery!</title><link>https://ryantrimble.com/blog/design-system-discovery/</link><guid isPermaLink="true">https://ryantrimble.com/blog/design-system-discovery/</guid><description>Kickoff of my new many-part series, Better Know a Design System - featuring The Fightin Discovery Phase!</description><pubDate>Tue, 11 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When a new UX project emerges, a product team may go through a design discovery phase to help navigate the project.&lt;/p&gt;
&lt;p&gt;Design discovery helps teams from various angles: understanding users, grokking the problems to solve, and more, all resulting in a shared vision from the team for how that project should come together.&lt;/p&gt;
&lt;p&gt;Let&apos;s talk about how to utilize design discovery to help build out design systems!&lt;/p&gt;
&lt;h2&gt;Design Discovery for Design Systems&lt;/h2&gt;
&lt;p&gt;A crucial skill to have as a design system maintainer is the ability to research and speak your organization&apos;s design language. This means researching and identifying common patterns that might make for useful additions to the design system.&lt;/p&gt;
&lt;p&gt;This skill is especially true if you find yourself in an evergreen project, tasked with building out a design system for a new project that might not have mockups or design compositions available.&lt;/p&gt;
&lt;p&gt;Generally speaking, discovery should be a broader approach, focusing less on the implementation details and more on the common parts.&lt;/p&gt;
&lt;p&gt;Everyone involved in a project may contribute to the research and discovery phase, as design discovery is an important step in design system creation and maintenance.&lt;/p&gt;
&lt;h2&gt;Types of Discovery&lt;/h2&gt;
&lt;p&gt;Inspiration and discovery comes from various sources, stemming internally from the organization&apos;s branding and staff product designers, or researching design system best practices externally online or by browsing other design systems.&lt;/p&gt;
&lt;h3&gt;Internal Discovery&lt;/h3&gt;
&lt;p&gt;A common starting point for design discovery is by taking a look at the organization itself - the branding, and who best to understand branding than the staff &lt;em&gt;Product Designer&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Organizations typically hire designers to work on various pieces of media, including print and web, becoming a valuable resource when it comes to discovering your organization&apos;s design language. Product designers should be attributed as contributors to a design system, as they are responsible for conceptualizing and describing the look and feel of a product. As a team, Product Designers and design system maintainers work together to ensure designs are being conveyed properly to the product line.&lt;/p&gt;
&lt;p&gt;Outside of product designers, there are many other avenues to internally discover or define your organization&apos;s design language. Are there any pieces that can be inherited from the organization that may cascade down to the products?&lt;/p&gt;
&lt;p&gt;Organizations tend to be deliberate when orchestrating their branding, so extending certain features to their products help create uniformity that design systems are known to deliver.&lt;/p&gt;
&lt;p&gt;Choices such as brand colors, selected font families, logos or any other image assets are important to note, even just for the sake of creating a mood board or style tiles. Ultimately recording these bits of data as &lt;strong&gt;Design Tokens&lt;/strong&gt;, which will become available to designers in Figma or developers in code (We&apos;ll talk more on Design Tokens throughout this series!).&lt;/p&gt;
&lt;p&gt;Another great place to look internally for design discovery is any other products your organization might have within their line-up. Closely inspect each product, breaking down all the parts to understand the design choices, recognizing the patterns and approaches used on completed work.&lt;/p&gt;
&lt;h3&gt;External Discovery&lt;/h3&gt;
&lt;p&gt;Design discovery should happen external to the organization too. It is important to hear how others tackle problems, as it can help you determine the best course of action when experiencing similar situations.&lt;/p&gt;
&lt;p&gt;The web is an ever-changing platform, so it can be difficult to keep up with the latest and greatest features. That being said, you absolutely &lt;em&gt;do not have&lt;/em&gt; to keep up-to-date with everything. Focus research where it matters most &lt;em&gt;to you&lt;/em&gt;, whether that be reading books on relevant topics, videos, blog posts, technical documentation, or whatever else. I guarantee you&apos;ll manage to learn something new.&lt;/p&gt;
&lt;p&gt;Listening to the opinions of others helps us organize our own thoughts, learn about best practices or alternative approaches, as well as exposes us to different mindsets.&lt;/p&gt;
&lt;p&gt;Look towards other design system maintainers on how their processes and procedures work to figure out if there are ways to enhance what your own process flow. Check out design systems for other organizations or products and try to recognize what work went into development.&lt;/p&gt;
&lt;h2&gt;Knowledge Sharing&lt;/h2&gt;
&lt;p&gt;What is a design system if not a resource, a resource to share what you have learned. While the contents of the design system are generally the main course, you can add even more value by documenting how you got to that point.&lt;/p&gt;
&lt;p&gt;Keep a notebook, whether digital or physical, and as you are learning, researching, and developing a design system, jot down the parts that trip you up. Notate the things that &lt;em&gt;did&lt;/em&gt; work and what &lt;em&gt;did not&lt;/em&gt; work. Keep a running to do list to help you stay on task. Document difficult issues and how you overcame them.&lt;/p&gt;
&lt;p&gt;Now you can take those notes and share them with others on your team, or make them publicly available on a personal own blog site, to provide even more value to those who might be developing their own design systems.&lt;/p&gt;
&lt;p&gt;The important part is sharing what you learned. Create the resources that you didn&apos;t have available to you, ultimately making things easier for yourself (and others!) the next time you need to build a design system.&lt;/p&gt;
&lt;h2&gt;Learn More&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://designsystem.university/books/design-that-scales&quot;&gt;Design Systems 101&lt;/a&gt; - by Dan Mall, Design System University&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.nngroup.com/articles/discovery-phase/&quot;&gt;The Discovery Phase in UX Projects&lt;/a&gt; - by Maria Rosala, Nielsen Norman Goup&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://spotify.design/article/navigating-the-discovery-phase&quot;&gt;Navigating the Discovery Phase&lt;/a&gt; - by Ashley Jahren and Flo Wen, Spotify Design&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Weekly Roundup #7</title><link>https://ryantrimble.com/blog/weekly-roundup-7/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-7/</guid><description>This week I&apos;ve been jealous of everyone in the city of Amsterdam.</description><pubDate>Sat, 08 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hope everyone had a great week!&lt;/p&gt;
&lt;p&gt;Personally, I&apos;ve been living vicariously through the &lt;code&gt;#cssday&lt;/code&gt; hashtag on Mastodon.&lt;/p&gt;
&lt;p&gt;I had so much fun &lt;a href=&quot;https://ryantrimble.com/blog/visiting-amsterdam-for-css-day/&quot;&gt;visiting Amsterdam for CSS Day&lt;/a&gt; last year, and while it did not work out this time, &lt;em&gt;I will return!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I miss you &lt;a href=&quot;https://cssday.nl/2024&quot;&gt;CSS Day&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ryantrimble.com/blog/parts-of-a-design-system/&quot;&gt;Parts of a Design System&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ryantrimble.com/&quot;&gt;Ryan Trimble&lt;/a&gt; on June 7, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wait&lt;/em&gt;, this one is from &lt;strong&gt;me&lt;/strong&gt;! I wrote up a post on the various bits and bobs you might find within a design system. I&apos;ve got more information to share about design systems, so keep an eye out for more posts soon!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://lynnandtonicblog.com/2024/06/06/the-dish-with-kish/&quot;&gt;The Dish with Kish&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://lynnandtonicblog.com/&quot;&gt;Lynn Fisher&lt;/a&gt; on June 7, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;~Hard~ &lt;em&gt;Awesome&lt;/em&gt; work pays off! Lynn Fisher recently had a chance to hangout with the folks at &lt;em&gt;Top Chef&lt;/em&gt; and give a rundown of her &lt;a href=&quot;https://topchefstats.com/&quot;&gt;Top Chef Stats&lt;/a&gt; project!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://gomakethings.com/learning-to-code/&quot;&gt;How to build your first Web Component&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on June 5, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I can&apos;t help it that Chris keeps doing cool stuff! Chris kicked off a new video series on YouTube and is already a pro at thumbnail face.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/css-cap-unit/&quot;&gt;Cap Unit&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on June 4, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Back-to-back weeks for Ahmad! Last week was about the &lt;code&gt;gap&lt;/code&gt; property, this week he&apos;s letting us know about the &lt;code&gt;cap&lt;/code&gt; unit. I didn&apos;t know this was a thing, but it&apos;ll make icons a whole lot easier.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/lets-make-a-floating-button-sign-up-form-pattern/&quot;&gt;Let&apos;s make a floating button sign up form pattern&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt; on June 4, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Classic problems with modern solutions! Andy walks us through how to make a subscribe button float in the air! Well, in CSS at least!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://clagnut.com/blog/2431&quot;&gt;A modern approach to browser support&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://clagnut.com/&quot;&gt;Richard Rutter&lt;/a&gt; on June 4, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Richard talks about how &lt;a href=&quot;https://clearleft.com/&quot;&gt;Clearleft&lt;/a&gt; uses &lt;a href=&quot;https://web.dev/baseline&quot;&gt;Baseline&lt;/a&gt; to determine browser support and how &lt;em&gt;newly available&lt;/em&gt; features might be implemented through progressive enhancements.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://frostapalooza.bradfrost.com/&quot;&gt;Frostapalooza&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;hosted by &lt;a href=&quot;https://bradfrost.com/&quot;&gt;Brad Frost&lt;/a&gt; on August 17, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I got tickets to Brad Frost&apos;s &lt;em&gt;Frostapalooza&lt;/em&gt;! Social anxiety be damned, I&apos;m hoping to see some friends out in Pittsburgh later this year. Consider checking it out!&lt;/p&gt;
</content:encoded></item><item><title>Parts of a Design System</title><link>https://ryantrimble.com/blog/parts-of-a-design-system/</link><guid isPermaLink="true">https://ryantrimble.com/blog/parts-of-a-design-system/</guid><description>Everybody&apos;s talkin&apos; about design systems, so what are they?</description><pubDate>Fri, 07 Jun 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Design systems are a fun topic for me, because I like design and I like systems.&lt;/p&gt;
&lt;p&gt;They can be maintained by the &lt;em&gt;lone dev&lt;/em&gt; looking to make their job easier, or are robustly powering multiple websites and applications for organizations all over the place.&lt;/p&gt;
&lt;p&gt;Design systems might be a &lt;em&gt;magical nexus point&lt;/em&gt; between &lt;strong&gt;designers&lt;/strong&gt; and &lt;strong&gt;developers&lt;/strong&gt; to some, however If you know what a design system is, then this post probably isn&apos;t for you.&lt;/p&gt;
&lt;p&gt;I want to talk about different parts that may or may not be included in an organization&apos;s design system. Give an overview of the types of tools you might find in a design system.&lt;/p&gt;
&lt;h2&gt;Design System Features&lt;/h2&gt;
&lt;p&gt;So, what actually makes up a design system?&lt;/p&gt;
&lt;p&gt;Well, that is fairly open-ended, as it really comes down to what an organization needs. Maybe just a set of tokens or a handful of components, here and there. Heck, the &lt;em&gt;big organizations&lt;/em&gt; might have fully decked out systems with libraries, frameworks, UI kits.&lt;/p&gt;
&lt;p&gt;I&apos;m gonna talk about all these pieces!&lt;/p&gt;
&lt;h3&gt;Accessibility Guidelines&lt;/h3&gt;
&lt;p&gt;Personally, I believe building accessible user interaces typically enhances the experience &lt;em&gt;for all users&lt;/em&gt;. One of my personal mantras is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;if something is designed well, but not accessible — then it is not designed well.&quot;&lt;/p&gt;
&lt;p&gt;— Me&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;In my opinion&lt;/em&gt;, design systems should contain guidelines an organization&apos;s &lt;em&gt;designers&lt;/em&gt; and &lt;em&gt;developers&lt;/em&gt; should adhere to, committed to inclusive and accessible experiences for all users.&lt;/p&gt;
&lt;p&gt;A great starting point is making sure products are following the &lt;a href=&quot;https://en.wikipedia.org/wiki/Web_Content_Accessibility_Guidelines#:~:text=The%20Web%20Content%20Accessibility%20Guidelines,standards%20organization%20for%20the%20Internet.&quot;&gt;Web Content Accessibility Guidelines (WCAG)&lt;/a&gt; to meet some sort of compliance standards.&lt;/p&gt;
&lt;p&gt;Design systems are an excellent way to promote accessibility and inclusivity.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encourage products to be developed with accessibility and inclusivity in mind produces better overall user experiences.&lt;/li&gt;
&lt;li&gt;Commitment to accessibility helps the organization &lt;em&gt;lead by example&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Meeting Web Content Accessibility Guidelines in order to stay compliant!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Some neat examples of accessibility guidelines can be found in these design systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cedar.rei.com/guidelines/accessibility&quot;&gt;Cedar - Accessibility&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lightningdesignsystem.com/accessibility/overview/&quot;&gt;Lightning Design System - Accessibility Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/accessibility-checklist/&quot;&gt;Nordhealth - Accessibility Checklist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Component Libraries&lt;/h3&gt;
&lt;p&gt;The contents of a component library might be determined through a design discovery phase, perusing a catalog of products to determine potential reusable patterns. Capturing these patterns into components to make designer and developer work more streamlined.&lt;/p&gt;
&lt;p&gt;Once identified and packaged, components can be distributed through package registries (such as &lt;code&gt;npm&lt;/code&gt;) or through design kits created for Figma.&lt;/p&gt;
&lt;p&gt;Component libraries help reduce overhead of rebuilding the same components over and over and over again. Also, pushing changes to a component will trickle down to any project using it as a dependency.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Updates in one location will cascade to all products utilizing component library.&lt;/li&gt;
&lt;li&gt;Designers and Developers no longer need to recreate the same experiences over and over again.&lt;/li&gt;
&lt;li&gt;Contributions to the component library will continue as design patterns are identified.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Great examples of component libraries within these design systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cedar.rei.com/components&quot;&gt;Cedar - Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/components/&quot;&gt;Nordhealth - Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://polaris.shopify.com/components&quot;&gt;Polaris - Components&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;CSS Frameworks&lt;/h3&gt;
&lt;p&gt;CSS frameworks are based upon the organization&apos;s design principles, accessibility guidelines, and branding.&lt;/p&gt;
&lt;p&gt;Custom built CSS frameworks can be used to deploy your organization&apos;s style across all projects. This helps to keep styling consistent throughout websites and applications.&lt;/p&gt;
&lt;p&gt;CSS resets, layouts, utilities, and more may be included within the design system&apos;s CSS Framework.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Core CSS contains all necessary organization styles to easily get projects up and running.&lt;/li&gt;
&lt;li&gt;Easy to use with within products, flexible to support organization applications.&lt;/li&gt;
&lt;li&gt;Proudly conveys organization branding.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;There so many great design system CSS frameworks out there, such as:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/css/&quot;&gt;Nordhealth - CSS Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pitviper.turquoise.health/&quot;&gt;Pit Viper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://designsystem.digital.gov/&quot;&gt;US Web Design System&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Design Principles&lt;/h3&gt;
&lt;p&gt;Similar to an organization&apos;s &lt;a href=&quot;#accessibility-guidelines&quot;&gt;accessibility guidelines&lt;/a&gt;, design principles help to keep designers and developers on the same page about how things should look, feel, or behave.&lt;/p&gt;
&lt;p&gt;These core values inform design decisions, instructing how to utilize the design system effectively.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Single source of truth, one location to describe how the organization&apos;s designs and styles should be used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;These design systems have been built upon great design principles:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/guidelines/&quot;&gt;Nordhealth - Guidelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://polaris.shopify.com/design&quot;&gt;Polaris - Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://designsystem.digital.gov/design-principles/&quot;&gt;US Web Design System - Design Principles&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Design Tokens&lt;/h3&gt;
&lt;p&gt;Bite-sized sets of information containing the values of the organization&apos;s brand colors, typography, spacing, and whatever else that might come in handy.&lt;/p&gt;
&lt;p&gt;Design tokens can be used within organization projects, delivering branding through the design system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Delivers tokens in many formats such as CSS custom properties, JavaScript variables, or for use within mobile applications.&lt;/li&gt;
&lt;li&gt;Easily installable in projects to bring organization branding to products.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;For some ideas on how to implement design tokens, check out these design systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cedar.rei.com/tokens&quot;&gt;Cedar - Tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/tokens/&quot;&gt;Nordhealth - Tokens&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pitviper.turquoise.health/theming/&quot;&gt;Pit Viper - Theming&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Iconography&lt;/h3&gt;
&lt;p&gt;Icons are used literally everywhere: print, mobile, web. So having easy-to-grab access to any icon in any format necessary might be a useful addition to a design system. Especially if you have organization-specific icons that get re-used often.&lt;/p&gt;
&lt;p&gt;As they are used everywhere, Icons might need to be a &lt;code&gt;.png&lt;/code&gt; file format for a print design or a scalabale vector graphic (SVG) for something on the web.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vector graphics are scalable to any resolution.&lt;/li&gt;
&lt;li&gt;Sprite sheets might be useful if you want to optimize which icons are used where.&lt;/li&gt;
&lt;li&gt;Icon fonts, while heavy, can be an easy way to drop your icons into projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Neat iconography can be found in these design systems:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cedar.rei.com/guidelines/icons#library&quot;&gt;Cedar - Icons Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lightningdesignsystem.com/icons/&quot;&gt;Lightning Design System - Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://m3.material.io/styles/icons/overview&quot;&gt;Material Design - Icons&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Design Kits&lt;/h3&gt;
&lt;p&gt;Much of what I focused on above is more developer-focused, however a design system may be used by non-developers also.&lt;/p&gt;
&lt;p&gt;Design tools such as Figma provide an excellent way to create design kits, enabling non-devs the ability to quickly mockup a prototype.&lt;/p&gt;
&lt;p&gt;These tools help convey design ideas to developers for a distinct feature development pipeline.&lt;/p&gt;
&lt;p&gt;Figma is also a great place to work on design discovery, which might happen within a design kit. Identifying the patterns, extracting them into reusable components and publishing to the kit.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Created for use within tools such as Figma, Adobe XD, or Sketch, to quickly iterate on design concepts.&lt;/li&gt;
&lt;li&gt;Design discovery can guide what is built into a design kit and overall design system.&lt;/li&gt;
&lt;li&gt;Enhances collaboration between designers and developers to translate design into code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Examples of design kits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/community/file/1121065701252736567/ios-16-ui-kit-for-figma&quot;&gt;iOS 16 UI Kit for Figma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/community/file/1035203688168086460/material-3-design-kit&quot;&gt;Material Design 3 Design Kit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nordhealth.design/downloads/#figma-templates&quot;&gt;Nordhealth - Figma Templates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Morale of the Story&lt;/h2&gt;
&lt;p&gt;Design systems are a great way to organize, collaborate, and iterate upon your organization&apos;s design ideas.&lt;/p&gt;
&lt;p&gt;Design systems can be as simple or as complex as necessary (though strive for simple, please!) and are a living machine for your organization&apos;s design principles, guidelines, tools, and more.&lt;/p&gt;
&lt;p&gt;If your organization is not currently utilizing a design system, it may be beneficial towards more efficient design practices by instituting these design system features.&lt;/p&gt;
</content:encoded></item><item><title>The Internet according to me</title><link>https://ryantrimble.com/blog/the-internet-according-to-me/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-internet-according-to-me/</guid><description>Inside me are two wolves and they both are connected to WiFi.</description><pubDate>Sat, 25 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes I feel like I share the same birthday as the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I know that isn&apos;t true, but my near 36 rotations have seen many milestones for that massive network of computers, the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Much of my life has involved computers and the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;My first experience with computers was at my elementary school&apos;s computer lab, where I played &lt;a href=&quot;https://oregontrail.ws/&quot;&gt;&lt;em&gt;Oregon Trail&lt;/em&gt;&lt;/a&gt; on old Apple computers. Eventually my family had a computer where I learned all sorts of things on the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I met friends online. I wrote HTML to make cool pages for my &lt;a href=&quot;https://www.neopets.com/&quot;&gt;&lt;em&gt;Neopets&lt;/em&gt;&lt;/a&gt; and created &lt;a href=&quot;https://en.wikipedia.org/wiki/GeoCities&quot;&gt;&lt;em&gt;GeoCities&lt;/em&gt;&lt;/a&gt; websites for the weird little hobbies I had. I discovered music and movies and video games on the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I &quot;grew up&quot; and began professional life in Information Technology. Working with computers, networking, and just in-general Internet &lt;em&gt;stuff&lt;/em&gt;. I eventually made the switch to writing code, creating websites and applications, online, on the &lt;em&gt;Internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Honestly, I&apos;m worried about my old friend, the &lt;em&gt;Internet&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;A brief 80+ year history&lt;/h2&gt;
&lt;p&gt;Obviously the Internet was conceived of long before myself. Traces of the Internet span an earnest 80+ year history, emerging around the 1950s as &lt;em&gt;Computer Science&lt;/em&gt; gained popularity.&lt;/p&gt;
&lt;h3&gt;&apos;50s - Computer Science&lt;/h3&gt;
&lt;p&gt;While Computer Science existed for a while, interest certainly grew in the &apos;40s and &apos;50s (war and innovation, name a better duo), as did the need to make these machines talk to each other. People needed to share what they were learning about these things.&lt;/p&gt;
&lt;p&gt;You&apos;ve probably seen those room-sized computers, typically installed in colleges, government facilities, labs. These puppies were &lt;em&gt;BIG&lt;/em&gt; and &lt;em&gt;EXPENSIVE&lt;/em&gt; and &lt;em&gt;LOUD&lt;/em&gt; to run. So when they ran idle, it was much wasted potential.&lt;/p&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;post-image&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;cite class=&quot;container&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;Big, expensive, and loud computer, &lt;a href=&quot;https://en.wikipedia.org/wiki/ENIAC&quot;&gt;&lt;em&gt;ENIAC&lt;/em&gt;&lt;/a&gt;. Photo Credit: &lt;a href=&quot;https://en.wikipedia.org/wiki/ENIAC#/media/File:Glen_Beck_and_Betty_Snyder_program_the_ENIAC_in_building_328_at_the_Ballistic_Research_Laboratory.jpg&quot;&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;The logical next step was figuring out how to share these computational resources with other people, to fill that idle time with tasks to perform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; want to &lt;em&gt;learn&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;60s - Packet Switching&lt;/h3&gt;
&lt;p&gt;Packet switching, invented by &lt;a href=&quot;https://en.wikipedia.org/wiki/Paul_Baran&quot;&gt;Paul Baran&lt;/a&gt; and later iterated upon by &lt;a href=&quot;https://en.wikipedia.org/wiki/Donald_Davies&quot;&gt;Donald Davies&lt;/a&gt;, is the concept of bundling up data into packets to be sent and received over digital networks. This process could be performed over the existing telephone line infrastructure of the time.&lt;/p&gt;
&lt;p&gt;Now all those huge, expensive, and loud computer machines could communicate on a much larger, wide area network. People would be able to communicate in much different ways.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; learn &lt;em&gt;together&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;70s - ARPANET&lt;/h3&gt;
&lt;p&gt;Like &lt;a href=&quot;https://en.wikipedia.org/wiki/Closed_captioning&quot;&gt;many&lt;/a&gt; &lt;a href=&quot;https://www.cdc.gov/flu/prevent/flushot.htm&quot;&gt;good&lt;/a&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Doppler_radar&quot;&gt;technologies&lt;/a&gt;, the United States government got involved.&lt;/p&gt;
&lt;p&gt;The US Department of Defense and its &lt;em&gt;Defense Advanced Research Projects Agency&lt;/em&gt; (or DARPA) built &lt;a href=&quot;https://en.wikipedia.org/wiki/ARPANET&quot;&gt;ARPANET&lt;/a&gt;, a large scale &lt;em&gt;inter&lt;/em&gt;connected computer &lt;em&gt;net&lt;/em&gt;work throughout the states.&lt;/p&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;post-image&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;cite class=&quot;container&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;The character of Donald Anderson, DARPA Chief from the video game &lt;a href=&quot;https://en.wikipedia.org/wiki/Metal_Gear_Solid_(1998_video_game)&quot;&gt;&lt;em&gt;Metal Gear Solid&lt;/em&gt;&lt;/a&gt; (Konami 1998, Sony Playstation). This is the only thing I think about when I see &quot;DARPA&quot; because my brain is broken. Photo Credit: &lt;a href=&quot;https://metalgear.fandom.com/wiki/Donald_Anderson?file=Anderson1I1.png&quot;&gt;Metal Gear Wiki&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Spoiler:&lt;/em&gt; ARPANET is &lt;em&gt;the ancestor&lt;/em&gt; to the Internet as we know it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; build &lt;em&gt;connections&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;80s - DNS and ISP&lt;/h3&gt;
&lt;p&gt;Just as phonebooks are available to help people lookup phone numbers, computers needed ways to look up another computer.&lt;/p&gt;
&lt;p&gt;New protocols were developed, connected devices receive an &lt;em&gt;Internet protocol address&lt;/em&gt; (similar to phone numbers). Now, how to make it friendlier? This is what the &lt;em&gt;Domain Name System&lt;/em&gt; (DNS) was created to do.&lt;/p&gt;
&lt;p&gt;Computer networks, known as &lt;em&gt;domains&lt;/em&gt;, would utilize their &lt;em&gt;domain names&lt;/em&gt; as a unique way to reference each other. DNS will translate domain names to IP addresses, enabling networks to become more reachable - after all, it&apos;s much easier to remember &lt;code&gt;ryantrimble.com&lt;/code&gt; than something like &lt;code&gt;75.2.60.5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As cool as a network of computers is by itself, it&apos;s gonna get &lt;em&gt;so much cooler&lt;/em&gt; when real people gain access and actually &lt;em&gt;use it&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;People, like the &lt;a href=&quot;https://en.wikipedia.org/wiki/Homebrew_Computer_Club&quot;&gt;Homebrew Computer Club&lt;/a&gt;, built these computer things in their garages. Computers start showing up in more colleges, businesses are bringing in smaller hardware for employee usage. Personal Computing is like a &lt;em&gt;thing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;post-image&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;cite class=&quot;container&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;Legend and co-founder of the Homebrew Computer Club, &lt;a href=&quot;https://en.wikipedia.org/wiki/Gordon_French&quot;&gt;Gordon French&lt;/a&gt;, sitting in front of two computers, photographed in 2013. Photo Credit: &lt;a href=&quot;https://en.wikipedia.org/wiki/Homebrew_Computer_Club#/media/File:Gordon_French_(2013).jpg&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;Internet Service Providers (ISPs) sell access to computer networks. It works by dialing a phone number and placing the phone&apos;s handset onto a modem box connected to your computer.&lt;/p&gt;
&lt;p&gt;With Internet access, you can do fun things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read research papers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nobody has really heard of a &quot;website&quot; yet, but it&apos;s all about to fall into place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; innovate with &lt;em&gt;systems&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;90s - World Wide Web&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.w3.org/People/Berners-Lee/&quot;&gt;Tim Berners-Lee&lt;/a&gt; and &lt;a href=&quot;https://home.web.cern.ch/about&quot;&gt;CERN&lt;/a&gt; invented &lt;a href=&quot;https://info.cern.ch/&quot;&gt;websites&lt;/a&gt; which &lt;em&gt;changed everything forever&lt;/em&gt;. I bet you are reading this post on a website right now, in fact!&lt;/p&gt;
&lt;p&gt;Personal Computers were shipping with operating systems, network connectivity, and browser applications.&lt;/p&gt;
&lt;p&gt;This is when a lot of websites were newly created for everything: governments, corporations, businesses, churches, clubs, libraries, music, art, sports, politics, and even personal use.&lt;/p&gt;
&lt;p&gt;I think when folks wax poetic about the weird web, this is what they might be thinking about. People had no idea what was going on: lots of time spent playing, learning, and experimenting during this weird era. You just put stuff out there and hoped the right people saw it.&lt;/p&gt;
&lt;p&gt;The Internet expanded very fast thanks to websites.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; create for &lt;em&gt;people&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;00s - Social Media&lt;/h3&gt;
&lt;p&gt;Folks eventually gathered on &lt;em&gt;certain&lt;/em&gt; websites.&lt;/p&gt;
&lt;p&gt;Places like &lt;a href=&quot;https://en.wikipedia.org/wiki/Myspace&quot;&gt;Myspace&lt;/a&gt; helped folks setup an online presence much quicker than creating a website. Much cheaper than finding website hosting and purchasing a domain name. Much easier than learning how to code.&lt;/p&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;post-image&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;cite class=&quot;container&quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;I wonder if I&apos;m still in anyones top 8. Photo credit: &lt;a href=&quot;https://en.wikipedia.org/wiki/Myspace&quot;&gt;Wikipedia&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;People are mostly social creatures, right? Now they have access to virtually &lt;em&gt;anyone&lt;/em&gt;, for better or worse. The Internet is a &lt;em&gt;fun&lt;/em&gt;, albeit &lt;em&gt;mysterious&lt;/em&gt; and &lt;em&gt;scary&lt;/em&gt;, but still &lt;em&gt;fun&lt;/em&gt; place.&lt;/p&gt;
&lt;p&gt;More and more things move online. The Internet becomes &lt;em&gt;the place&lt;/em&gt; to socialize and share: ideas, art, videos, and whatever thoughts a person might have.&lt;/p&gt;
&lt;p&gt;Oh, also everything is faster too. Those Internet Service Providers are pushing packets around at &lt;a href=&quot;https://en.wikipedia.org/wiki/Fiber-optic_communication&quot;&gt;the fucking speed of light&lt;/a&gt; in many places.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;People&lt;/em&gt; share with &lt;em&gt;communities&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;10s - Capitalism Ruins It&lt;/h3&gt;
&lt;p&gt;Natural laws govern human nature and all that, &lt;em&gt;of course&lt;/em&gt; we figured out a way to squeeze all the money out of this.&lt;/p&gt;
&lt;p&gt;We see the rise of eCommerce sites, targeted advertisements popping up due to analytic data gathered from tracking &lt;em&gt;users&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Different&lt;/em&gt; social media sites are popular now and they try to eat up all their user&apos;s time browsing the Internet. Which turns out, people will spend &lt;em&gt;a lot of time browsing&lt;/em&gt; when it&apos;s pocket-size and available &lt;em&gt;everywhere&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Corporations&lt;/em&gt; create for &lt;em&gt;users&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&apos;20s - Current Hellscape&lt;/h3&gt;
&lt;p&gt;The Internet is in everything now.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Phones:&lt;/strong&gt; &lt;em&gt;connected&lt;/em&gt;, easy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Televisions:&lt;/strong&gt; &lt;em&gt;connected&lt;/em&gt;, how fun.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lightbulbs:&lt;/strong&gt; &lt;em&gt;connected&lt;/em&gt;, um ok.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cars:&lt;/strong&gt; &lt;em&gt;connected&lt;/em&gt;, that could be dangerous.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&apos;ve got these little speaker boxes that listen to us and answer all our questions, but are mostly just used for maybe two commands: &lt;em&gt;connected&lt;/em&gt;, the lightbulbs make more sense now at least.&lt;/p&gt;
&lt;p&gt;Those targeted advertisements are now showing &lt;em&gt;before&lt;/em&gt;, &lt;em&gt;during&lt;/em&gt;, and &lt;em&gt;after&lt;/em&gt; every news article, online game, and video. Some folks think these ads can read minds, so are our minds &lt;em&gt;connected?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;People group up with other like-minded folks. They stop sharing ideas, instead fight over them.&lt;/p&gt;
&lt;p&gt;Also, it&apos;s not just &lt;em&gt;people&lt;/em&gt; browsing, learning, and creating on the Internet anymore. Artificial Intelligence is growing faster than can be sustained. This is another one of those &lt;em&gt;changes everything forever&lt;/em&gt; type things.&lt;/p&gt;
&lt;p&gt;People tell computers what they want and it returns a rough approximation, no matter the cost. Computers scrape together all the thoughts and ideas and art and expression that people have and its &lt;em&gt;like ✨magic✨&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Computers&lt;/em&gt; are &lt;em&gt;creating&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;What do we do?&lt;/h2&gt;
&lt;p&gt;Excellent question.&lt;/p&gt;
&lt;p&gt;I&apos;ve been wracking my brain trying to figure out a conclusion to the post. This topic has been on my mind for a while, but have been thinking about it a lot more recently.&lt;/p&gt;
&lt;p&gt;Probably because of a &lt;a href=&quot;https://humanewebmanifesto.com/&quot;&gt;Manifesto for a Humane Web&lt;/a&gt; written by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Michelle Barker&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Probably because of &lt;a href=&quot;https://www.youtube.com/watch?v=P-I5D6BlejM&quot;&gt;Henry Desroches&apos; talk&lt;/a&gt; at the &lt;a href=&quot;https://conf.11ty.dev/&quot;&gt;11ty Conf&lt;/a&gt; on &lt;a href=&quot;https://conf.11ty.dev/2024/digital-frontiers-indieweb-cowboys-and-a-place-online-to-call-your-own/&quot;&gt;owning your own content&lt;/a&gt; and the mission of the &lt;a href=&quot;https://indieweb.org/&quot;&gt;IndieWeb&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Probably because there are still awesome &lt;em&gt;people&lt;/em&gt; out there creating, learning, and sharing with &lt;em&gt;other people&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;So, What do we do? I can&apos;t tell you that because I don&apos;t know the answer — but I&apos;d love to hear your opinion.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #5</title><link>https://ryantrimble.com/blog/weekly-roundup-5/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-5/</guid><description>Cool things this week: ones and zeroes, single divs, 11ty, and Ben Myers.</description><pubDate>Sat, 25 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.alanwsmith.com/en/20en8mvx/?how-computers-work-the-1s-and-0s&quot;&gt;How Computers Work: The 1s And 0s&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.alanwsmith.com/&quot;&gt;Alan W. Smith&lt;/a&gt; on March 24, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;From the creative mind of Alan W. Smith, comes an interactive light switch adventure... Really clever way to demonstrate how the bits all add up!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NwnZU6mWJkk&quot;&gt;Add an overlay to a background-image with one line of CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.kevinpowell.co/&quot;&gt;Kevin Powell&lt;/a&gt; on March 23, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Kevin Powell teaches us how to write a super handy, one-line, linear-gradient, &lt;code&gt;.overlay&lt;/code&gt; class using the dark arts of &lt;code&gt;border-image&lt;/code&gt; properties.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://lynnandtonic.com/thoughts/entries/ten-years-of-a-single-div/&quot;&gt;Ten Years of A Single Div&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://lynnandtonic.com/&quot;&gt;Lynn Fisher&lt;/a&gt; on March 22, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Lynn Fisher talks about her &lt;em&gt;ten years&lt;/em&gt; of being a total &lt;em&gt;badass&lt;/em&gt; on the net with &lt;a href=&quot;https://a.singlediv.com/&quot;&gt;A Single Div&lt;/a&gt;. Seriously, thank you Lynn for continuing to be an inspiration to this craft.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://benmyers.dev/&quot;&gt;Ben Myers - Web Developer. Accessibility Advocate. Human T-rex.&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Ben Myers&lt;/a&gt; on March 22, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Check out Ben&apos;s updated website, it looks awesome! I contiue to learn a lot from this website in particular, between the incredible articles and literally inspecting the code to see how Ben does things. I highly recommend Ben.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.zachleat.com/web/independent-sustainable-11ty/&quot;&gt;I need your help to make 11ty fully independent and sustainable in 2024&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.zachleat.com/&quot;&gt;Zach Leatherman&lt;/a&gt; on March 21, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I can&apos;t think of an open source project more deserving than what Zach Leatherman and co. are doing with 11ty. If you believe in open source, please consider supporting the project.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://nerdy.dev/using-starting-style-and-transition-behavior-for-enter-and-exit-stage-effects&quot;&gt;Using @starting-style and transition-behavior for enter and exit stage effects&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; on March 20, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;A collective sigh of relief echoes across the web as CSS developers are finally able to animate from &lt;code&gt;display: none&lt;/code&gt; and Adam shows us how using &lt;code&gt;@starting-style&lt;/code&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #6</title><link>https://ryantrimble.com/blog/weekly-roundup-6/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-6/</guid><description>This was a really long, short week - but these articles helped me through it.</description><pubDate>Sat, 25 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://adhdftw.com/memory-recollection-issues-with-adhd/&quot;&gt;Memory recollection issues with ADHD&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on March 31, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Chris is connecting so many dots in my head that I think he is secretly writing these articles about me. &lt;em&gt;Serious shout out&lt;/em&gt; to Chris for this series of daily tips, it&apos;s been super helpful in figuring out how my own brain works.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I also get flustered super easily in high-pressure real time conversations. I am much better in writing, and as a result, seem to favor online conversations where I can take a beat to think first.&lt;/p&gt;
&lt;p&gt;-- Chris Ferdinandi&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/the-gap/&quot;&gt;The Gap&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on March 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Ahmad does another deep dive, this time into one of my favorite of the (relatively) newer CSS properties: the &lt;code&gt;gap&lt;/code&gt;. I love when Ahmad does these, always a great reminder how much thought went into developing these features, &lt;em&gt;on top&lt;/em&gt; of showing some great examples on how to incorporate them into your projects.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://noahliebman.net/2024/05/yet-another-take-on-layout-breakouts/&quot;&gt;Yet another take on layout breakouts&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://noahliebman.net&quot;&gt;Noah Liebman&lt;/a&gt; on March 30, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I love me a small CSS snippet that demonstrate how capable CSS is nowadays. Noah shows us a nice, simple, and powerful addition to your CSS toolkit. Be sure to check out this &lt;em&gt;breakout article&lt;/em&gt; on layout breakouts.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.mayank.co/blog/web-components-considered-harmful/&quot;&gt;&quot;Web components&quot; considered harmful&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; on March 28, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Mayank provides great context into common misconceptions surrounding the terminology of &quot;web components&quot; — but more importantly has me quesitoning if water &lt;em&gt;is wet&lt;/em&gt; or if it &lt;em&gt;makes things wet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://alex.party/posts/2024-05-27-my-recent-container-query-use-pagination/&quot;&gt;My Recent Container Query Use: Pagination&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://alex.party/&quot;&gt;Alex Riviere&lt;/a&gt; on March 27, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Last year at CSS Day, Miriam Suzanne declared us safe to use container queries. Now it seems we need examples, so Alex is here to help with that. Awesome use-case, demonstrating how one might use container queries with a pagination component.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #4</title><link>https://ryantrimble.com/blog/weekly-roundup-4/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-4/</guid><description>Stairs, masonry, anchors, and manifestos - what a week!</description><pubDate>Sat, 18 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://georgefrancis.dev/writing/fluid-design-with-css-round/&quot;&gt;Fluid Design with CSS Round&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://georgefrancis.dev/&quot;&gt;George Francis&lt;/a&gt; on March 17, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;George redesigned his site recently and &lt;em&gt;just&lt;/em&gt; released this great advice on using the upcoming CSS &lt;code&gt;round()&lt;/code&gt; function to apply fluid design to your styles.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://lofi.codes/pen/the-shed-stairs/&quot;&gt;The Shed - Stairs&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://lofi.codes/&quot;&gt;David Fitzgibbon&lt;/a&gt; on March 15, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;m a big fan of David&apos;s work and this one made me smile. David first built this in 3D using ThreeJS, in order to help him understand how to recreate this in plain old CSS. Does this mean CSS is the fourth dimension??&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://piccalil.li/blog/masonry-and-tabbing/&quot;&gt;I&apos;m worried about the tabbing behaviour, rather than the syntax and name of CSS masonry&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.youtube.com/watch?v=dQw4w9WgXcQ&quot;&gt;Andy Bell&lt;/a&gt; on March 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Andy discusses an issue discovered while exploring the new &quot;masonry&quot; style grid that is being debated by Apple and Google. Applying this masonry-style layout causes some unexpected behavior regarding the tab order, which will &lt;em&gt;not be fun&lt;/em&gt; for assistive device users who rely on tabbing through a page.&lt;/p&gt;
&lt;p&gt;I&apos;m interested to see more non-&lt;em&gt;Pinterest&lt;/em&gt; style use-cases for the masonry layout. I&apos;m not totally convinced this feature was a necessity, but it might help sites feel a touch more refined if used appropriately.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://developer.chrome.com/blog/anchor-positioning-api&quot;&gt;Introducing the CSS anchor positioning API&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Una Kravets&lt;/a&gt; on March 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://io.google/2024/&quot;&gt;Google I/O&lt;/a&gt; was this week, which usually introduces us to new developer features. Una gives a great rundown of CSS anchor positioning and created an &lt;a href=&quot;https://anchor-tool.com/&quot;&gt;achor positioning tool&lt;/a&gt; to help understand the &lt;code&gt;inset-area&lt;/code&gt; property a bit better.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://humanewebmanifesto.com/&quot;&gt;Manifesto for a Humane Web&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://michellebarker.co.uk/&quot;&gt;Michelle Barker&lt;/a&gt; on March 10, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;m always down for a good &lt;em&gt;manifesto&lt;/em&gt; and this one is &lt;em&gt;actually good&lt;/em&gt;. Michelle writes about how hostile the web has become, with concerns for privacy and AI being injected into everything.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.tpgi.com/subheadings-subtitles-alternative-titles-and-taglines-in-html/&quot;&gt;Subheadings, subtitles, alternative titles and taglines in HTML&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.tpgi.com/author/steve/&quot;&gt;Steve Faulkner&lt;/a&gt; on July 19, 2022.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This is a wonderful resource on how to help make the often overlooked &lt;code&gt;&amp;lt;hgroup&amp;gt;&lt;/code&gt; tag more useful and semantic. I have this in my bookmarks and dig it out often enough, might be helpful to you.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://blog.castac.org/2022/04/disability-dongle/&quot;&gt;Disability Dongle&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://blog.castac.org/author/lizjackson/&quot;&gt;Liz Jackson&lt;/a&gt;, &lt;a href=&quot;https://blog.castac.org/author/alexhaagaard/&quot;&gt;Alex Haagaard&lt;/a&gt;, and &lt;a href=&quot;https://blog.castac.org/author/ruawilliams/&quot;&gt;Rua Williams&lt;/a&gt; on July 19, 2022.&lt;/p&gt;
&lt;p&gt;shared by &lt;a href=&quot;https://front-end.social/@ben@a11y.info/112451099901470013&quot;&gt;Ben Myers&lt;/a&gt; on May 16, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Ben shared this excellent read for &lt;a href=&quot;https://accessibility.day/&quot;&gt;Global Accessibility Awareness Day&lt;/a&gt;. Discusses how good intentions can backfire, especially when you are solving for problems that don&apos;t exist.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #3 — Possum Edition</title><link>https://ryantrimble.com/blog/weekly-roundup-3/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-3/</guid><description>This week I annoyed everyone at the 11ty conference.</description><pubDate>Sat, 11 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I mostly wanna talk about the &lt;a href=&quot;https://conf.11ty.dev/&quot;&gt;&lt;em&gt;International Symposium on Making Websites Real Good&lt;/em&gt; conference&lt;/a&gt;. It was so much fun!&lt;/p&gt;
&lt;h2&gt;Interesting ~Links~ Talks&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=WSKovzRKxipqfWl-&amp;amp;t=2160&quot;&gt;The Future of 11ty&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://www.zachleat.com/&quot;&gt;Zach Leatherman&lt;/a&gt; on May 9, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Zach provided great updates on the state of 11ty, version &lt;code&gt;3.0&lt;/code&gt; changes, enhancements to &lt;a href=&quot;https://github.com/11ty/eleventy-img&quot;&gt;&lt;code&gt;eleventy-img&lt;/code&gt;&lt;/a&gt;, and more! The 11ty community are eating good.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=JrveXQN4Kwwsyctd&amp;amp;t=4080&quot;&gt;Hints &amp;amp; Suggestions (First, Do No Harm)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://www.miriamsuzanne.com/&quot;&gt;Miriam Suzanne&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;No matter if you watch Miriam speak in-person or on a stream, you are in for a treat. A thoughtful tour through the history of design on the web. Miriam is one of my favorite people.&lt;/p&gt;
&lt;p&gt;&amp;lt;blockquote&amp;gt;&lt;/p&gt;
&lt;p&gt;&quot;Graphic design of &lt;em&gt;unknown content&lt;/em&gt; with &lt;em&gt;unknown collaborators&lt;/em&gt;, on and &lt;em&gt;infinite and unknowable canvas&lt;/em&gt;, across &lt;em&gt;operating systems, interfaces, languages, and writing modes&lt;/em&gt;&quot;&lt;/p&gt;
&lt;p&gt;&amp;lt;cite&amp;gt;— Miriam Suzanne&amp;lt;/cite&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/blockquote&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=u_6VzUBzOmS2K4ZJ&amp;amp;t=5610&quot;&gt;11ty and Large Project Tooling&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://www.jetbrains.com/guide/authors/pwe/&quot;&gt;Paul Everitt&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Paul demonstrated how to use 11ty &lt;em&gt;like a pro&lt;/em&gt;. Bringing component-driven development to 11ty with TypeScript, TSX, and testing through Vitest.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=pm7L-IydkE9gRNBW&amp;amp;t=8542&quot;&gt;Digital Frontiers, IndieWeb Cowboys, and a Place Online to Call Your Own&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://henry.codes&quot;&gt;Henry Desroches&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Henry pleads the case for IndieWeb and why it&apos;s best to publish your own content and syndicate it elsewhere. Own your content, folks!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=D94JIRs-Aa76xZ2K&amp;amp;t=9583&quot;&gt;You&apos;re Probably Doing Web Performance Wrong&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://sia.codes/&quot;&gt;Sia Karamalegos&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;While the &lt;a href=&quot;https://pagespeed.web.dev/&quot;&gt;Lighthouse&lt;/a&gt; can often bring your ship towards land, Sia is here to help you set up a port authority. Breaking down performance gains while centering on user experience. I don&apos;t know where that metaphor came from.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=9HqRLCPUYNqxt3Hp&amp;amp;t=10833&quot;&gt;Building a Town That Doesn&apos;t Exist&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;questionmarkohio.com&quot;&gt;Dan Sinker&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This was a brilliant pause from the technical side of the conference. Dan demonstrated how he uses the power of the web to tell a story, creating the believable town of Q&lt;em&gt;uestion Mark, Ohio&lt;/em&gt;. What an intriguing project!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=6EPKhvGiRDZEXSx7&amp;amp;t=12900&quot;&gt;11ty Sites for People Who Don&apos;t Think They Are Web Developers&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://popagandhi.com/&quot;&gt;Adrianna Tan&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Adrianna shares her story on how 11ty empowered her to develop more websites and gives a rundown on how it can help others too.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=fE6HTNAa4ID-GksW&amp;amp;t=13850&quot;&gt;Don&apos;t Fear The Cascade&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Mayank introduced lots of folks to selector specificfity... specificity, &lt;code&gt;@scope&lt;/code&gt;, and CSS Layers, always fun to see excitement for CSS!&lt;/p&gt;
&lt;p&gt;I use Mayank&apos;s &lt;a href=&quot;https://github.com/mayank99/reset.css&quot;&gt;CSS reset&lt;/a&gt; on many of my personal projects and this talk gave some great insight into the logic used to create &lt;code&gt;@acab/reset.css&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=RAvw4sa5ELtDI87r&amp;amp;t=15410&quot;&gt;Managing Content Management (With No Vendor Lock-in)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://twitter.com/liambigelow?lang=en&quot;&gt;Liam Bigelow&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/avidlarge&quot;&gt;David Large&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This is a super interesting talk and one that might be relevent for a project I have in mind. Liam and David describe a problem larger organizations may run into and offer up a Jamstack-style solution. Also, the red balloon was a nice touch!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=mYs5VKX9kMxhLs4r&amp;amp;t=17435&quot;&gt;Come to the Light Side: HTML Web Components&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://gomakethings.com/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I always love when a talk makes me want to &lt;em&gt;go make things&lt;/em&gt; and Chris certainly got the gears turning in my head around this pattern of HTML-first web components. Legendary talk and perfect introduction to native web components.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.youtube.com/live/iLxJ6PtuF9M?si=SDIH4hmkvdFk4ays&amp;amp;t=18955&quot;&gt;Chinese Type Systems&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a href=&quot;https://ivanzhao.me/&quot;&gt;Ivan Zhao&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;As someone with little experience with languages other than English, this talk was &lt;em&gt;fascinating&lt;/em&gt;. Ivan traces the roots of Chinese characters to where we are today, with web typography and Chinese type systems.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a&gt;~Light Mode Versus Dark~ Mode Why Not Both?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;presented by &lt;a&gt;Sara Joy&lt;/a&gt; on May 9, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Sara proves that there is always &lt;em&gt;something&lt;/em&gt; to learn in web development. Did you know you can enable light mode and dark mode without &lt;em&gt;any CSS&lt;/em&gt;? What an pleasant conclusion to the conference.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #2</title><link>https://ryantrimble.com/blog/weekly-roundup-2/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-2/</guid><description>Update on CSS Harrisburg, interesting links from the week, and Adam Kuhn is the DOOM Slayer?</description><pubDate>Sat, 04 May 2024 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Housekeeping&lt;/h2&gt;
&lt;p&gt;Before we dig into this weeks interesting links, I wanted to do some housekeeping.&lt;/p&gt;
&lt;p&gt;A new friend reached out about an announcement I had made a while back, &lt;a href=&quot;https://cssharrisburg.com/&quot;&gt;CSS Harrisburg&lt;/a&gt; - a local meet up group for web developers and I wanted to give an update for those interested:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First of all - if you are interested, reach out to me already, sheesh!&lt;/li&gt;
&lt;li&gt;Second of all, &lt;em&gt;life happens&lt;/em&gt; and you are already coming up on a year since thinking of something.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I still have my notes and plans - my schemes, if you will. Hopefully the motivation will kick in soon and we&apos;ll be all set.&lt;/p&gt;
&lt;p&gt;Thanks &lt;a href=&quot;https://asuh.com/&quot;&gt;Micah&lt;/a&gt; for reaching out!&lt;/p&gt;
&lt;h2&gt;Interesting Links&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://peruvianidle.mikeaparicio.com/2/&quot;&gt;All in on Balatro - Peruvian Idle #2&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.mikeaparicio.com/&quot;&gt;Mike Aparicio&lt;/a&gt; on May 1, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;My friend Mike created a newsletter where he breaks down recent movies, television shows, and video games he&apos;s been into. If you know Mike - or follow him on Letterboxd - you know he has great taste. Definitely worth subscribing!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://cruncher.ch/blog/printing-music-with-css-grid/&quot;&gt;Printing Music with CSS Grid&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://cruncher.ch/blog/printing-music-with-css-grid/&quot;&gt;Stephen Band of Cruncher&lt;/a&gt; on April 24, 2024&lt;/p&gt;
&lt;p&gt;shared by &lt;a href=&quot;https://front-end.social/@kevinpowell/112371500374036780&quot;&gt;Kevin Powell on Mastodon&lt;/a&gt; on May 1, 2024.&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Stephen Band wrote about how he is using modern CSS techniques to render sheet music. As a guitarist and a CSS developer, I&apos;m sold! I find reading music, chords, or tablature on devices frustrating. Constantly having to stop, zoom, and scroll around while trying to quickly learn a new piece. I&apos;m excited to try this one out!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://ishadeed.com/article/tree-view-css-indent/&quot;&gt;Handling The Indentation of a Treeview Component&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://ishadeed.com/&quot;&gt;Ahmad Shadeed&lt;/a&gt; on April 30, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Ahmad does an incredible deep-dive into different patterns for handling nested treeview components. Excellent UX research on how a few different companies handle this within products.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://codepen.io/cobra_winfrey/full/oNOMRav&quot;&gt;DOOM Scrolling&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://front-end.social/@cobra_winfrey&quot;&gt;Adam Kuhn&lt;/a&gt; on April 29, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Adam released his project from his 2024 Front End Conf talk, DOOM Scroll. Adam uses CSS and CSS only to create a (somewhat) playable version of the classic DOOM video game, proving again that &lt;a href=&quot;https://www.youtube.com/watch?v=lp3X4IL4_UA&quot;&gt;DOOM really can run on anything&lt;/a&gt;. Rip and tear, Adam.&lt;/p&gt;
&lt;h2&gt;Parting Notes&lt;/h2&gt;
&lt;p&gt;I&apos;m not a reader.&lt;/p&gt;
&lt;p&gt;Like, I read to learn, online stuff mostly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blogs, RSS feeds, newsletters from people that teach me things.&lt;/li&gt;
&lt;li&gt;Technical documentation, for better or wose.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I do like comics and graphic novels, but for very similar reasons as to why &lt;a href=&quot;i-love-cartoons&quot;&gt;I love cartions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My point being: I read one whole &lt;em&gt;non&lt;/em&gt;-nonfiction - uhh, whatya call &apos;em - &lt;em&gt;fiction&lt;/em&gt; book. And I&apos;ve already sunk into it&apos;s sequel! Guess what? It&apos;s a trilogy! That means there is another one after that!&lt;/p&gt;
&lt;p&gt;I&apos;m trying to form some new routines and I&apos;ve enjoyed making &quot;reading for fun&quot; part of those routines. You can follow along with my reading journey on my &lt;a href=&quot;https://literal.club/mrtrimble&quot;&gt;literal.club profile&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Weekly Roundup #1</title><link>https://ryantrimble.com/blog/weekly-roundup-1/</link><guid isPermaLink="true">https://ryantrimble.com/blog/weekly-roundup-1/</guid><description>Obsidian has me taking notes on everything, include these great links!</description><pubDate>Sat, 27 Apr 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been using &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; for &lt;em&gt;just over&lt;/em&gt; a month now, I am kind of hooked on it. I like the whole &quot;second brain&quot; thing, which we will get to in a moment, but mostly I like the Daily Notes feature. It&apos;s simple and straightforward, I just like jotting down things about my day in there.&lt;/p&gt;
&lt;p&gt;In my Daily Notes, I record interesting links that I come across during my day. Now, I&apos;d like to pass that savings onto &lt;em&gt;you&lt;/em&gt;, the readers of this blog.&lt;/p&gt;
&lt;p&gt;I read a lot of blog posts, so a lot of this might be rehashing the RSS feeds, although I also want to share anything that may have helped me out during week as well as I would love a place to thank folks.&lt;/p&gt;
&lt;p&gt;I thought about doing this as a newsletter, but there are many great newsletters out there that do similar things - probably best to go subscribe to those if you are looking for something well organized and consistent, because I&apos;m sure I will forget to do this at some point (maybe even as early as next week, so stay tuned to be disappointed).&lt;/p&gt;
&lt;p&gt;With that out of the way - let&apos;s jump into what my brain thought was interesting this week!&lt;/p&gt;
&lt;h2&gt;Interesting Articles&lt;/h2&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://darn.es/date-pickers-are-hard/&quot;&gt;Date pickers are hard&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://darn.es/&quot;&gt;David Darnes&lt;/a&gt; on April 25, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;David is &lt;em&gt;not lying&lt;/em&gt; when he says Date pickers are hard. Browser native date pickers even have their issues, especially on mobile devices. David suggests &lt;a href=&quot;https://wicky.nillia.ms/&quot;&gt;Nick William&lt;/a&gt;&apos;s &lt;a href=&quot;https://wicky.nillia.ms/cally/&quot;&gt;Cally&lt;/a&gt; package as a great alternative.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://kilianvalkhof.com/2024/javascript/the-problem-with-new-url-and-how-url-parse-fixes-that/&quot;&gt;The problem with new URL(), and How URL.parse() Fixes that&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt; on April 24, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;If Kilian is excited about something, I&apos;m excited about that something. This looks like a great new addition for parsing those pesky URLs!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://adhdftw.com/second-brain-tool-obsidian/&quot;&gt;Second brain tool: Obsidian&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://adhdftw.com/about/&quot;&gt;Chris Ferdinandi&lt;/a&gt; on April 23, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Friend and JavaScript guru, Chris Ferdinandi, has created a new resource for folks with ADHD where he&apos;s posting daily about the subject, including this great article on how to use Obsidian as a second brain. Great tips on how to set up a simple workflow for managing tasks and more!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.csscade.com/how-to-create-css-utility-classes&quot;&gt;How to create CSS utility classes&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://robinrendle.com/&quot;&gt;Robin Rendle&lt;/a&gt; on April 19th, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;I&apos;ve been doing a lot of research on building Design Systems, so this piece on how to generate CSS Utility Classes from JSON design tokens was relevant. Certainly got the gears turning for a personal project!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://webkit.org/blog/15269/help-us-invent-masonry-layouts-for-css-grid-level-3/&quot;&gt;Help us invent CSS Grid Level 3, aka “Masonry” layout&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://jensimmons.com/&quot;&gt;Jen Simmons&lt;/a&gt; on April 19, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Jen Simmons posted some updated demos for the CSS Grid, so called &quot;masonry&quot; layouts (or should I say, waterfall...). I&apos;m always excited to try out new CSS features, even if they aren&apos;t production ready!&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://heydonworks.com/article/testing-html-with-modern-css/&quot;&gt;Testing HTML with Modern CSS&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; on April 7, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Heydon demonstrates awesome error-handling techniques within CSS and how to display messages pointing out what might be causing problems.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.jameskerr.blog/posts/javascript-sort-comparators/&quot;&gt;JavaScript Sort Comparators&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://www.jameskerr.blog/&quot;&gt;James Kerr&lt;/a&gt; on March 28, 2024&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;Shared by Andy Bell over on &lt;a href=&quot;https://piccalil.li/links/finally-understanding-how-array-sort-comparator-works/&quot;&gt;Picalilli&lt;/a&gt;, James provides a great visual way to remember how to &lt;code&gt;.sort()&lt;/code&gt; things. I&apos;m used to the trial-by-fire approach of swapping things around until it does what I was hoping for, maybe I can save some of that frustration now.&lt;/p&gt;
&lt;p&gt;&amp;lt;hgroup&amp;gt;&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/&quot;&gt;Are your Anchor Links accessible?&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;posted by &lt;a href=&quot;https://amberwilson.co.uk/&quot;&gt;Amber Wilson&lt;/a&gt; on December 14, 2020&lt;/p&gt;
&lt;p&gt;&amp;lt;/hgroup&amp;gt;&lt;/p&gt;
&lt;p&gt;This article was shared by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; over on Frontend Horse, after some discussion on how to properly handle heading anchors. This is a rather common pattern that seems simple, but important to get right.&lt;/p&gt;
</content:encoded></item><item><title>What the heck is an SVG sprite sheet?</title><link>https://ryantrimble.com/blog/what-the-heck-is-an-svg-sprite-sheet/</link><guid isPermaLink="true">https://ryantrimble.com/blog/what-the-heck-is-an-svg-sprite-sheet/</guid><description>What is an SVG? What is a Sprite Sheet? Who are you? Those questions answered, and more.</description><pubDate>Fri, 29 Mar 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you work with me, you may have heard me mention SVG sprite sheets and wondered to yourself, &quot;Man... he&apos;s talking about SVG sprite sheets again, does Ryan not have &lt;em&gt;any&lt;/em&gt; actually fun hobbies?&quot;&lt;/p&gt;
&lt;p&gt;And to that I say: &quot;Thank you for asking about SVG sprite sheets.&quot;&lt;/p&gt;
&lt;p&gt;Now, am I a graphic designer? &lt;em&gt;Not exactly&lt;/em&gt;, though I think I do a pretty well &lt;a href=&quot;https://codepen.io/collection/qOWdLm?cursor=eyJwYWdlIjoxfQ%3D%3D&quot;&gt;navigating SVGs&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;SVG?&lt;/h2&gt;
&lt;p&gt;SVG, or Scalable Vector Graphic, is an XML-based way to describe two-dimensional graphics that stay crisp at any size (hence, &quot;scalable&quot; graphics).&lt;/p&gt;
&lt;p&gt;The cool part, though, is browsers know what to do with SVGs and can render them like HTML elements. This allows developers to embed graphics directly, inline with other parts of a page. Also, as a generous bonus, we can style and adjust SVGs with cascading style sheets.&lt;/p&gt;
&lt;h2&gt;Sprite Sheets?&lt;/h2&gt;
&lt;p&gt;Sprite sheets are a way to have many graphics available from one resource and are used in many different ways.&lt;/p&gt;
&lt;p&gt;In video games, sprites can be used for animating characters, actions, and environment elements. Sprite sheets have been used on the web for quite a long time as well.&lt;/p&gt;
&lt;p&gt;An older technique for sprite sheets on the web involved having a grid of graphics within a single image file, then positioning the image in a way that showed only one graphic at a time. This was clever, though it was painful to manage.&lt;/p&gt;
&lt;h2&gt;SVG Sprite Sheets?&lt;/h2&gt;
&lt;p&gt;Combining the power of SVG with the concept of sprite sheets provides an effective way to deliver graphics, like icons, to our users.&lt;/p&gt;
&lt;p&gt;SVG contains a feature called &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; which wraps around a graphic and turns it into something reusable, ideal for graphics such as icons. Adding an &lt;code&gt;id&lt;/code&gt; attribute to the &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; gives us a way to reference the symbol.&lt;/p&gt;
&lt;p&gt;We can &lt;em&gt;mostly&lt;/em&gt; add as many icons as we want, though there are some warnings here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fairly complex graphics may add to the weight of the overall page.&lt;/li&gt;
&lt;li&gt;Similarly, having a excessive amount of icons (think hundreds or thousands), will also cause performance issues&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Combined with the &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; element, SVG also provides us a way to &lt;em&gt;use&lt;/em&gt; the symbols, with &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; (duh, I guess). MDN says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;&lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt;&lt;/strong&gt; element takes nodes from within the SVG document, and duplicates them somewhere else. The effect is the same as if the nodes were deeply cloned into a non-exposed DOM, then pasted where the &lt;code&gt;use&lt;/code&gt; element is, much like cloned template elements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Neat! But wait, you might be thinking to yourself:&lt;/p&gt;
&lt;p&gt;&quot;I just remembered - writing SVGs by hand is a surefire path to madness, I thought you said this was cool&quot;&lt;/p&gt;
&lt;p&gt;...and you would be correct, this would be a pain to manage.&lt;/p&gt;
&lt;p&gt;Luckily there are some great tools that can help us accomplish creating SVG sprite sheets so much easier.&lt;/p&gt;
&lt;h2&gt;Generators&lt;/h2&gt;
&lt;p&gt;There are several SVG sprite sheet generators online where you can upload your icon SVG files and it&apos;ll spit out a sprite sheet.&lt;/p&gt;
&lt;p&gt;I have used https://svgsprit.es/ for this type of thing previously, mostly as a quick way to get something together. A much more preferable way of creating these sprite sheets might be something a bit more automated.&lt;/p&gt;
&lt;h2&gt;Automating&lt;/h2&gt;
&lt;p&gt;So, I&apos;m sure there are several ways to go about this, but the way I do this is by implementing this as a step within the build process.&lt;/p&gt;
&lt;p&gt;I primarily use &lt;a href=&quot;https://vitejs.dev/&quot;&gt;Vite&lt;/a&gt; as my build tool of choice, so let&apos;s use that to build a SVG sprite sheet.&lt;/p&gt;
&lt;h3&gt;Setup&lt;/h3&gt;
&lt;p&gt;Let&apos;s initialize a new Vite project for the purposes of this demonstration, but if you are already working on an existing Vite project, this will fit in nicely to your build process.&lt;/p&gt;
&lt;p&gt;To create a new Vite project, navigate to your project directory and run the following in the terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm create vite@latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Provide a name for the project and follow the prompts to complete. I named my project &lt;code&gt;svg-sprite-sheets&lt;/code&gt;, selected to work with vanilla JavaScript, but feel free to select whatever matches your preferences or project requirements.&lt;/p&gt;
&lt;p&gt;Navigate into the freshly created project and run &lt;code&gt;npm install&lt;/code&gt; to install dependencies.&lt;/p&gt;
&lt;h3&gt;Plugins&lt;/h3&gt;
&lt;p&gt;One of the many reasons I prefer Vite is due to it&apos;s vast community of developers who make awesome plugins and... hey would you look at that:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;npm install -D vite-svg-sprite-wrapper&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Yep, there is a &lt;a href=&quot;https://github.com/vshepel/vite-svg-sprite-wrapper&quot;&gt;Vite plugin&lt;/a&gt; to do exactly what we want to do, isn&apos;t that convenient?&lt;/p&gt;
&lt;p&gt;I love open source software! Shoutout to &lt;a href=&quot;https://github.com/vshepel&quot;&gt;vshepel&lt;/a&gt; on Github for this Vite plugin!&lt;/p&gt;
&lt;p&gt;Open up your project&apos;s &lt;code&gt;vite.config.js&lt;/code&gt; file, or if there is not one in your project directory, create a &lt;code&gt;vite.config.js&lt;/code&gt; file and include the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineConfig } from &apos;vite&apos;;
import ViteSvgSpriteWrapper from &apos;vite-svg-sprite-wrapper&apos;;

export default defineConfig({
  plugins: [ViteSvgSpriteWrapper()],
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We need to pass in some options, specifically where to locate the icons and the output directory for the sprite sheet.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { defineConfig } from &apos;vite&apos;;
import ViteSvgSpriteWrapper from &apos;vite-svg-sprite-wrapper&apos;;

export default defineConfig({
  plugins: [
    ViteSvgSpriteWrapper({
      icons: &apos;./src/icons/**/*.svg&apos;,
      outputDir: &apos;./public/&apos;,
    }),
  ],
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;icons&lt;/code&gt; property points to the directory containing your SVG icons. We can use the &lt;code&gt;**/*.svg&lt;/code&gt; syntax to recursively look for SVGs within the &lt;code&gt;src/icons/&lt;/code&gt; directory, if they happen to be nested into sub-directories.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;outputDir&lt;/code&gt;, we can send the generated sprite sheet to Vite&apos;s &lt;code&gt;public/&lt;/code&gt; directory. Anything within &lt;code&gt;public/&lt;/code&gt; is automatically copied, unprocessed, into the built &lt;code&gt;dist/&lt;/code&gt; folder, making the sprite sheet available to use within pages.&lt;/p&gt;
&lt;p&gt;Now, whenever we run &lt;code&gt;npm build&lt;/code&gt; to build the project, this plugin will do the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grab all of the icons out of &lt;code&gt;src/icons/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Combine and format the icons as &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; elements&lt;/li&gt;
&lt;li&gt;Output a &lt;code&gt;sprite.svg&lt;/code&gt; file to the &lt;code&gt;public/&lt;/code&gt; directory&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Adding new icons&lt;/h3&gt;
&lt;p&gt;Just drop them into the &lt;code&gt;src/icons/&lt;/code&gt; directory and re-run the build!&lt;/p&gt;
&lt;h2&gt;Using Sprite Sheets&lt;/h2&gt;
&lt;p&gt;Now that we have a sprite sheet, let&apos;s figure out how to actually &lt;em&gt;use&lt;/em&gt; it.&lt;/p&gt;
&lt;p&gt;I mentioned earlier that SVG has another feature called &lt;code&gt;&amp;lt;use&amp;gt;&lt;/code&gt; that allows you to reference the &lt;code&gt;id&lt;/code&gt; of a &lt;code&gt;&amp;lt;symbol&amp;gt;&lt;/code&gt; inside our &lt;code&gt;public/sprite.svg&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;If the sprite sheet is small enough, one thing you can do is embed it directly on the page, the you could do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;svg class=&quot;icon&quot; aria-hidden=&quot;true&quot;&amp;gt;
  &amp;lt;use xlink:href=&quot;#arrow&quot;&amp;gt;&amp;lt;/use&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which would copy the SVG symbol with the &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;arrow&lt;/code&gt; inline, wherever you are using the icon.&lt;/p&gt;
&lt;p&gt;This presents a problem though, anytime we update the sprite sheet, we would need to re-copy it&apos;s code into the HTML somewhere - not ideal.&lt;/p&gt;
&lt;p&gt;Instead, we can reference the path to the SVG &lt;em&gt;and&lt;/em&gt; the &lt;code&gt;id&lt;/code&gt; of the icon:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;svg class=&quot;icon&quot; aria-hidden=&quot;true&quot;&amp;gt;
  &amp;lt;use xlink:href=&quot;./sprite.svg#arrow&quot;&amp;gt;&amp;lt;/use&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Vite is smart enough to know where to find &quot;public&quot; files, so you do not need to include &lt;code&gt;public/&lt;/code&gt; within the path to the sprite sheet.&lt;/p&gt;
&lt;p&gt;Now you should see the corresponding icon in the browser!&lt;/p&gt;
&lt;h2&gt;CSS Approach&lt;/h2&gt;
&lt;p&gt;You can create a CSS powered sprite sheet as well!&lt;/p&gt;
&lt;h3&gt;Prepping the SVG&lt;/h3&gt;
&lt;p&gt;We have to massage the SVG a bit to make this effective.&lt;/p&gt;
&lt;p&gt;First, in your SVG tool of choice (I&apos;m using Figma) make sure each sprite is grouped appropriately with whatever name you&apos;d like to use as reference to the SVG. Stack each icon ontop of one another, Figma has an alignment tool to make this easy - but make sure all icons are centered! Group all the stacked icons together.&lt;/p&gt;
&lt;p&gt;Next we can export the sprites as a &lt;em&gt;single&lt;/em&gt; SVG file, however we will want our export tool to preserve the names as &lt;code&gt;id&lt;/code&gt; attributes within the SVG.&lt;/p&gt;
&lt;p&gt;We are looking for something similar to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;svg width=&quot;100&quot; height=&quot;100&quot; viewBox=&quot;0 0 100 100&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&amp;gt;
  &amp;lt;g id=&quot;heart&quot;&amp;gt;// ...&amp;lt;/g&amp;gt;
  &amp;lt;g id=&quot;star&quot;&amp;gt;// ...&amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice the &lt;code&gt;id=&quot;heart&quot;&lt;/code&gt; on the first &lt;code&gt;g&lt;/code&gt; tag? This will be how we can reference the sprite when requesting it as an asset later!&lt;/p&gt;
&lt;p&gt;Now we need to include a couple of things within this SVG file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;svg class=&quot;spritesheet&quot; width=&quot;100&quot; height=&quot;100&quot; viewBox=&quot;0 0 100 100&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;style&amp;gt;
      &amp;lt;![CDATA[
          .sprite { display: none; }
          .sprite:target { display: inline; }
        ]]&amp;gt;
    &amp;lt;/style&amp;gt;
  &amp;lt;/defs&amp;gt;

  //...
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;&amp;lt;defs&amp;gt;&lt;/code&gt; tag gives us a spot to where we can define a couple CSS styles for our new SVG sprite sheet to abide by.&lt;/p&gt;
&lt;p&gt;Let&apos;s take a peek at those rules:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.sprite {
  display: none;
}
.sprite:target {
  display: inline;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Very straightforward: don&apos;t display unless you are being targeted.&lt;/p&gt;
&lt;p&gt;Apply &lt;code&gt;class=&quot;sprite&quot;&lt;/code&gt; to each of the &lt;code&gt;&amp;lt;g&amp;gt;&lt;/code&gt; tags within your SVG file for the rules to take effect.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;svg class=&quot;spritesheet&quot; width=&quot;100&quot; height=&quot;100&quot; viewBox=&quot;0 0 100 100&quot; fill=&quot;none&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&amp;gt;
  &amp;lt;defs&amp;gt;
    &amp;lt;style&amp;gt;
      &amp;lt;![CDATA[
            .sprite { display: none; }
            .sprite:target { display: inline; }
          ]]&amp;gt;
    &amp;lt;/style&amp;gt;
  &amp;lt;/defs&amp;gt;

  &amp;lt;g class=&quot;sprite&quot; id=&quot;heart&quot;&amp;gt;// ...&amp;lt;/g&amp;gt;
  &amp;lt;g class=&quot;sprite&quot; id=&quot;star&quot;&amp;gt;// ...&amp;lt;/g&amp;gt;
&amp;lt;/svg&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Default Styles&lt;/h3&gt;
&lt;p&gt;If the spritesheet is being used as an icon set, you may want to define some default styles to accompany the icons. In your project&apos;s CSS, you can do something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;span[class*=&apos;icon&apos;] {
  display: inline-block;
  height: var(--icon-size, 100px);
  aspect-ratio: 1;
  background: transparent var(--icon-url, url(&apos;./sprite.svg&apos;));
  background-size: contain;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Using the SVGs&lt;/h3&gt;
&lt;p&gt;Now that we have our SVG sprite sheet setup and some default styles in place, we can use this sprite sheet in a few different ways:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- as an image tag --&amp;gt;
&amp;lt;img src=&quot;./sprite.svg#arrow&quot; /&amp;gt;

&amp;lt;!-- as an iframe --&amp;gt;
&amp;lt;iframe src=&quot;./sprite.svg#heart&quot;&amp;gt; &amp;lt;/iframe&amp;gt;

&amp;lt;!-- as an object --&amp;gt;
&amp;lt;object type=&quot;image/svg+xml&quot; data=&quot;/sprite.svg#heart&quot;&amp;gt;
  &amp;lt;!-- provide a fallback graphic --&amp;gt;
  &amp;lt;img src=&quot;./heart.png&quot; /&amp;gt;
&amp;lt;/object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, this SVG sprite sheet can be used in CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.icon-heart {
  background: url(&apos;./sprite.svg#heart&apos;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Demonstration&lt;/h3&gt;
&lt;p&gt;&amp;lt;p
class=&quot;codepen&quot;
data-height=&quot;600&quot;
data-theme-id=&quot;default&quot;
data-default-tab=&quot;result&quot;
data-slug-hash=&quot;VwOwgBV&quot;
data-user=&quot;mrtrimble&quot;
data-token=&quot;a1ea2c9ee5114cc2f3524419a0797505&quot;
style=&quot;height: 600px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;span&amp;gt;
See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/VwOwgBV/a1ea2c9ee5114cc2f3524419a0797505&quot;&amp;gt;Untitled&amp;lt;/a&amp;gt; by Ryan
Trimble (&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;script async src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
</content:encoded></item><item><title>Creating a Guestbook with Astro DB</title><link>https://ryantrimble.com/blog/creating-a-guestbook-with-astro-db/</link><guid isPermaLink="true">https://ryantrimble.com/blog/creating-a-guestbook-with-astro-db/</guid><description>Astro added a database and now I feel powerful.</description><pubDate>Sat, 16 Mar 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My &lt;a href=&quot;https://ryantrimble.com/blog/why-astro-is-my-favorite-framework/&quot;&gt;favorite framework&lt;/a&gt; and its amazing team of developers released a new feature this week that I am &lt;em&gt;very&lt;/em&gt; excited about: &lt;a href=&quot;https://astro.build/db&quot;&gt;Astro DB&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What is Astro DB?&lt;/h2&gt;
&lt;p&gt;As you may expect, the DB stands for database - however it&apos;s not just &lt;em&gt;any&lt;/em&gt; database.&lt;/p&gt;
&lt;p&gt;Astro DB was built on top of &lt;a href=&quot;https://turso.tech/libsql&quot;&gt;LibSQL&lt;/a&gt; to be integrated directly with Astro and I gotta say it works &lt;em&gt;very well&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The integration provides you with a few tools: a no-fuss local development database, an awesome API to work with said database, and a cloud database platform which can be wired up for your dynamic production content with Astro server-side rendering.&lt;/p&gt;
&lt;h2&gt;Creating a Guestbook&lt;/h2&gt;
&lt;p&gt;I just read the &lt;a href=&quot;https://manuelmoreale.com/pb-sara-joy&quot;&gt;29th edition of &lt;em&gt;People &amp;amp; Blogs&lt;/em&gt;&lt;/a&gt; which features &lt;a href=&quot;https://CS.Sjoy.lol&quot;&gt;webring&lt;/a&gt; and &lt;a href=&quot;https://sarajoy.dev/guestbook/&quot;&gt;guestbook&lt;/a&gt; aficionado, &lt;a href=&quot;https://sarajoy.dev/&quot;&gt;Sara Joy&lt;/a&gt;, which got me thinking about Guestbooks - an excellent project to test out Astro DB.&lt;/p&gt;
&lt;h3&gt;Setup Astro&lt;/h3&gt;
&lt;p&gt;Let&apos;s scaffold a new Astro project using &lt;code&gt;create-astro&lt;/code&gt;. The absolute best place to start an Astro project is the &lt;a href=&quot;https://docs.astro.build/en/getting-started/&quot;&gt;Astro docs&lt;/a&gt;, Astro&apos;s documentation team is great and I have never had issues finding what I need.&lt;/p&gt;
&lt;p&gt;In your terminal, navigate to where you&apos;d like to create your project and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm create astro@latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Follow the prompts, selecting which preferences are best for you - in my case, I created an empty Astro project, with &lt;code&gt;Strict&lt;/code&gt; TypeScript settings.&lt;/p&gt;
&lt;p&gt;Now, open up that directory in your editor of choice so we can dig into Astro DB!&lt;/p&gt;
&lt;h3&gt;Setup Astro DB&lt;/h3&gt;
&lt;p&gt;First things first, let&apos;s install the Astro DB integration:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx astro add db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will install the Astro DB package into your project and will ask if it is allowed to update your Astro config file, say yes.&lt;/p&gt;
&lt;p&gt;Astro DB also scaffolds out a &lt;code&gt;db/&lt;/code&gt; folder containing a &lt;code&gt;config.ts&lt;/code&gt; file for configuring your database, and a &lt;code&gt;seed.ts&lt;/code&gt; file for seeding the database for development.&lt;/p&gt;
&lt;p&gt;Open up the &lt;code&gt;db/config.ts&lt;/code&gt; file, it&apos;s empty at the moment, so let&apos;s add our table.&lt;/p&gt;
&lt;p&gt;To add a table, we will need to import the &lt;code&gt;defineTable&lt;/code&gt; function from &lt;code&gt;astro:db&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/config.ts
import { defineDb, defineTable } from &apos;astro:db&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also need to create a column on the table, so import &lt;code&gt;column&lt;/code&gt; as well:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/config.ts
import { defineDb, defineTable, column } from &apos;astro:db&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great! Now let&apos;s instantiate a table called &lt;code&gt;GuestBook&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/config.ts
import { defineDb, defineTable, column, NOW } from &apos;astro:db&apos;;

const GuestBook = defineTable({
  columns: {},
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our table schema is going to be simple on purpose, we are building a guestbook after all. We are looking to store:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt; - The guestbook entry&apos;s unique identifier&lt;/li&gt;
&lt;li&gt;&lt;code&gt;author&lt;/code&gt; - a &lt;code&gt;string&lt;/code&gt; containing who left the guestbook entry&lt;/li&gt;
&lt;li&gt;&lt;code&gt;content&lt;/code&gt; - another &lt;code&gt;string&lt;/code&gt; featuring the main content of the guestbook entry&lt;/li&gt;
&lt;li&gt;&lt;code&gt;timestamp&lt;/code&gt; - a timestamp to capture when the entry was added&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can configure this schema for our table column like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/config.ts
import { defineDb, defineTable, column, NOW } from &apos;astro:db&apos;;

const GuestBook = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    author: column.text(),
    content: column.text(),
    timestamp: column.date({ default: NOW }),
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can indicate the type of data for each column. For the &lt;code&gt;timestamp&lt;/code&gt; property, we can set the default value to the most current time using the &lt;code&gt;NOW&lt;/code&gt; function provided by Astro DB (don&apos;t forget to import it!).&lt;/p&gt;
&lt;p&gt;Checkout the Astro Docs&apos; &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/db/#table-configuration-reference&quot;&gt;Table Configuration Reference&lt;/a&gt; for more information on how to set up columns, advanced configuration, and types of columns available.&lt;/p&gt;
&lt;p&gt;Finally we will want to export the Guestbook table, we can do this using the &lt;code&gt;defineDb&lt;/code&gt; function provided by Astro DB:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/config.ts
import { defineDb, defineTable, column, NOW } from &apos;astro:db&apos;;

const GuestBook = defineTable({
  columns: {
    id: column.number({ primaryKey: true }),
    author: column.text(),
    content: column.text(),
    timestamp: column.date({ default: NOW }),
  },
});

// https://astro.build/db/config
export default defineDb({
  tables: { GuestBook },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is all the table we need for our simple guestbook, so let&apos;s talk about seeding the database.&lt;/p&gt;
&lt;h3&gt;Seed Database&lt;/h3&gt;
&lt;p&gt;To populate the database with some test data for development, open up the &lt;code&gt;db/seed.ts&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;To actually &lt;em&gt;use&lt;/em&gt; our &lt;code&gt;GuestBook&lt;/code&gt; table we created in our &lt;code&gt;db/config.ts&lt;/code&gt; file, we can simply import it from the database.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/seed.ts
import { db, GuestBook } from &apos;astro:db&apos;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, inside the &lt;code&gt;seed()&lt;/code&gt; function, we can insert data like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// db/seed.ts
import { db, GuestBook } from &apos;astro:db&apos;;

// https://astro.build/db/seed
export default async function seed() {
  await db.insert(GuestBook).values([
    {
      author: &apos;John Doe&apos;,
      content: &apos;You are so cool!&apos;,
    },
    {
      author: &apos;John Doe, The Second&apos;,
      content: &apos;I agree with my dad!&apos;,
    },
  ]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We only need to provide the &lt;code&gt;author&lt;/code&gt; and the &lt;code&gt;content&lt;/code&gt; as the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;timestamp&lt;/code&gt; will automatically be set based on the schema setup in the &lt;code&gt;db/config.ts&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Now we have our database configured and the seed file ready, let&apos;s fire up the Astro development server!&lt;/p&gt;
&lt;h3&gt;Render to the Browser&lt;/h3&gt;
&lt;p&gt;For the purposes of this demonstration, I&apos;m creating this guestbook on a single page.&lt;/p&gt;
&lt;p&gt;To output the guestbook data on the homepage, open up &lt;code&gt;src/pages/index.astro&lt;/code&gt; and import the &lt;code&gt;db&lt;/code&gt; and our &lt;code&gt;GuestBook&lt;/code&gt; table from Astro DB.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://orm.drizzle.team/&quot;&gt;DrizzleORM &lt;/a&gt; is built into Astro DB, so querying the database is super easy. Let&apos;s grab everything from the &lt;code&gt;GuestBook&lt;/code&gt; table and render it to the page:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

&amp;lt;dl&amp;gt;
{
  guestBook
    .sort((a, b) =&amp;gt; new Date(b.timestamp) - new Date(a.timestamp))
    .map(({author, content, timestamp}) =&amp;gt; (
    &amp;lt;div&amp;gt;
      &amp;lt;dt&amp;gt;{author}&amp;lt;/dt&amp;gt;
      &amp;lt;dd&amp;gt;{content}&amp;lt;/dd&amp;gt;
      &amp;lt;dd&amp;gt;{timestamp}&amp;lt;/dd&amp;gt;
    &amp;lt;/div&amp;gt;
  ))
}
&amp;lt;/dl&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will iterate over the &lt;code&gt;guestBook&lt;/code&gt; array, destructuring &lt;code&gt;author&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, and &lt;code&gt;timestamp&lt;/code&gt; for use within the template.&lt;/p&gt;
&lt;p&gt;Personally, I want the latest entry in the guestbook at the top of the page, which we can achieve by chaining a &lt;code&gt;sort()&lt;/code&gt; array method onto &lt;code&gt;guestBook&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  guestBook
    .sort((a, b) =&amp;gt; new Date(b.timestamp) - new Date(a.timestamp))
    .map(({ author, content, timestamp }) =&amp;gt; (
      &amp;lt;div&amp;gt;
        &amp;lt;dt&amp;gt;{author}&amp;lt;/dt&amp;gt;
        &amp;lt;dd&amp;gt;{content}&amp;lt;/dd&amp;gt;
        &amp;lt;dd&amp;gt;{timestamp}&amp;lt;/dd&amp;gt;
      &amp;lt;/div&amp;gt;
    ));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will output the stored data from the &lt;code&gt;GuestBook&lt;/code&gt; table onto the page!&lt;/p&gt;
&lt;p&gt;BUT WAIT! How do we &lt;em&gt;add&lt;/em&gt; things to the database? Well, like any good web application: &lt;strong&gt;Forms&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Creating a Form&lt;/h3&gt;
&lt;p&gt;If you have ever created an HTML form, you already know what to do, here is the form I created:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form method=&quot;POST&quot;&amp;gt;
  &amp;lt;label for=&quot;author&quot;&amp;gt;
    Author
    &amp;lt;input id=&quot;author&quot; name=&quot;author&quot; /&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;label for=&quot;content&quot;&amp;gt;
    Content
    &amp;lt;textarea id=&quot;content&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;button type=&quot;reset&quot;&amp;gt;Cancel&amp;lt;/button&amp;gt;
  &amp;lt;button type=&quot;submit&quot;&amp;gt;Leave your mark&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh no! The form is setup to post to itself, we need to handle that! Luckily Astro already knows what to do. We can check the page for &lt;code&gt;POST&lt;/code&gt; requests using an &lt;code&gt;if&lt;/code&gt; check on &lt;code&gt;Astro.request.method&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Watch for POST requests
if(Astro.request.method === &apos;POST&apos;) {

}

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we catch a &lt;code&gt;POST&lt;/code&gt; request, we will want to do a few things before adding the item to the database.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parse the &lt;code&gt;formData&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s grab the &lt;code&gt;author&lt;/code&gt; and &lt;code&gt;content&lt;/code&gt; submitted through the form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Watch for POST requests
if(Astro.request.method === &apos;POST&apos;) {

  // Parse form data
  let formData = await Astro.request.formData();
  let author = formData.get(&apos;author&apos;);
  let content = formData.get(&apos;content&apos;);
}

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Data Validation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prior to inserting the data to the database, it is generally a good idea to add some validation to make sure what is being submitted can be safely added. For the purposes of this simple demo, I&apos;m checking to ensure the data types are valid - be sure to apply proper validation to projects you create!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Watch for POST requests
if(Astro.request.method === &apos;POST&apos;) {

  // Parse form data
  let formData = await Astro.request.formData();
  let author = formData.get(&apos;author&apos;);
  let content = formData.get(&apos;content&apos;);

  // Validate that author and content are both of type &apos;string&apos;
  if (typeof author === &apos;string&apos; &amp;amp;&amp;amp; typeof content === &apos;string&apos;) {

    // Insert data into the database
    await db.insert(GuestBook).values({ author, content });
  }
}

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when submitting the guestbook form, new items will be added to the database! There is one bug though, if you try to refresh the page after submitting the form, it will cause a re-submit and duplicate the entry in the database. My friend &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; reminded me that you can utilize &lt;code&gt;Astro.redirect&lt;/code&gt; to move users to different pages in Astro, but in this case we just want it to redirect the page back to itself.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Watch for POST requests
if(Astro.request.method === &apos;POST&apos;) {

  // Parse form data
  let formData = await Astro.request.formData();
  let author = formData.get(&apos;author&apos;);
  let content = formData.get(&apos;content&apos;);

  // Validate that author and content are both of type &apos;string&apos;
  if (typeof author === &apos;string&apos; &amp;amp;&amp;amp; typeof content === &apos;string&apos;) {

    // Insert data into the database
    await db.insert(GuestBook).values({ author, content });

    return Astro.redirect(&apos;/&apos;);
  }
}

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Spam Filtering&lt;/h2&gt;
&lt;p&gt;I was discussing this project over on the &lt;a href=&quot;https://frontend.horse&quot;&gt;Frontend Horse&lt;/a&gt; Discord, where Sara Joy had the excellent suggestion of implementing spam filtering.&lt;/p&gt;
&lt;p&gt;She had already asked about implementing spam filtering on the Astro Discord, where they gave a great run-down of how to accomplish it:&lt;/p&gt;
&lt;p&gt;&amp;lt;blockquote class=&quot;flow&quot;&amp;gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have a &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt; on your page for submitting to the guestbook, including the honeypot input.&lt;/li&gt;
&lt;li&gt;Have a &lt;code&gt;POST&lt;/code&gt; endpoint handler in your Astro site that receives the form data.&lt;/li&gt;
&lt;li&gt;If the honeypot input has been filled, throw away that submission and return some error.&lt;/li&gt;
&lt;li&gt;If not, call the Akismet API to get another check on whether it&apos;s spam or not.&lt;/li&gt;
&lt;li&gt;If all is well, add the comment to the database and return a successful response.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;lt;cite&amp;gt;&amp;lt;strong&amp;gt;— Chris, from the Astro Discord&amp;lt;/strong&amp;gt;&amp;lt;/cite&amp;gt;
&amp;lt;/blockquote&amp;gt;&lt;/p&gt;
&lt;h3&gt;Honeypot&lt;/h3&gt;
&lt;p&gt;We already have our form on the page, so to include a honeypot field, we can inlude just a normal text input that is hidden.&lt;/p&gt;
&lt;p&gt;The idea is that bots and automated tools that may attempt to fill out the form will also fill out the hidden field. If the hidden field has been filled out, we can disregard the entire submission as it is &lt;em&gt;most likely&lt;/em&gt; a spam post.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;form method=&quot;POST&quot;&amp;gt;
  &amp;lt;label for=&quot;author&quot;&amp;gt;
    Author
    &amp;lt;input id=&quot;author&quot; name=&quot;author&quot; /&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;label for=&quot;special&quot;&amp;gt;
    &amp;lt;input id=&quot;special&quot; name=&quot;special&quot; /&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;label for=&quot;content&quot;&amp;gt;
    Content
    &amp;lt;textarea id=&quot;content&quot; name=&quot;content&quot;&amp;gt;&amp;lt;/textarea&amp;gt;
  &amp;lt;/label&amp;gt;

  &amp;lt;button type=&quot;reset&quot;&amp;gt;Cancel&amp;lt;/button&amp;gt;
  &amp;lt;button type=&quot;submit&quot;&amp;gt;Leave your mark&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I have included an input with the &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;special&lt;/code&gt;. This can essentially be any unique &lt;code&gt;id&lt;/code&gt; that you want it to be, we just need to know which field to look for when there has been a post submitted. I learned that using sort of obvious identifiers like the word &lt;code&gt;honeypot&lt;/code&gt; may not work on some spam bots, as they most likely account for that to be a thing.&lt;/p&gt;
&lt;p&gt;Inside our &lt;code&gt;POST&lt;/code&gt; request check, we can grab the value of the &lt;code&gt;special&lt;/code&gt; input and wrap our validation check within another &lt;code&gt;if&lt;/code&gt; check, this time making sure the &lt;code&gt;special&lt;/code&gt; input is of a &lt;code&gt;falsy&lt;/code&gt; value.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;

// Watch for POST requests
if(Astro.request.method === &apos;POST&apos;) {

  // Parse form data
  let formData = await Astro.request.formData();
  let author = formData.get(&apos;author&apos;);
  let content = formData.get(&apos;content&apos;);
  let special = formData.get(&apos;special&apos;);

  // if special is falsy, proceed to validation
  if(!special) {
    // Validate that author and content are both of type &apos;string&apos;
    if (typeof author === &apos;string&apos; &amp;amp;&amp;amp; typeof content === &apos;string&apos;) {

      // Insert data into the database
      await db.insert(GuestBook).values({ author, content });

      return Astro.redirect(&apos;/&apos;);
    }
  }
}

// Selects all items from the GuestBook table
const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Akismet API&lt;/h3&gt;
&lt;p&gt;Honeypot checks are a great first step to cutting down on the number of spam submissions you might receive, however there are always going to be some that slip through. A second line defense against spam is reaching out to a service to help determine if the submission is &lt;code&gt;ham&lt;/code&gt; or &lt;code&gt;spam&lt;/code&gt;, well at least that is how &lt;a href=&quot;https://akismet.com/&quot;&gt;Akismet&lt;/a&gt; defines it.&lt;/p&gt;
&lt;p&gt;Akismet is a spam filtering service that is used all over the web, particularly due to it&apos;s integration within the WordPress platform. They also provide a super generous free tier for their API! If you&apos;d like to use Akismet, you will need to create a free account and register your application to receive an API token.&lt;/p&gt;
&lt;p&gt;Once you have an API token, we can include it in the project as an environment variable. In the root of the project, create a &lt;code&gt;.env&lt;/code&gt; file with the following contents:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;AKISMET_TOKEN={YOUR_TOKEN_HERE}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copy your API token from Akismet and paste it directly after the &lt;code&gt;=&lt;/code&gt; sign. We&apos;ll use this in a moment, where we will read the environment variable within our Astro page using the method used by Vite, &lt;code&gt;import.meta.env&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There is a lovely node package useful to work with the Akismet API called &lt;code&gt;@cedx/akismet&lt;/code&gt;, which also has excellent &lt;a href=&quot;https://docs.belin.io/akismet.js/#/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With it, we can do a few things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Verify our Akismet API to make sure we are even permitted to check if a message is spam&lt;/li&gt;
&lt;li&gt;Pass our form data items to Akismet&lt;/li&gt;
&lt;li&gt;Determine whether the submission contains &lt;code&gt;ham&lt;/code&gt; or &lt;code&gt;spam&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Install the package by running the following in your terminal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install @cedx/akismet
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are several changes we are going to make to our &lt;code&gt;src/pages/index.astro&lt;/code&gt; file, so I&apos;ll show you up front what it looks like, then I will explain in more detail.&lt;/p&gt;
&lt;p&gt;Updated file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// src/pages/index.astro
---
import { db, GuestBook } from &apos;astro:db&apos;;
import { Blog, Client, Comment, Author, CheckResult } from &apos;@cedx/akismet&apos;;

// Watch for POST requests
if (Astro.request.method === &apos;POST&apos;) {
  // Setup Akismet client
  const blog = new Blog({ url: &apos;https://www.ryantrimble.com/&apos; });
  const client = new Client(import.meta.env.AKISMET_TOKEN, blog);

  // Parse form data
  let formData = await Astro.request.formData()
  let author = formData.get(&apos;author&apos;);
  let special = formData.get(&apos;special&apos;);
  let content = formData.get(&apos;content&apos;);

  // Will be used to validate the Akismet API key
  let isValid = false;

  if (!special) {
    // Check if Akismet API key is valid
    try {
      isValid = await client.verifyKey();
    } catch (error) {
      handleError(error);
    }

    if (isValid) {
      // Check if comment is spam or not
      if (typeof author === &apos;string&apos; &amp;amp;&amp;amp; typeof content === &apos;string&apos;) {
        try {
          let commentAuthor = new Author({
            name: author,
          });

          let comment = new Comment({
            author: commentAuthor,
            content,
          });

          const result = await client.checkComment(comment);

          if (result === CheckResult.ham) {
            // If comment is not spam, push the entry to the database.
            await db.insert(GuestBook).values({ author, content });

            // Finally redirect back to homepage!
            return Astro.redirect(&apos;/&apos;);
          } else {
            // Otherwise disregard comment.
            throw new Error(&apos;This comment has not been published.&apos;);
          }
        } catch (error) {
          if (typeof error === &apos;string&apos; || typeof error === &apos;object&apos;) {
            handleError(error);
          }
        }
      }
    }
  }
}

// @ts-ignore
function handleError(error) {
  if (typeof error === &apos;string&apos; || typeof error === &apos;object&apos;) {
    const message = error instanceof Error ? error.message : String(error);
    console.log(`An error occurred: ${message}`);
  }
}

const guestBook = await db.select().from(GuestBook);
---

// ...template
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are now importing a few useful tools from the &lt;code&gt;@cedx/akismet&lt;/code&gt; package:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Blog&lt;/code&gt; - This &lt;code&gt;class&lt;/code&gt; is what the &lt;code&gt;@cedx/akismet&lt;/code&gt; package uses to &lt;a href=&quot;https://docs.belin.io/akismet.js/api/classes/Blog.html&quot;&gt;represent the URL transmitted when making requests&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Client&lt;/code&gt; - Another useful &lt;code&gt;class&lt;/code&gt; &lt;a href=&quot;https://docs.belin.io/akismet.js/api/classes/Client.html&quot;&gt;used to submit items to the Akismet service&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Author&lt;/code&gt; - &lt;code&gt;class&lt;/code&gt; representing &lt;a href=&quot;https://docs.belin.io/akismet.js/api/classes/Author.html&quot;&gt;properties common to authors&lt;/a&gt;, such as names, email address, and &lt;a href=&quot;https://docs.belin.io/akismet.js/api/interfaces/AuthorOptions.html&quot;&gt;more&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Comment&lt;/code&gt; - Similar to &lt;code&gt;Author&lt;/code&gt;, the &lt;code&gt;Comment&lt;/code&gt; class represents properties common to comments such as authors, content, dates, and &lt;a href=&quot;https://docs.belin.io/akismet.js/api/interfaces/CommentOptions.html&quot;&gt;more&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CheckResult&lt;/code&gt; - Checks whether a comment is &lt;code&gt;ham&lt;/code&gt; or &lt;code&gt;spam&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We then instantiate new &lt;code&gt;Blog&lt;/code&gt; and &lt;code&gt;Client&lt;/code&gt; objects. Pass the same address you used to setup your Akisment API into the &lt;code&gt;Blog&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;Client&lt;/code&gt;, we need to pass in our Akismet API token, which is stored as a environment variable. We can use &lt;code&gt;import.meta.env&lt;/code&gt; to access the environment variables within Vite projects such as Astro.&lt;/p&gt;
&lt;p&gt;I added an &lt;code&gt;isValid&lt;/code&gt; variable which is utilized to validate the Akismet API token. We do this using the &lt;code&gt;client.verifyKeys()&lt;/code&gt; method. If we have a valid API token, we are free to move on to the next part.&lt;/p&gt;
&lt;p&gt;Next we create two objects for &lt;code&gt;Author&lt;/code&gt; and &lt;code&gt;Comment&lt;/code&gt;, including the properties we want to have checked by Akismet. To check the items with Akismet, we use the &lt;code&gt;client.checkComment()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;To recap, here are all the levels of protection we now have in place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Honeypot field to cut down on the number of spam submissions processed&lt;/li&gt;
&lt;li&gt;API token verification, ensures that the validation request is being sent by us.&lt;/li&gt;
&lt;li&gt;Akismet API spam checking to catch messages that may have gotten through Honeypot,&lt;/li&gt;
&lt;li&gt;JavaScript typechecks in place to make sure the content being posted is in the proper formats&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have a full implementation of this included in the &lt;a href=&quot;https://github.com/mrtrimble/astro-guestbook&quot;&gt;Github Repo&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;Deploying&lt;/h2&gt;
&lt;p&gt;There are few things necessary to deploy this application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Astro must be in server-side rendering mode to dynamically update the page. This can be enabled within the &lt;code&gt;astro.config.mjs&lt;/code&gt; file by adding &lt;code&gt;output: &apos;server&apos;&lt;/code&gt; to the configuration.&lt;/li&gt;
&lt;li&gt;Astro must utilize one of the hosting adapter integrations, I&apos;m using the &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/netlify/&quot;&gt;Netlify adapter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Push project up to Github.&lt;/li&gt;
&lt;li&gt;Set up your project within &lt;a href=&quot;https://studio.astro.build/&quot;&gt;Astro Studio&lt;/a&gt; with &lt;a href=&quot;https://docs.astro.build/en/guides/astro-db/#connect-to-astro-studio&quot;&gt;these instructions&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Connect your site to your hosting provider. Make sure to include your Astro Studio API token as an environment variable on your production builds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, once the site builds and deploys to the hosting provider of your choice, you should have a fully working Guestbook!&lt;/p&gt;
&lt;h2&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;The completed project is available to view at:
https://astro-guestbook.netlify.app/&lt;/p&gt;
&lt;p&gt;Feel free to check it out and leave a comment! You can find all the code here:
https://github.com/mrtrimble/astro-guestbook&lt;/p&gt;
&lt;p&gt;I&apos;m SUPER excited to see what the creative folks of the web dev community can come up with using Astro DB.&lt;/p&gt;
</content:encoded></item><item><title>Cool VSCode Plugins</title><link>https://ryantrimble.com/blog/cool-vs-code-plugins/</link><guid isPermaLink="true">https://ryantrimble.com/blog/cool-vs-code-plugins/</guid><description>Some neat plugins that I use so often I have forgotten they are plugins.</description><pubDate>Fri, 19 Jan 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Earlier today over on the Frontend Horse Discord, there was a super interesting discussion on how different folks take notes and what tools they use.&lt;/p&gt;
&lt;p&gt;Obsidian and VSCode were compared for their Markdown authoring abilities and the advantage seemed to be leaning towards Obsidian as it allows for things such as pasting URLs over selected text.&lt;/p&gt;
&lt;p&gt;I derailed this thoughtful, interesting discussion by being all &lt;em&gt;&quot;hurr durr my VSCode does that durr&quot;&lt;/em&gt; and sharing this video:&lt;/p&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;flow&quot;&amp;gt;
&amp;lt;video width=&quot;100%&quot; controls&amp;gt;
&amp;lt;source src=&quot;/videos/my-vscode-does-that.mov&quot; type=&quot;video/mp4&quot; /&amp;gt;
&amp;lt;/video&amp;gt;
&amp;lt;figcaption&amp;gt;
&amp;lt;p style=&quot;padding-inline: 1rem; font-size: var(--step--1);&quot;&amp;gt;
Screenrecording showing me highlight the word &quot;amazing&quot; inside of VSCode, then by pasting the Frontend Horse url,
it is converted into a Markdown link.
&amp;lt;/p&amp;gt;
&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;Of course I quickly realized that this is not because I&apos;m special, it is because of the other awesome developers helping to make great tools even greater: plugins.&lt;/p&gt;
&lt;h2&gt;Productivity&lt;/h2&gt;
&lt;h3&gt;Markdown All in One&lt;/h3&gt;
&lt;p&gt;This is the one that I was referring to in that intro and let me tell you, I&apos;ve had this plugin installed for so long that I actually forgot that it wasn&apos;t baked into VSCode.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one&quot;&gt;Markdown All in One&lt;/a&gt; by &lt;a href=&quot;https://github.com/yzhang-gh&quot;&gt;Yu Zhang&lt;/a&gt; handles basically everything you&apos;d expect to enhance your Markdown authoring needs.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Link pasting&lt;/li&gt;
&lt;li&gt;Table of Contents&lt;/li&gt;
&lt;li&gt;Table Formatting&lt;/li&gt;
&lt;li&gt;Autocomplete paths&lt;/li&gt;
&lt;li&gt;Enhanced keyboard shortcuts&lt;/li&gt;
&lt;li&gt;A bunch more things&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One caveat, as &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt; pointed out in our discussion - this does not &lt;em&gt;automatically&lt;/em&gt; handle &lt;code&gt;.mdx&lt;/code&gt; filetypes, however it can be added by associating the filetype to markdown files in VSCode settings.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Press &lt;code&gt;ctrl&lt;/code&gt; / &lt;code&gt;cmd&lt;/code&gt; + &lt;code&gt;,&lt;/code&gt; to open VSCode settings&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;files.associations&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Click Add Item and include &lt;code&gt;.mdx&lt;/code&gt; as &lt;code&gt;markdown&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you do any sort of editing of Markdown files, I totally recommend checking this out.&lt;/p&gt;
&lt;h3&gt;Better Comments&lt;/h3&gt;
&lt;p&gt;I like &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments&quot;&gt;Better Comments&lt;/a&gt; by &lt;a href=&quot;https://github.com/aaron-bond&quot;&gt;Aaron Bond&lt;/a&gt; as it helps me easily find places in a file that I may need to revisit, such as: todos, questionable code, or alerts about specific things.&lt;/p&gt;
&lt;p&gt;This works by just including certain annotations in your comment such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;// !&lt;/code&gt; Alerts&lt;/li&gt;
&lt;li&gt;&lt;code&gt;// ?&lt;/code&gt; Queries&lt;/li&gt;
&lt;li&gt;&lt;code&gt;// TODO:&lt;/code&gt; Todos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each end up highlighted differently from other comments.&lt;/p&gt;
&lt;p&gt;I like this too as it leads to a nice convention for writing comments, plus it makes searching projects for todo items easier.&lt;/p&gt;
&lt;h3&gt;Peacock&lt;/h3&gt;
&lt;p&gt;This is one that might take a little more effort to set up, and I expect few to give it the chance, but &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=johnpapa.vscode-peacock&quot;&gt;Peacock&lt;/a&gt; by &lt;a href=&quot;https://www.johnpapa.net/&quot;&gt;John Papa&lt;/a&gt; helps you change the color of VSCode &lt;em&gt;per workspace&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I don&apos;t know if you are all as weird as I am, but I like to make things different colors. It&apos;s like 90% of why I&apos;m a &lt;em&gt;web developer&lt;/em&gt; for Pete&apos;s sake!&lt;/p&gt;
&lt;p&gt;That being said, this is also super helpful if, also like me, you typically have many different projects open at a time. That can get confusing since all the windows look the same at quick glance. I usually set the color to a brand color or a darker type color from the projects theme, that way it helps clue me in on which project is which.&lt;/p&gt;
&lt;h3&gt;GitLens&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens&quot;&gt;GitLens&lt;/a&gt; by &lt;a href=&quot;https://gitkraken.com/&quot;&gt;GitKraken&lt;/a&gt; is awesome to me for one reason and one reason only: &lt;strong&gt;inline blame&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Don&apos;t get me wrong, I&apos;m not the type of person to go after someone over bad code (spoiler, it&apos;s me - I&apos;m the bad code), but it can be helpful while debugging to know when changes were made, directly in your editor.&lt;/p&gt;
&lt;p&gt;Now, does GitLens have other features: probably. I don&apos;t know and I don&apos;t care, this one thing is all I need it for.&lt;/p&gt;
&lt;h2&gt;Fun&lt;/h2&gt;
&lt;h3&gt;Stream Deck for VS Code&lt;/h3&gt;
&lt;p&gt;If you have a Stream Deck, you can make it do stuff in VSCode with &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=nicollasr.vscode-streamdeck&quot;&gt;Stream Deck for Visual Studio Code&lt;/a&gt; by &lt;a href=&quot;https://github.com/nicollasricas&quot;&gt;Nicollas R&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Basically it helps you by setting up Stream Deck buttons to run commands, shortcuts, and other things within VSCode.&lt;/p&gt;
&lt;p&gt;I wired it up with all the usual node project suspects: &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;npm start&lt;/code&gt;, &lt;code&gt;npm run dont-walk-to-our-summer-savings-sales-event&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;VSCode Pets&lt;/h3&gt;
&lt;p&gt;This is the best plugin on this list, &lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=tonybaloney.vscode-pets&quot;&gt;VSCode Pets&lt;/a&gt; by &lt;a href=&quot;https://github.com/tonybaloney&quot;&gt;Anthony Shaw&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You get cats, dogs, snakes, &lt;a href=&quot;https://en.wikipedia.org/wiki/Office_Assistant&quot;&gt;Clippy&lt;/a&gt; for some reason, birds, and a few other options for furry friends.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I set up VSCode Pets to represent my real pets, which are &lt;a href=&quot;/blog/the-animals-that-live-inside-my-house&quot;&gt;the animals who live inside my house&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Automatically import Components in Astro MDX</title><link>https://ryantrimble.com/blog/automatically-import-components-in-astro-mdx/</link><guid isPermaLink="true">https://ryantrimble.com/blog/automatically-import-components-in-astro-mdx/</guid><description>Re-upload of an article I originally published on RIMdev.io, discussing how to automatically import components into MDX files with Astro.</description><pubDate>Fri, 17 Nov 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of my (very few) complaints while working with Astro was that using components in MDX files tends to be a bit clunky, especially for those who may not be as familiar with how to import things. For example, we have some non-developers that make content updates to our static sites who are most likely unaware of this crucial step.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;We are converting sites from Hugo to Astro and in Hugo there is a concept of &quot;shortcodes&quot; used inside markdown to easily generate snippets of code. Hugo automatically knows about shortcodes, as long as they reside inside the &lt;code&gt;shortcodes/&lt;/code&gt; folder, in order to be used throughout a markdown file without having to do any imports.&lt;/p&gt;
&lt;p&gt;Astro doesn&apos;t have a &quot;shortcodes&quot; concept per se, but components are a pretty straightforward replacement. There are two main differences though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Regular markdown does not understand components, which leads us to utlize MDX instead.&lt;/li&gt;
&lt;li&gt;Components are not automatically imported into these MDX files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now importing components may not sound like the end-of-the-world, but might cause a lot of unneeded stress the first time someone unknowingly uses a component without importing it first.&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;Over on Mastodon, &lt;a href=&quot;https://front-end.social/@kizu&quot;&gt;Roma Komarov&lt;/a&gt; had the answer with a recent post called &lt;a href=&quot;https://blog.kizu.dev/astro-mdx-components/&quot;&gt;Astro MDX Components&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the post, Roma explains a very similar use-case for Astro components to our problem with shortcodes. Roma figured out that when rendering a dynamic &lt;code&gt;&amp;lt;Content /&amp;gt;&lt;/code&gt; component, you can actually provide it a &lt;code&gt;components&lt;/code&gt; prop in order to pass in whichever components you want to be automatically included in the MDX files.&lt;/p&gt;
&lt;p&gt;Definitely check out Roma&apos;s post for all the details!&lt;/p&gt;
&lt;h2&gt;Implementation&lt;/h2&gt;
&lt;p&gt;For my implementation of Roma&apos;s solution, I created a mixin file called &lt;code&gt;mixins/autoImportComponents.js&lt;/code&gt; which has the one job of returning all the components I&apos;ve created &quot;shortcodes&quot; for:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import DetailSummary from &apos;../shortcodes/DetailSummary.astro&apos;;
import MessageBlock from &apos;../shortcodes/MessageBlock.astro&apos;;

export const components = {
  DetailSummary,
  MessageBlock,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I chose to do this as a mixin file to quickly include these components in any layout files I might need.&lt;/p&gt;
&lt;p&gt;Within &lt;code&gt;[slug].astro&lt;/code&gt; (or whatever layout file needed) used for MDX content, I can now import the mixin file and pass these shortcode components into the dynamically created render component via the &lt;code&gt;components&lt;/code&gt; prop:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import {components} from &apos;../mixins/autoImportComponents&apos;;

const { Content } = await entry.render();
---

&amp;lt;Content components={components} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now anyone can freely use these shortcode components within MDX files without needing to import first!&lt;/p&gt;
</content:encoded></item><item><title>CSS-Only Scroll Animations</title><link>https://ryantrimble.com/blog/css-only-scroll-animations/</link><guid isPermaLink="true">https://ryantrimble.com/blog/css-only-scroll-animations/</guid><description>I&apos;m still digging into all the amazing things I learned at CSS Day!</description><pubDate>Fri, 07 Jul 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;During CSS Day, &lt;a href=&quot;https://www.bram.us/&quot;&gt;Bramus Van Damme&lt;/a&gt; did a fantastic two-subject talk on the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API&quot;&gt;View Transitions API&lt;/a&gt; and &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll-driven_animations&quot;&gt;Scroll-Driven Animations&lt;/a&gt;. I wrote an article for &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Stephanie Eckles&lt;/a&gt;&apos; &lt;em&gt;12 Days of Web&lt;/em&gt; on the &lt;a href=&quot;https://12daysofweb.dev/2022/view-transitions-api/&quot;&gt;View Transitions API&lt;/a&gt; over the holidays, and while a lot has changed with it since then, that will be a topic for another blog post. Instead, I want to talk about Scroll-Driven Animations today.&lt;/p&gt;
&lt;p&gt;Scroll-Driven Animations usually are something you would need to reach towards JavaScript for, either using something like the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;Intersection Observer API&lt;/a&gt; or a library such as &lt;a href=&quot;https://greensock.com/&quot;&gt;GreenSock Animation Platform&lt;/a&gt; to accomplish. However, a new feature is coming to the CSS specification, enabling scrolling as a timeline for CSS animations.&lt;/p&gt;
&lt;p&gt;As of the time of writing, CSS Scroll-Driven Animations is an experimental feature that is only available in Chrome 116+ (Use Chrome Canary to test things out!).&lt;/p&gt;
&lt;h2&gt;New Properties&lt;/h2&gt;
&lt;p&gt;A couple of new CSS properties control Scroll-Driven Animations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;animation-timeline&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;animation-range&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;animation-timeline&lt;/code&gt; is used to specify what type of Scroll-Driven timeline will be used, such as a &lt;em&gt;Scroll Progress Timeline&lt;/em&gt; or a &lt;em&gt;View Progress Timeline&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Scroll Progress Timelines&lt;/h3&gt;
&lt;p&gt;The most basic use-case for &lt;code&gt;animation-timeline&lt;/code&gt; is creating a &lt;strong&gt;Scroll Progress Timeline&lt;/strong&gt; with the &lt;code&gt;scroll()&lt;/code&gt; CSS function:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.animating-element {
  animation: fade-in ease;
  animation-timeline: scroll();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;scroll()&lt;/code&gt; function can also accept parameters for the scrolling element, or &lt;em&gt;scroller&lt;/em&gt;, and the axis in which the scrolling will occur.&lt;/p&gt;
&lt;p&gt;The scroller can be set as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nearest&lt;/code&gt; - closest ancestor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;root&lt;/code&gt; - the document root&lt;/li&gt;
&lt;li&gt;&lt;code&gt;self&lt;/code&gt; - the element itself&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Or can be uniquely named by setting the &lt;code&gt;scroll-timeline-name&lt;/code&gt; on the scrolling element.&lt;/p&gt;
&lt;p&gt;The axis parameter specifies whether the scrolling will occur on the &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt; axis, but can also be used with CSS logical properties such as &lt;code&gt;inline&lt;/code&gt; or &lt;code&gt;block&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.scroller {
  scroll-timeline-name: --scroller;
  scroll-timeline-axis: block;
}

.animating-element {
  animation: fade-in ease;
  animation-timeline: --scroller;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;View Progress Timelines&lt;/h3&gt;
&lt;p&gt;A much more fun alternative to the Scroll Progress Timeline is creating a &lt;strong&gt;View Progress Timeline&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;View Progress Timelines can start Scroll-Driven Animations when intersecting with certain parts of the scroller. You may think this is similar to Scroll-&lt;em&gt;Triggered&lt;/em&gt; animations, but that is not the case - the animations are still scrubbed through by scrolling.&lt;/p&gt;
&lt;p&gt;To create a View Progress Timeline, we can set the &lt;code&gt;view()&lt;/code&gt; CSS function for &lt;code&gt;animation-timeline&lt;/code&gt;. Similar to &lt;code&gt;scroll()&lt;/code&gt;, the &lt;code&gt;view()&lt;/code&gt; function can take in the axis of the scroller.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.animating-element {
  animation-timeline: view(block);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Where the magic happens is with another new CSS property, &lt;code&gt;animation-range&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;animation-range&lt;/code&gt; allows you to specify when the animation should start and stop based on when the element is intersecting different parts of the scroller.&lt;/p&gt;
&lt;p&gt;The different parts of the scroller are labeled as such:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;contain&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cover&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;entry-crossing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;entry&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exit-crossing&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exit&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You must specify what percentage of each part as to when the animation should start and stop. The syntax would look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.animating-element {
  animation: fade-in ease;
  animation-timeline: view(block);
  animation-range: contain 0 contain 100%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I would recommend creating CSS Custom Properties to make the start and end points a bit clearer, such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.animating-element {
  --range-start: contain 0;
  --range-end: contain 100%;

  animation: fade-in ease;
  animation-timeline: view(block);
  animation-range: var(--range-start) var(--range-end);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bramus has created &lt;a href=&quot;https://scroll-driven-animations.style/tools/view-timeline/ranges/#range-start-name=cover&amp;amp;range-start-percentage=0&amp;amp;range-end-name=cover&amp;amp;range-end-percentage=100&amp;amp;view-timeline-axis=block&amp;amp;view-timeline-inset=0&amp;amp;subject-size=smaller&amp;amp;subject-animation=reveal&amp;amp;interactivity=clicktodrag&amp;amp;show-areas=yes&amp;amp;show-fromto=yes&amp;amp;show-labels=yes&quot;&gt;an excellent tool&lt;/a&gt; to help understand this a bit better, I highly recommend checking it out.&lt;/p&gt;
&lt;h2&gt;Progressive Enhancement&lt;/h2&gt;
&lt;p&gt;The good news here is that CSS Scroll-Driven Animations are able to be implemented as a progressive enhancement for browsers that will support them.&lt;/p&gt;
&lt;p&gt;This can be done with the good old, trusty &lt;code&gt;@supports&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@supports (animation-timeline: scroll()) {
  .animating-element {
    animation: fade-in ease;
    animation-timeline: scroll();
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will check to see if the browser knows what &lt;code&gt;animation-timeline: scroll()&lt;/code&gt; is and if so, apply the Scroll-Driven Animation.&lt;/p&gt;
&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;Similar to progressive enhancement, Scroll-Driven Animations can also respect user&apos;s motion preferences by being wrapped inside a &lt;code&gt;prefers-reduced-motion&lt;/code&gt; media query:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .animating-element {
      animation: fade-in ease;
      animation-timeline: scroll();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I personally like to use &lt;code&gt;prefers-reduced-motion: no-preference&lt;/code&gt; as it is more akin to the user opting into animations, rather than the opposite.&lt;/p&gt;
&lt;h2&gt;Demonstration&lt;/h2&gt;
&lt;p&gt;For a more “real-life” example of Scroll-Driven Animations, check out this Codepen I have created:&lt;/p&gt;
&lt;p&gt;&amp;lt;video controls width=&quot;100%&quot; preload=&quot;none&quot; poster=&quot;/images/posts/scroll-driven-animation-poster.jpg&quot;&amp;gt;
&amp;lt;source src=&quot;/videos/scroll-driven-animation.webm&quot; type=&quot;video/webm&quot; /&amp;gt;
&amp;lt;/video&amp;gt;&lt;/p&gt;
&lt;p&gt;I recommend checking that out &lt;a href=&quot;https://codepen.io/mrtrimble/pen/YzRrzgM&quot;&gt;fullscreen on Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Wrap-up&lt;/h2&gt;
&lt;p&gt;It&apos;s absolutely amazing what CSS is capable of nowadays. It&apos;s also great that we are needing less-and-less JavaScript dependencies when it comes to building out things like this. I&apos;m super excited to see all the creative stuff that can be done with Scroll-Driven Animations.&lt;/p&gt;
&lt;p&gt;For further reading on Scroll-Driven Animations, please check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/articles/scroll-driven-animations/&quot;&gt;Chrome Developers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://scroll-driven-animations.style/&quot;&gt;Bramus Van Damme&apos;s demo site&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Introducing CSS Harrisburg</title><link>https://ryantrimble.com/blog/introducing-css-harrisburg/</link><guid isPermaLink="true">https://ryantrimble.com/blog/introducing-css-harrisburg/</guid><description>A new community for web developers in the central Pennsylvania area!</description><pubDate>Fri, 30 Jun 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the most interesting facts I learned from CSS Day in Amsterdam was that there are over fifty JavaScript-related conferences around the world and only one CSS-specific conference, CSS Day. This fact inspired me. I don&apos;t have the means to put on a whole conference on my own, but I figured there might be a small way to do my part.&lt;/p&gt;
&lt;p&gt;Introducing &lt;a href=&quot;https://cssharrisburg.com/&quot;&gt;CSS Harrisburg&lt;/a&gt; - a web developer community group for the central Pennsylvania region!&lt;/p&gt;
&lt;p&gt;Don&apos;t let the name fool you. Though I am definitely a Frontend Developer and CSS is one of my favorite things - we welcome anyone interested in web development to join!&lt;/p&gt;
&lt;h2&gt;The Plan&lt;/h2&gt;
&lt;p&gt;I&apos;m still in the process of working out a lot of the details, but I have a few things in mind for this community:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In-person meetups&lt;/li&gt;
&lt;li&gt;Newsletter&lt;/li&gt;
&lt;li&gt;Community discussion&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;In-person meetups&lt;/h3&gt;
&lt;p&gt;I&apos;ll be organizing in-person meetups on a regular schedule, expected every other month.&lt;/p&gt;
&lt;p&gt;My goal for the meetups is to be informative and fun at around an hour long. Meetups will be structured to have a presentation and time for networking.&lt;/p&gt;
&lt;p&gt;I have a venue in mind and am working towards scheduling the first event!&lt;/p&gt;
&lt;h3&gt;Newsletter&lt;/h3&gt;
&lt;p&gt;I&apos;m planning a weekly summary of interesting articles, fun Codepens, and inspiring websites.&lt;/p&gt;
&lt;p&gt;For the community, I want to be able to use this as a platform to share member success stories and their awesome projects.&lt;/p&gt;
&lt;p&gt;This will also be the place to receive community updates, such as when meetup events will occur.&lt;/p&gt;
&lt;h3&gt;Community discussion&lt;/h3&gt;
&lt;p&gt;To help community members keep in touch between meetups, I will be setting up either a community Slack or Discord.&lt;/p&gt;
&lt;p&gt;Depending on interest, we may use this as a platform to have community events online as well, such as online presentations, small workshops, or game nights!&lt;/p&gt;
&lt;h2&gt;How to join&lt;/h2&gt;
&lt;p&gt;I&apos;m looking for interest in this group at the moment, and the best way to show interest is by signing up for the newsletter on the &lt;a href=&quot;https://cssharrisburg.com/&quot;&gt;CSS Harrisburg website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you are interested in helping shape the group or would like to pitch a presentation, please reach out to me directly with the contact form here on my website!&lt;/p&gt;
&lt;h2&gt;Closing thoughts&lt;/h2&gt;
&lt;p&gt;I&apos;m stepping waaay outside my comfort zone as an introvert here, but I am very passionate about development and want a way to pass knowledge along and learn from others in the process.&lt;/p&gt;
</content:encoded></item><item><title>Mixing Colors with CSS</title><link>https://ryantrimble.com/blog/mixing-colors-with-css/</link><guid isPermaLink="true">https://ryantrimble.com/blog/mixing-colors-with-css/</guid><description>I&apos;ve been digging into many new CSS features since CSS Day, including mixing colors.</description><pubDate>Sun, 25 Jun 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;How cool is it that we can now take two colors and mix them together in CSS?&lt;/p&gt;
&lt;p&gt;If you aren&apos;t familiar with what I&apos;m referring to, I&apos;m talking about the new CSS &lt;code&gt;color-mix()&lt;/code&gt; function. It is surprisingly straightforward to use and can provide some great results.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;color-mix()&lt;/code&gt; Function&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;color-mix()&lt;/code&gt; function takes in a couple of parameters: the color space you want to use and the colors you want to mix.&lt;/p&gt;
&lt;p&gt;A very basic example looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.box {
  background: color-mix(in hsl, #ff0000, #0000ff);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will use the &lt;code&gt;hsl&lt;/code&gt; color space to mix red (&lt;code&gt;#FF0000&lt;/code&gt;) and blue (&lt;code&gt;#0000FF&lt;/code&gt;) to make a purple color.&lt;/p&gt;
&lt;p&gt;You can do more with it though! We can tell it how much of each color we want to mix in percentages:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.box {
  background: color-mix(in hsl, #ff0000 25%, #0000ff 50%);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;hsl&lt;/code&gt; color space even provides further control using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix#using_hue_interpolation_in_color-mix&quot;&gt;hue interpolation&lt;/a&gt; where we can adjust the hue to give different results:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.box1 {
  background: color-mix(in hsl shorter hue, #ff0000, #0000ff);
}

.box1 {
  background: color-mix(in hsl longer hue, #ff0000, #0000ff);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Color Spaces&lt;/h2&gt;
&lt;p&gt;I can&apos;t honestly say I understand color spaces, however, from what I understand, the CSS Color Module Level 4 has introduced several high-definition color spaces. The main thing to grok from this is that HD color spaces provide even more color options than non-HD color spaces.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.chrome.com/articles/high-definition-css-color-guide/&quot;&gt;Adam Argyle has a full write-up on color spaces&lt;/a&gt; if you want to understand the technical side of things a bit more.&lt;/p&gt;
&lt;p&gt;My point is, with &lt;code&gt;color-mix()&lt;/code&gt;, you aren&apos;t limited to using just the &lt;code&gt;hsl&lt;/code&gt; color space. You can use many of the supported color spaces in CSS (including the new CSS Color Level Module 4&apos;s HD color spaces), such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hsl&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hwb&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lab&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;oklab&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;oklch&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;srgb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Demonstration&lt;/h2&gt;
&lt;p&gt;Here is a small demo using &lt;code&gt;color-mix&lt;/code&gt; to provide various shades of a single color by mixing a brand color with the selected white and black colors:&lt;/p&gt;
&lt;p&gt;&amp;lt;p
class=&quot;codepen&quot;
data-height=&quot;650&quot;
data-theme-id=&quot;default&quot;
data-default-tab=&quot;result&quot;
data-slug-hash=&quot;wvQooqg&quot;
data-user=&quot;mrtrimble&quot;
style=&quot;height: 650px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;span&amp;gt;
See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/wvQooqg&quot;&amp;gt;CSS color-mix() Demo&amp;lt;/a&amp;gt; by Ryan Trimble (
&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;script async src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;p&gt;I added some JavaScript here as well to demonstrate how this is all handled in the browser. Simply changing the color of the &lt;code&gt;--_brand-color&lt;/code&gt; custom property affects the colors throughout the entire layout. Amazing!&lt;/p&gt;
&lt;h2&gt;Browser Support&lt;/h2&gt;
&lt;p&gt;The awesome news here is that &lt;code&gt;color-mix()&lt;/code&gt; and the new color spaces are &lt;a href=&quot;https://caniuse.com/?search=color-mix&quot;&gt;supported in all major browsers&lt;/a&gt;!&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;I feel like this is an awesome addition to CSS as a whole. Pairing CSS custom properties with the &lt;code&gt;color-mix&lt;/code&gt; function will be super helpful for customizing themes or applying different colors to states such as &lt;code&gt;:active&lt;/code&gt;, &lt;code&gt;:hover&lt;/code&gt;, and &lt;code&gt;:focus&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For more information on &lt;code&gt;color-mix()&lt;/code&gt; or CSS color spaces, check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix&quot;&gt;color-mix() on MDN&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/blog/css-color-mix/&quot;&gt;CSS color-mix()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://web.dev/color-spaces-and-functions/&quot;&gt;New CSS color spaces and functions in all major engines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3.org/TR/css-color-4/&quot;&gt;W3C CSS Color Module Level 4 Spec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Visiting Amsterdam for CSS Day</title><link>https://ryantrimble.com/blog/visiting-amsterdam-for-css-day/</link><guid isPermaLink="true">https://ryantrimble.com/blog/visiting-amsterdam-for-css-day/</guid><description>I traveled over 4,000 miles to attend the only CSS conference in the world.</description><pubDate>Fri, 16 Jun 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Judging from my &lt;a href=&quot;https://ryantrimble.com/blog/london-calling&quot;&gt;London Calling&lt;/a&gt; and &lt;a href=&quot;https://ryantrimble.com/blog/vue-conf-recap&quot;&gt;Vue Conf Recap&lt;/a&gt; posts from earlier this year, you might get the impression that I travel a lot. That is &lt;strong&gt;not&lt;/strong&gt; the case, just this year happens to be the year we (my wife and I) decided to branch out and explore the world. In fact, before this year, I had never even been on an airplane.&lt;/p&gt;
&lt;p&gt;This time we traveled to Amsterdam, The Netherlands, to attend &lt;a href=&quot;https://cssday.nl/2023&quot;&gt;CSS Day&lt;/a&gt; — which I found out is the only CSS-specific conference in the world now.&lt;/p&gt;
&lt;h2&gt;First night in Amsterdam&lt;/h2&gt;
&lt;p&gt;After a long, nine(-ish) hour total flight from Baltimore to Iceland, then Iceland to Amsterdam, we checked in at our hotel and took a power nap before going out to explore the city a bit.&lt;/p&gt;
&lt;p&gt;We originally had booked an upper-floor room as I was hoping to get a good view of the canals, however, the only room the hotel had available to check in early for was a basement-level room. I was disappointed for a moment until we saw the room and realized we were nearly level with the canal which still provided an incredible view.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;On the first night, we kept things fairly low-key by taking a walk down some streets and checking out some of the many canals. For dinner, we tried a local automat fast food chain called &lt;a href=&quot;https://www.febo.nl/&quot;&gt;FEBO&lt;/a&gt;. They have a wide variety of items to choose from at FEBO, all inside a vending machine-type wall. We tried fries, croquettes, and burgers all for a few euros each, all pretty good!&lt;/p&gt;
&lt;h2&gt;First day of CSS Day&lt;/h2&gt;
&lt;p&gt;The first day of CSS Day! The event was held in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Zuiderkerk&quot;&gt;Zuiderkerk&lt;/a&gt;, a 17th-century church that is now being used for events such as developer conferences. The Zuiderkerk was about a ten-minute walk from our hotel, which was perfect. We got there early and watched as folks began to arrive.&lt;/p&gt;
&lt;p&gt;For breakfast at the conference, we had coffee with croissants and jam. The conference recommended we keep to the “Pac-man” rule of always leaving space in groups for more people to join, which was a great way to meet new folks!&lt;/p&gt;
&lt;p&gt;I had the wonderful opportunity to meet my friend &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt; who makes &lt;a href=&quot;https://ryantrimble.com/blog/building-with-polypane/&quot;&gt;my favorite developer tool&lt;/a&gt;, &lt;a href=&quot;https://polypane.app/&quot;&gt;Polypane&lt;/a&gt;. I&apos;ve been chatting with Kilian for a while through the &lt;a href=&quot;https://frontend.horse/&quot;&gt;Frontend Horse&lt;/a&gt; community and it was so nice to meet him in person. A few other great folks I met included &lt;a href=&quot;https://front-end.social/@Jbasoo@mastodon.social&quot;&gt;James Basoo&lt;/a&gt; (who I connected with on Mastodon just before the conference) and had a lovely discussion with &lt;a href=&quot;https://front-end.social/@Liesbeth_Smit@mastodon.green&quot;&gt;Liesbeth Smit&lt;/a&gt; and &lt;a href=&quot;https://front-end.social/@paul@social.van.buu.re&quot;&gt;Paul Van Buuren&lt;/a&gt; in which we talked about our embarrassing old screen names and websites.&lt;/p&gt;
&lt;p&gt;Day one of CSS Day had &lt;a href=&quot;https://nerdy.dev/&quot;&gt;Adam Argyle&lt;/a&gt; as the Master of Ceremonies. Setting &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; his use of corny developer puns, Adam has a great personality for this type of thing and kept things exciting.&lt;/p&gt;
&lt;h3&gt;Una Kravets&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://una.im/&quot;&gt;Una Kravets&lt;/a&gt; kicked off talks with her presentation on &lt;em&gt;The State of the CSS Community&lt;/em&gt;. This was super exciting to see all the new features of CSS shipping from browser vendors, as well as many new features proposed by the &lt;a href=&quot;https://open-ui.org/&quot;&gt;Open UI group&lt;/a&gt; being considered.&lt;/p&gt;
&lt;p&gt;Una is right, this is a much different time for CSS, I still remember when new CSS and browser features took forever to get implemented. It&apos;s a CSS Revolution!&lt;/p&gt;
&lt;h3&gt;Hidde de Vries&lt;/h3&gt;
&lt;p&gt;Next up was &lt;a href=&quot;https://hidde.blog/&quot;&gt;Hidde de Vries&lt;/a&gt;, who talked about a topic I recently researched quite a bit for my post &lt;a href=&quot;https://ryantrimble.com/blog/the-popover-api-is-exciting-sort-of/&quot;&gt;The Popover API is Exciting, sort of&lt;/a&gt; - the Popover API.&lt;/p&gt;
&lt;p&gt;Hidde walked through how the Popover API works as well as provided some excellent examples as to when to use Popovers and when to use &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements.&lt;/p&gt;
&lt;p&gt;One of the things I was concerned about in my post was browser support for the Popover API and luckily it seems that this feature will be &lt;a href=&quot;https://ryantrimble.com/blog/the-popover-api-is-exciting-sort-of/&quot;&gt;shipping in Safari 17&lt;/a&gt; later this year, which is a great sign for adoption.&lt;/p&gt;
&lt;h3&gt;Léonie Watson&lt;/h3&gt;
&lt;p&gt;When I looked through the line-up of speakers and topics, one that piqued my interest was from &lt;a href=&quot;https://tink.uk/&quot;&gt;Léonie Watson&lt;/a&gt; on &lt;a href=&quot;https://www.w3.org/TR/css-speech-1/&quot;&gt;CSS Speech&lt;/a&gt;, mainly because I had never heard of it. Well, it turns out that is because it doesn&apos;t quite exist yet. During breakfast, I was chatting with &lt;a href=&quot;https://adactio.com/&quot;&gt;Jeremy Keith&lt;/a&gt; who said Léonie&apos;s talk is a rallying cry to gather support for this concept.&lt;/p&gt;
&lt;p&gt;Léonie described how with voice assistants, such as Siri or Alexa, there are ways to manipulate the voice to give it more character using something called &lt;a href=&quot;https://www.w3.org/TR/speech-synthesis11/&quot;&gt;SSML&lt;/a&gt;. With SSML, you can do things such as adjust the voice as if it were a font, change the pitch of the voice, as well as adjust the rate of speed at which the voice is read. Essentially Léonie is asking: why isn&apos;t this a thing in CSS?&lt;/p&gt;
&lt;p&gt;Well it turns out, this &lt;strong&gt;was&lt;/strong&gt; in the CSS spec at one point, but was dropped for seemingly unknown reasons.&lt;/p&gt;
&lt;p&gt;The main benefit to this would be for assistive technologies such as screen readers, where designers and developers would have the opportunity to provide better experiences for those listening to their content.&lt;/p&gt;
&lt;p&gt;This was such an interesting concept and now I&apos;m on board for this to be implemented.&lt;/p&gt;
&lt;h3&gt;Sanne &apos;t Hooft&lt;/h3&gt;
&lt;p&gt;Sanne ‘t Hooft&apos;s &lt;em&gt;Tinkering at Night&lt;/em&gt; talk turned out to be another topic I am not familiar with but was super interesting to see what is capable nowadays with CSS. Sanne demonstrated the superpowers of the &lt;a href=&quot;https://web.dev/css-trig-functions/&quot;&gt;CSS trigonometric functions&lt;/a&gt; to create stunning animations and potential UI implementations.&lt;/p&gt;
&lt;p&gt;As someone who doesn&apos;t math very well, this admittedly went a bit over my head, however, I was still able to appreciate these new capabilities of CSS. I was never great at math in school, but it is something I have gotten better at understanding while learning more practical applications for math in programming, this talk inspired me to add these trigonometry features to my list of things to try out.&lt;/p&gt;
&lt;h3&gt;Patrick Brosset&lt;/h3&gt;
&lt;p&gt;CSS selector performance is something I don&apos;t think about too much and luckily &lt;a href=&quot;https://patrickbrosset.com/&quot;&gt;Patrick Brosset&lt;/a&gt; shared that, in most cases, this is fine. However, when it does become an issue, it is good to know how to troubleshoot potential problems.&lt;/p&gt;
&lt;p&gt;Patrick gave several great tips on how to utilize the browser developer tools to track down problems, as well as potential examples of when these issues might occur.&lt;/p&gt;
&lt;h3&gt;Heydon Pickering&lt;/h3&gt;
&lt;p&gt;If you are familiar with &lt;a href=&quot;https://heydonworks.com/&quot;&gt;Heydon Pickering&lt;/a&gt; and his &lt;a href=&quot;https://briefs.video/&quot;&gt;Webbed Briefs&lt;/a&gt; videos, this talk was very much in the same vein — which is a great thing!&lt;/p&gt;
&lt;p&gt;Heydon spoke about scoping in CSS and how everything in CSS is some form of scoping. They discussed how JavaScript frameworks approach scoping and talked about the &lt;code&gt;@scope&lt;/code&gt; feature that will eventually be making its way to browsers.&lt;/p&gt;
&lt;p&gt;Hilarious and informative, and absolutely one of my favorite talks from the conference!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Sophie Koonin&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://localghost.dev/&quot;&gt;Sophie Koonin&apos;s&lt;/a&gt; talk was a walk down memory lane for me as she described a very familiar start to her web developer journey by building websites on Geocities, learning HTML and styling in places like Neopets and MySpace.&lt;/p&gt;
&lt;p&gt;Nowadays the web is, in general, a capitalist hellscape that lacks a certain charm that personal websites promoted back in the day.&lt;/p&gt;
&lt;p&gt;Sophie is encouraging people to get weird with the web again and build more personal websites, experiment with things and see what can be done to make the web fun. This is especially true now where maybe getting off of social media networks and owning your data is becoming more important.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Final Day of CSS Day&lt;/h2&gt;
&lt;p&gt;The second and final day of CSS coincided with my birthday, which being at CSS Day was one of the best ways to celebrate. The conference continued being amazing with more amazing talks and meeting amazing folks.&lt;/p&gt;
&lt;p&gt;One of those folks is another friend from the Frontend Horse community, &lt;a href=&quot;https://helloyes.dev/&quot;&gt;Thomas Michael Semmler&lt;/a&gt;. Thomas was such a pleasure to meet and it felt like catching up with an old friend even though we had never met in person.&lt;/p&gt;
&lt;p&gt;The Master of Ceremonies for the final day was Michelle Barker, who runs the &lt;a href=&quot;https://css-irl.info/&quot;&gt;CSS {In Real Life}&lt;/a&gt; blog. Michelle did a wonderful job announcing speakers and providing thoughtful input and questions in the after-talk question-and-answer sessions.&lt;/p&gt;
&lt;h3&gt;Miriam Suzanne&lt;/h3&gt;
&lt;p&gt;Container Queries are something that took some time for me to wrap my head around. Initially, I was confused as to what they did differently compared to Media Queries. I did manage to figure that out on my own, however, &lt;a href=&quot;https://www.miriamsuzanne.com/&quot;&gt;Miriam Suzanne&apos;s&lt;/a&gt; talk on the topic further cemented to me that Container Queries have a lot more potential.&lt;/p&gt;
&lt;p&gt;Miriam demonstrated the powers of containers and introduced me to container-style queries, which I have been playing with since getting back home. I can see myself re-watching this talk several times.&lt;/p&gt;
&lt;p&gt;Also, after the talk, I asked Miriam if the premise of the talk “CSS Containers, What Do They Know?” was a reference to &lt;a href=&quot;https://www.youtube.com/watch?v=i1eJMig5Ik4&quot;&gt;Bojack Horseman&lt;/a&gt; (&lt;a href=&quot;https://ryantrimble.com/blog/i-love-cartoons/&quot;&gt;one of my all-time favorite shows&lt;/a&gt;) and I can confirm that it was.&lt;/p&gt;
&lt;h3&gt;Umar Hansa&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://umaar.com/&quot;&gt;Umar Hansa&lt;/a&gt; presented on using modern tooling to help create and debug CSS. In his talk, Umar showed off many tips on using VS Code to its fullest, including using code snippets, shortcuts, and extensions. Umar also discussed other tools, such as artificial intelligence, to assist in writing code.&lt;/p&gt;
&lt;p&gt;This is another talk I want to review as there were many great tips throughout the presentation and had my head spinning with possibilities.&lt;/p&gt;
&lt;h3&gt;Stephanie Eckles&lt;/h3&gt;
&lt;p&gt;One of the main reasons I wanted to attend this conference was for &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Stephanie Eckles&lt;/a&gt; as I think she has made the biggest impact on how I write CSS nowadays. I know Stephanie from the Frontend Horse community and was luckily able to attend her Modern CSS Workshop last fall through work.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Stephanie is brilliant with CSS and has so much knowledge on the topic that it seemed difficult for her to contain it in just an hour-long talk.&lt;/p&gt;
&lt;p&gt;It was great getting to meet with her in person as well and hanging out under the stairs with her and Thomas is one of my favorite memories from the conference.&lt;/p&gt;
&lt;h3&gt;Jhey Tompkins&lt;/h3&gt;
&lt;p&gt;I have been following &lt;a href=&quot;https://jhey.dev/&quot;&gt;Jhey Tompkins&apos;&lt;/a&gt; work on Codepen for a long time and his creative use of the medium absolutely carried over to live events.&lt;/p&gt;
&lt;p&gt;Jhey demonstrated several ways to take something plain and turn it into a fun and memorable experience. The talk itself, for example, had a web page folks could visit and toss emojis onscreen with booming sound effects.&lt;/p&gt;
&lt;h3&gt;Cassondra Roberts&lt;/h3&gt;
&lt;p&gt;This is one of the talks that seemed to stick with me more than I initially expected it to. Cassondra Roberts detailed using CSS within JavaScript Web Components and the differences between the light DOM and the shadow DOM.&lt;/p&gt;
&lt;p&gt;I have been digging into native web components since this talk, trying to piece together the things Cassondra taught me and mixing them with other things from the conference as well and it&apos;s been super fun!&lt;/p&gt;
&lt;h3&gt;Bramus Van Damme&lt;/h3&gt;
&lt;p&gt;Originally this slot was for &lt;a href=&quot;https://jakearchibald.com/&quot;&gt;Jake Archibald&lt;/a&gt; to talk about the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API&quot;&gt;View Transitions API&lt;/a&gt;, which he helped pioneer. Since Jake left Google, &lt;a href=&quot;https://www.bram.us/about/&quot;&gt;Bramus Van Damme&lt;/a&gt; decided to fill in and give an excellent two-for-one talk on View Transitions as well as Scroll Driven Animations.&lt;/p&gt;
&lt;p&gt;Over the holidays, I wrote an article for Stephanie Eckles&apos; &lt;a href=&quot;https://12daysofweb.dev/2022/view-transitions-api/&quot;&gt;12 Days of Web project&lt;/a&gt; on the View Transitions API, so I had a familiarity with the topic and it was interesting to see how much has changed since then. Bramus demonstrated several great examples of how the View Transitions API can work with single-page applications and introduced a method for using them in multi-page applications (also known as websites).&lt;/p&gt;
&lt;p&gt;Scroll Driven Animations are another exciting new feature that I&apos;m excited to play around with. Looking at Bramus&apos; &lt;a href=&quot;https://scroll-driven-animations.style/&quot;&gt;demo site&lt;/a&gt; for the feature, there appears to be a lot more potential here than I originally thought. Bramus also showed possible ways to combine Scroll Driven Animations with other features to perform Scroll &lt;strong&gt;Triggered&lt;/strong&gt; Animations. It will be interesting to see how this gets finalized in Chrome and when other browser vendors adopt it.&lt;/p&gt;
&lt;p&gt;I also got the chance to talk shop with Bramus a bit on the first day and it was great meeting him!&lt;/p&gt;
&lt;h3&gt;Manuel Matuzović&lt;/h3&gt;
&lt;p&gt;For the final talk at CSS Day, &lt;a href=&quot;https://www.matuzo.at/&quot;&gt;Manuel Matuzović&lt;/a&gt; walked us through his evolution of writing CSS over the years. Manuel made it his mission to keep up-to-date with the latest modern CSS with a project where he focused on a different topic each day for (over) 100 days called:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;#100DaysOfMoreOrLessModernCSS&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Manuel&apos;s process felt very similar to how I&apos;ve approached learning new CSS concepts, typically focusing on one thing until I understand it. I enjoyed Manuel&apos;s talk. He showed several modern techniques that I had not seen before, such as using container-style queries similar to how Sass mixins work.&lt;/p&gt;
&lt;h2&gt;Saturday in the City&lt;/h2&gt;
&lt;p&gt;While in Amsterdam, there were several things I wanted to check out, but had little time to see everything. Sights such as the Van Gogh Museum and the Anne Frank House were booked out a month in advance, so, unfortunately, did not get to see these. Even still, we did manage to pack a lot of sights in on the Saturday after the conference.&lt;/p&gt;
&lt;h3&gt;Rijksmuseum&lt;/h3&gt;
&lt;p&gt;The Rijksmuseum is certainly a must-see if you are visiting Amsterdam. I never feel super excited about visiting museums for some reason, but I always lose my mind while I&apos;m there.&lt;/p&gt;
&lt;p&gt;Primarily the Rijksmuseum is an art museum of many of the dutch-masters such as Rembrandt and Vermeer.&lt;/p&gt;
&lt;p&gt;Seeing Rembrandt&apos;s work in person, such as The Night Watch, was incredible.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;KattenKabinet&lt;/h3&gt;
&lt;p&gt;The KattenKabinet (or Cat Cabinet) is a museum for all things cats. Many movie posters, advertisements, sculptures and paintings all depicting cat imagery are found all over the halls. They even had a quite serene garden outback containing even more cat-themed pieces.&lt;/p&gt;
&lt;p&gt;One of the best and probably most obvious parts of the cat museum is that live cats are roaming around. This was certainly a highlight of the trip for my wife.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Vondelpark&lt;/h3&gt;
&lt;p&gt;On our way to find our dinner spot, we strolled through Vondelpark which is one of the largest parks in the city.&lt;/p&gt;
&lt;p&gt;As the weather was great (basically every day while we were there) there were tons of people out. It was a lovely change of pace from walking through the city streets.&lt;/p&gt;
&lt;h3&gt;FoodHallen&lt;/h3&gt;
&lt;p&gt;For dinner, we went to FoodHallen which I can only describe as a shopping mall food court cranked up to 11. There are several restaurants inside with many different cuisines and was very crowded.&lt;/p&gt;
&lt;p&gt;We had the Dutch specialty Bitterballen, of course!&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;This trip was incredible for me!&lt;/p&gt;
&lt;p&gt;Amsterdam is a wonderful city, much greener than many cities here in the US. The many flowers and trees all along the canals were quite beautiful.&lt;/p&gt;
&lt;p&gt;Getting to attend a conference on a topic that I&apos;m quite passionate about and meeting wonderful folks that share that same passion was wonderful.&lt;/p&gt;
&lt;p&gt;I honestly never thought I would get to meet some of the folks I have become friends with over the past couple of years in person, but I was overjoyed at the opportunity.&lt;/p&gt;
&lt;p&gt;I learned so much and have already begun digging into some of the topics further to get a better understanding, expect more blog posts on some of the things I&apos;m learning about.&lt;/p&gt;
&lt;p&gt;Thank you to &lt;a href=&quot;https://front-end.social/@ppk&quot;&gt;PPK&lt;/a&gt;, &lt;a href=&quot;https://front-end.social/@KrijnHoetmer@mastodon.social&quot;&gt;Krijn Hoetmer&lt;/a&gt;, and everyone else who helped make CSS Day an amazing experience!&lt;/p&gt;
&lt;p&gt;I think I am going to try and make this event a yearly occurrence!&lt;/p&gt;
</content:encoded></item><item><title>Vue Conf Recap</title><link>https://ryantrimble.com/blog/vue-conf-recap/</link><guid isPermaLink="true">https://ryantrimble.com/blog/vue-conf-recap/</guid><description>Recapping Vue Conf 2023 in New Orleans, LA.</description><pubDate>Mon, 29 May 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had never been to New Orleans, a developer conference, or eaten gumbo, so there were a lot of firsts for me on this trip.&lt;/p&gt;
&lt;p&gt;We had six members of our development team attending the conference, including our documentation specialist (and my wife!).&lt;/p&gt;
&lt;h2&gt;New Orleans&lt;/h2&gt;
&lt;p&gt;When you think about New Orleans, you probably think about parties, great food, and music and the city certainly delivered. I&apos;m keen on two of those three things, but the trip was an overall success.&lt;/p&gt;
&lt;h3&gt;Ace Hotel&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://acehotel.com/new-orleans/&quot;&gt;Ace Hotel&lt;/a&gt; had a great vibe to it. The lounge was cool with lots of great furniture pieces, a bar, plants and a piano scribbled with signatures. There was an old-timey photo booth outside the elevators on the first floor, modernized and fashioned with a credit card reader to encourage usage.&lt;/p&gt;
&lt;p&gt;I particularly enjoyed the signage throughout the hotel, often painted directly onto the walls, pointing out key features, directions, and the many restaurants available.&lt;/p&gt;
&lt;p&gt;The vibe continued when we entered our hotel room - dimly lit with classic New Orleans Jazz already playing on the radio.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We unpacked our belongings, took a quick nap, and prepared for dinner with the team!&lt;/p&gt;
&lt;h3&gt;Cochon&lt;/h3&gt;
&lt;p&gt;A fan-favorite restaurant on our dev team from the previous Vue Conf held in New Orleans is &lt;a href=&quot;https://cochonrestaurant.com/&quot;&gt;Cochon Restaurant&lt;/a&gt;. This was before my time with the team, so I was not quite sure what to expect when I got there, especially since I had no idea what some of the dishes were when looking at their menu online (I&apos;m quite unsophisticated when it comes to food).&lt;/p&gt;
&lt;p&gt;That being said, they did have a chicken and andouille sausage gumbo that was &lt;em&gt;incredible&lt;/em&gt;, especially paired with their macaroni and cheese casserole. Others on our team enjoyed the rabbit and dumplings, fried alligator, and smoked beef short ribs.&lt;/p&gt;
&lt;p&gt;For dessert, I had a banana-spiced cake that contained milk jam, banana cream, and caramelized banana on top. I feel like I will be dreaming of this dessert for a while.&lt;/p&gt;
&lt;h2&gt;Vue Conf&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://us.vuejs.org/&quot;&gt;Vue Conf&lt;/a&gt; was held inside the Ace Hotel, so we didn&apos;t have to go too far to attend.&lt;/p&gt;
&lt;p&gt;The conference was three days in total, one day for workshops and two for talks. They provided breakfast and lunch, with coffee and snacks available throughout the day.&lt;/p&gt;
&lt;p&gt;One of the absolute best things about the conference was that they hired &lt;a href=&quot;https://twitter.com/KennethLafrance&quot;&gt;Ken LaFrance&lt;/a&gt; to be the master of ceremonies. Ken kept things so entertaining by mixing humor with interesting facts about New Orleans, excellent crowd interactions, and playful introductions to speakers. I wish Ken hosted every event!&lt;/p&gt;
&lt;h3&gt;Workshops&lt;/h3&gt;
&lt;p&gt;I participated in &lt;a href=&quot;https://us.vuejs.org/#workshops&quot;&gt;Nailing it with Nuxt 3 - Inside and Out&lt;/a&gt; workshop hosted by &lt;a href=&quot;https://roe.dev/&quot;&gt;Daniel Roe&lt;/a&gt;. Daniel leads the Nuxt core team, so, as expected, was super knowledgeable on the topic.&lt;/p&gt;
&lt;p&gt;I did make the mistake of entering the workshop a tad later than others, regrettably sitting in the last row. My eyesight is pretty awful.&lt;/p&gt;
&lt;p&gt;In the workshop, Daniel walked us through many of the key features of Nuxt that separate it from similar tools, such as modules, auto-importing components, layers, directory-based routing and tons more. One of the more interesting pieces he dived deep into was the Nitro server engine, which I feel will be very interesting to dig into on my own.&lt;/p&gt;
&lt;p&gt;As a more hands-on example, we got some time to play with Nuxt by building a To-Do list application. I managed to get mine to add and delete to-do items, so I consider that a success.&lt;/p&gt;
&lt;p&gt;I&apos;m very glad I did some &lt;a href=&quot;https://ryantrimble.com/blog/preparing-for-vue-conf-with-nuxt/&quot;&gt;preparation work&lt;/a&gt; before the conference by building an application with Nuxt, as this helped me follow along quite well (even though I could barely read the screen).&lt;/p&gt;
&lt;p&gt;All-in-all, I&apos;m looking forward to using Nuxt more often in projects I build. I&apos;m hoping we can find a way to utilize it in our workflow at work.&lt;/p&gt;
&lt;h3&gt;Presentations&lt;/h3&gt;
&lt;p&gt;The first day of talks began with &lt;a href=&quot;https://twitter.com/youyuxi&quot;&gt;Evan You&lt;/a&gt; presenting the keynote &quot;State of the Vuenion.&quot;&lt;/p&gt;
&lt;p&gt;This, of course, provides a lot of detail on the most recent version releases of Vue, including the latest &lt;a href=&quot;https://blog.vuejs.org/posts/vue-3-3&quot;&gt;Vue 3.3&lt;/a&gt;. This release contains a &lt;code&gt;defineModel&lt;/code&gt; feature that will help with creating components that utilize two-way binding.&lt;/p&gt;
&lt;p&gt;Evan also talked about the future of Vue involving &quot;Vapor Mode&quot; which he claims will make Vue more performant and use less memory. This an exciting development that I&apos;m looking forward to being released.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.rti.org/expert/alex-harding&quot;&gt;Alex Harding&lt;/a&gt; from RTI International discussed how helpful it is to understand the data when creating interactive and story-driven visualizations. I reflected on this from the point of view of a user experience developer and how it is helpful to understand the needs of a user to deliver the best possible experience.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/danielkelly_io&quot;&gt;Daniel Kelly&lt;/a&gt; from &lt;a href=&quot;https://vueschool.io/&quot;&gt;Vue School&lt;/a&gt; gave an awesome talk on common patterns that will help large-scale applications. A lot of common-sense advice that I&apos;m hoping to bring to my workflow when developing Vue applications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nuxtlabs.com/&quot;&gt;NuxtLabs&lt;/a&gt; CEO, &lt;a href=&quot;https://twitter.com/Atinux&quot;&gt;Sébastien Chopin&lt;/a&gt;, presented a live coding demonstration of building an application with Nuxt. He utilized many of the features of Nuxt to build a simple &quot;Coffee or Tea&quot; voting application where audience members could log in and vote.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/marktnoonan&quot;&gt;Mark Noonan&lt;/a&gt; presented &quot;Testing Vue Components with Cypress&quot; where he walked through finding and correcting errors with &lt;a href=&quot;https://www.cypress.io/&quot;&gt;Cypress&lt;/a&gt;. Testing is something I admit I am not very good at, but Cypress makes it look quite easy. I will be investigating this further for sure.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/ceceliacreates&quot;&gt;Cecelia Martinez&lt;/a&gt; presented an awesome solution for building mobile applications using Nuxt and &lt;a href=&quot;https://ionic.io/&quot;&gt;Ionic&lt;/a&gt;. Using just a single Nuxt codebase, you can compile applications for native iOS and Android applications - this made me feel like I gained a skill.&lt;/p&gt;
&lt;p&gt;There were quite a few more talks and all of them were great! I feel like I was able to pull something of value from every presentation!&lt;/p&gt;
&lt;h2&gt;Favorite Talks&lt;/h2&gt;
&lt;p&gt;Many of my favorite talks during the conference weren&apos;t necessarily as Vue-centric as the rest. Although what these folks presented certainly pertains to Vue, they can give a broader understanding of the tools and techniques for developing websites and applications.&lt;/p&gt;
&lt;h3&gt;Phil Hawksworth&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://indieweb.social/@philhawksworth&quot;&gt;Phil Hawksworth&apos;s&lt;/a&gt; presentation called &quot;Render when? Render where? Render why? Render what?&quot; broke down the various acronyms (such as &amp;lt;abbr title=&quot;static site generator&quot;&amp;gt;SSG&amp;lt;/abbr&amp;gt;, &amp;lt;abbr title=&quot;server side render&quot;&amp;gt;SSR&amp;lt;/abbr&amp;gt;, &amp;lt;abbr title=&quot;client side render&quot;&amp;gt;CSR&amp;lt;/abbr&amp;gt;, and so, so many more...) for building and rendering sites and apps used within our industry, explaining when might be best to use some over others.&lt;/p&gt;
&lt;p&gt;Ultimately, as his presentation repeatedly informed us, &lt;em&gt;it depends&lt;/em&gt; on what you are trying to accomplish. Phil explained his approach, using the &quot;&lt;a href=&quot;https://www.w3.org/2001/tag/doc/leastPower.html#:~:text=The%20%22Rule%20of%20Least%20Power,suitable%20for%20a%20given%20purpose.&quot;&gt;rule of least power&lt;/a&gt;&quot; to figure out the best option for rendering.&lt;/p&gt;
&lt;p&gt;I think Phil&apos;s presentation was super entertaining as well, mixing humor into what he was saying and into his slide deck.&lt;/p&gt;
&lt;h3&gt;Homer Gaines&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/xirclebox&quot;&gt;Homer Gaines&apos;&lt;/a&gt; presentation was mesmerizing. Homer began his talk with photo slides depicting &lt;a href=&quot;https://en.wikipedia.org/wiki/Tactile_paving&quot;&gt;Tenji blocks&lt;/a&gt; in the streets of Japan. He gave the history of the Tenji blocks and how they assist folks with sight-related disabilities to navigate cities via sidewalks.&lt;/p&gt;
&lt;p&gt;From there he segued into how folks with accessibility needs may navigate applications and websites, such as through keyboard navigation. Keyboard traps are a common accessibility pitfall that developers can face when designing interfaces and should be tested and corrected.&lt;/p&gt;
&lt;p&gt;Homer gave a rare live-coding demonstration, displaying how utilizing semantic HTML can correct a lot of these types of issues. He also demonstrated a package called &lt;a href=&quot;https://github.com/pdanpdan/vue-keyboard-trap&quot;&gt;Vue Keyboard Trap&lt;/a&gt; that adds a Vue directive that contains keyboard navigation when certain elements such as a modal are active.&lt;/p&gt;
&lt;h3&gt;Felipe Flor&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/Felipe_R_Flor&quot;&gt;Felipe Flor&lt;/a&gt;, a developer from Brazil who works for &lt;a href=&quot;https://vehikl.com/&quot;&gt;Vehikl&lt;/a&gt;, presented on developing with Vite.&lt;/p&gt;
&lt;p&gt;Felipe seems like a genuinely passionate developer. He expertly described what Vite is and how it is helpful as a build tool. He presented a comparison between Vite and Vue CLI (which utilizes Webpack) and how much faster Vite can launch an application.&lt;/p&gt;
&lt;p&gt;Speed is not the only reason to enjoy using Vite though, as it is highly customizable and simple to work with. To show this, Felipe converted an application from Vue ClI to Vite, which involved removing several packages and adding a small config file. Within just a couple of minutes, the application was converted and running in the browser.&lt;/p&gt;
&lt;p&gt;This was particularly relevant to our team as we are working through converting applications to Vite.&lt;/p&gt;
&lt;h2&gt;My Key Takeaways&lt;/h2&gt;
&lt;p&gt;There were a couple of common threads throughout the conference and one thing that caused the audience to cheer &lt;em&gt;during&lt;/em&gt; the presentation.&lt;/p&gt;
&lt;h3&gt;Nuxt&lt;/h3&gt;
&lt;p&gt;Nuxt was repeatedly brought up in nearly every talk. I feel like this is similar to the React/Next situation where it is the recommended way to build Vue applications.&lt;/p&gt;
&lt;p&gt;Though not nearly as drastic as the &lt;code&gt;create-react-app&lt;/code&gt; drama, since Vue and Vite are still a pretty powerful combination, Nuxt just gives you a lot of great functionality out-of-box and provides a thoughtful developer experience.&lt;/p&gt;
&lt;h3&gt;Typescript&lt;/h3&gt;
&lt;p&gt;Another thing that pretty much felt like a standard approach is the use of Typescript.&lt;/p&gt;
&lt;p&gt;I get this sentiment and I fully intend on making this my next mission when it comes to learning, but I also sort of dread it. I have &lt;em&gt;slight&lt;/em&gt; experience with Typescript, but ultimately it just felt like JavaScript that yells at you. For type safety, code suggestions, and tons more, Typescript certainly can be a good thing though.&lt;/p&gt;
&lt;h3&gt;FormKit&lt;/h3&gt;
&lt;p&gt;I feel like &lt;a href=&quot;https://formkit.com/&quot;&gt;FormKit&lt;/a&gt; might have stolen the show for many folks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://twitter.com/jpschroeder&quot;&gt;Justin Schroeder&lt;/a&gt; from FormKit, presented the thought process used when developing FormKit and explained how they managed to extract the essence of web forms into the tool. Developing forms is generally very hard, especially large forms, but FormKit seemingly makes it way easier.&lt;/p&gt;
&lt;p&gt;I had previously heard of FormKit but mostly thought it was another component library to reach for building forms. Though that is part of it, seemingly you can utilize any components you want.&lt;/p&gt;
&lt;p&gt;FormKit itself essentially maintains the structure of forms under the hood, making it very easy to build complex forms.&lt;/p&gt;
&lt;p&gt;This is one I will &lt;em&gt;definitely&lt;/em&gt; be digging into further, expect a blog post on this in the future.&lt;/p&gt;
</content:encoded></item><item><title>Preparing for Vue Conf with Nuxt</title><link>https://ryantrimble.com/blog/preparing-for-vue-conf-with-nuxt/</link><guid isPermaLink="true">https://ryantrimble.com/blog/preparing-for-vue-conf-with-nuxt/</guid><description>Digging into the Nuxt framework ahead of Vue Conf</description><pubDate>Sun, 21 May 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This upcoming week my team and I will be heading to New Orleans, LA to attend &lt;a href=&quot;https://us.vuejs.org/&quot;&gt;Vue Conf&lt;/a&gt;! This will be my first-ever developer conference which should be very fun.&lt;/p&gt;
&lt;p&gt;I signed up to attend the &quot;Nuxt - Inside and Out&quot; &lt;a href=&quot;https://us.vuejs.org/#workshops&quot;&gt;workshop&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/danielcroe&quot;&gt;Daniel Roe&lt;/a&gt; and I&apos;m very excited about it.&lt;/p&gt;
&lt;h2&gt;About Nuxt&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://nuxt.com/&quot;&gt;Nuxt&lt;/a&gt; is a meta-framework for Vue and provides a lot of great functionality out-of-box. I didn&apos;t want to go into the workshop completely blind, so I decided to make a small application to test it out.&lt;/p&gt;
&lt;p&gt;Technically this isn&apos;t the first time I&apos;ve used Nuxt, but this is my first time using the latest version, Nuxt 3.&lt;/p&gt;
&lt;p&gt;Nuxt 3 includes several great features including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vue 3 and Vite for superfast development.&lt;/li&gt;
&lt;li&gt;Easy-to-understand directory scaffold.&lt;/li&gt;
&lt;li&gt;Server-Side Rendering with many supported hosts.&lt;/li&gt;
&lt;li&gt;Modules to quickly integrate other tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;My Nuxt App&lt;/h2&gt;
&lt;p&gt;I decided to build a small application for users to keep track of their purchased music. This was inspired by Andy Bell&apos;s &lt;a href=&quot;https://music.andy-bell.co.uk/&quot;&gt;music collection site&lt;/a&gt; and my newfound love of collecting vinyl records.&lt;/p&gt;
&lt;p&gt;I wanted users to be able to log into the app and update their libraries, this meant that I needed to have authentication, databases, and some sort of music search.&lt;/p&gt;
&lt;p&gt;This post is intended as a summary of how I built the application using Nuxt, but if you&apos;d like to check out the full code, it is available on &lt;a href=&quot;https://github.com/mrtrimble/mymusic&quot;&gt;GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;h3&gt;Supabase Nuxt Module&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://supabase.com/&quot;&gt;Supabase&lt;/a&gt; is a great open-source alternative to Google&apos;s Firebase that provides databases and authentication. I have used Supabase before for other projects, but it was made even better when I discovered there was a &lt;a href=&quot;https://supabase.nuxtjs.org/&quot;&gt;Supabase Nuxt module&lt;/a&gt; available to be installed.&lt;/p&gt;
&lt;p&gt;Nuxt modules are plugins to enhance your Nuxt application or connect with third-party tools, such as Supabase.&lt;/p&gt;
&lt;p&gt;Using Supabase&apos;s authentication, I was able to set up GitHub and Google as authentication providers for my application.&lt;/p&gt;
&lt;p&gt;One of the great things about Nuxt is that it makes routing a lot more straightforward. You can just add a &lt;code&gt;.vue&lt;/code&gt; file to the &lt;code&gt;pages/&lt;/code&gt; directory and Nuxt will automatically build routes for it. Some routes should not be accessible by unauthenticated users, though - but this is where Nuxt&apos;s middleware comes in handy.&lt;/p&gt;
&lt;p&gt;Using the middleware, you can set up authentication criteria and redirect users who are not logged in, creating route guards.&lt;/p&gt;
&lt;p&gt;Also, since I was already using Supabase for authentication, it made sense to continue using Supabase for storing data. Of course, the Supabase Nuxt module made querying the database straightforward as well.&lt;/p&gt;
&lt;h3&gt;Music Search&lt;/h3&gt;
&lt;p&gt;For music searching, I created an &amp;lt;abbr title=&quot;application programming interface&quot;&amp;gt;API&amp;lt;/abbr&amp;gt; key with &lt;a href=&quot;https://www.discogs.com/my&quot;&gt;Discogs&lt;/a&gt;. Discogs itself is an online platform for managing your music and luckily have a free API to interact with its massive database of music.&lt;/p&gt;
&lt;p&gt;Although there are many ways to build a music search engine, I wanted to experiment with Nuxt&apos;s ability to have nested routes. For this, I created a multi-step form where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user would first search for an artist&lt;/li&gt;
&lt;li&gt;After selecting the artist, they could select a specific album from that artist&lt;/li&gt;
&lt;li&gt;In the final step, the user could select what media format they own (CD, Cassette, Digital, or Vinyl), rate the album (out of five), and select their favorite track from the album.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To build the multi-step form, I needed to have some sort of state management. Since Nuxt is based on Vue, the best choice for state management is &lt;a href=&quot;https://pinia.vuejs.org/&quot;&gt;Pinia&lt;/a&gt;. Using Pinia, I can keep track of the form data while users traverse the nested routes.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;User Profiles&lt;/h3&gt;
&lt;p&gt;I made a simple user profile page that can be viewed by browsing by the user&apos;s ID. This is handled by Nuxt&apos;s routing also.&lt;/p&gt;
&lt;p&gt;With Nuxt, you can create dynamic routes by putting brackets around the file name like &lt;code&gt;[id].vue&lt;/code&gt;. This allows you to grab the ID parameter from the URL and use it on the page, in my case I used this to query the database looking for data related to that ID.&lt;/p&gt;
&lt;h2&gt;Things I like&lt;/h2&gt;
&lt;p&gt;In my opinion, if you use Vue, Nuxt 3 has one of the best developer experiences I&apos;ve come across.&lt;/p&gt;
&lt;p&gt;One of the simplest and most convenient things about Nuxt is that you do not need to import components as any component you create within the &lt;code&gt;components/&lt;/code&gt; directory is globally available. This makes using components easier and keeps code cleaner.&lt;/p&gt;
&lt;p&gt;The fact that Nuxt makes routing easy is also a huge win in my opinion, with nested and dynamic routes providing more possibilities for your applications.&lt;/p&gt;
&lt;h2&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;I am looking forward to learning more about Nuxt from the workshop and in general looking forward to Vue Conf itself. I&apos;ve never been to New Orleans, but I&apos;ve heard it has a lot of great food. Plus I will get to spend some time with some of my team members that I don&apos;t typically get to see since they work remotely from other states.&lt;/p&gt;
&lt;p&gt;I plan to have a post-conference write-up once I get back, so keep an eye out for that!&lt;/p&gt;
</content:encoded></item><item><title>Accessible Slider Attempt</title><link>https://ryantrimble.com/blog/accessible-slider-attempt/</link><guid isPermaLink="true">https://ryantrimble.com/blog/accessible-slider-attempt/</guid><description>I attempted to make a slider element with accessibility considerations.</description><pubDate>Mon, 08 May 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sliders/carousels are pretty much the banes of user experience design. Though they can be nice to look at, they aren&apos;t the most user-friendly component and have a reputation for not being accessible.&lt;/p&gt;
&lt;p&gt;I took a stab at creating one with some accessibility considerations in mind, though I&apos;m certain there still could be improvements added.&lt;/p&gt;
&lt;h2&gt;Codepen Demo&lt;/h2&gt;
&lt;p&gt;&amp;lt;p
class=&quot;codepen&quot;
data-height=&quot;500&quot;
data-theme-id=&quot;default&quot;
data-default-tab=&quot;result&quot;
data-slug-hash=&quot;bGmYWbG&quot;
data-user=&quot;mrtrimble&quot;
style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;span&amp;gt;
See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/bGmYWbG&quot;&amp;gt;Carousel Slideshow with CSS Scrollsnap&amp;lt;/a&amp;gt; by Ryan
Trimble (&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/span&amp;gt;
&amp;lt;/p&amp;gt;
&amp;lt;script async src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;h2&gt;Considerations&lt;/h2&gt;
&lt;p&gt;Here are a few things I figured would help make this component more accessible.&lt;/p&gt;
&lt;h3&gt;Skip Link&lt;/h3&gt;
&lt;p&gt;I have added a link to skip the slider entirely. I figured this might be beneficial to folks traversing the page via keyboard by providing a way to forego tabbing through each slide individually.&lt;/p&gt;
&lt;h3&gt;Navigation&lt;/h3&gt;
&lt;p&gt;The star of this component is &amp;lt;abbr title=&quot;cascading style sheets&quot;&amp;gt;CSS&amp;lt;/abbr&amp;gt; scroll snapping. Scroll snapping provides a few benefits out-of-box:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Able to scroll using the element&apos;s scrollbar&lt;/li&gt;
&lt;li&gt;Works with mouse scroll wheels&lt;/li&gt;
&lt;li&gt;Keyboard arrow keys also scroll through the slides&lt;/li&gt;
&lt;li&gt;Also automatically works with touch-enabled devices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did also add in &quot;previous&quot; and &quot;next&quot; buttons to scroll through the slides by clicking. I did this by calculating the full width of all the slides divided by the number of slides and using that to either scroll forward or backward depending on which button is clicked.&lt;/p&gt;
&lt;h3&gt;No Autoplay&lt;/h3&gt;
&lt;p&gt;Instead of having the slider automatically switch between the slides, I have opted to make it more of a self-driven experience so users can browse that their own pace.&lt;/p&gt;
&lt;p&gt;Also, this element does not loop. I feel like having a clear-cut start and endpoints help prevent keyboard traps.&lt;/p&gt;
&lt;h2&gt;Other Features&lt;/h2&gt;
&lt;p&gt;Aside from attempting to make it as accessible as possible, I also added the ability to easily alter the slides.&lt;/p&gt;
&lt;p&gt;Using CSS Custom Properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can set the number of slides to be shown at a time&lt;/li&gt;
&lt;li&gt;Easily adjust the height&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Enhancements&lt;/h2&gt;
&lt;p&gt;I do feel there is still room for improvement on this component. One idea I had was using &lt;code&gt;aria-current&lt;/code&gt; to specify which slide is the current slide.&lt;/p&gt;
&lt;p&gt;I posted about this on &lt;a href=&quot;https://front-end.social/@mrtrimble/110312005371016913&quot;&gt;Mastodon&lt;/a&gt; asking if any other considerations that might help improve this component.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://indieweb.social/@bobmonsour&quot;&gt;Bob Monsour&lt;/a&gt; &lt;a href=&quot;https://indieweb.social/@bobmonsour/110312120438336076&quot;&gt;replied&lt;/a&gt; suggesting to hide the previous and next buttons when the scroll position is at the start or end of the slides. I haven&apos;t quite figured out how to implement that yet, but it is a solid suggestion!&lt;/p&gt;
&lt;p&gt;If anyone has any other suggestions or enhancements (or if there are things I have just flat-out ignored), please reach out to me and let me know! I&apos;m available on &lt;a href=&quot;https://www.twitter.com/mrtrimble2&quot;&gt;Twitter&lt;/a&gt;, &lt;a href=&quot;https://front-end.social/@mrtrimble&quot;&gt;Mastodon&lt;/a&gt;, and through the contact form on my site.&lt;/p&gt;
</content:encoded></item><item><title>The Popover API is exciting, sort of</title><link>https://ryantrimble.com/blog/the-popover-api-is-exciting-sort-of/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-popover-api-is-exciting-sort-of/</guid><description>Yet another experimental feature that I&apos;m excited for, but is Chrome only.</description><pubDate>Sat, 29 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At work, there is a particular component in our design system that I have made obvious I dislike immensely, yet I have not been able to figure out a solid replacement. We call it the &quot;Info Box&quot; and it&apos;s essentially just a tooltip-style element that can contain more text and actions.&lt;/p&gt;
&lt;p&gt;I&apos;m not fond of it for several reasons, but mainly I dislike it because of the number of times we run into issues using it due &lt;code&gt;z-index&lt;/code&gt; stacking.&lt;/p&gt;
&lt;p&gt;While researching a few ways to make this component better, I have come across the new &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/popover-api/&quot;&gt;Popover API&lt;/a&gt; that has certainly piqued my interest.&lt;/p&gt;
&lt;p&gt;The long and short of the Popover API is essentially it can turn any element into a top-layer popover. This means elements can live outside &amp;lt;abbr title=&quot;document object model&quot;&amp;gt;DOM&amp;lt;/abbr&amp;gt; structure, and the &lt;code&gt;z-index&lt;/code&gt; stack, potentially helping with issues such as what we are facing with the Info Box.&lt;/p&gt;
&lt;p&gt;A very important note: This is an experimental API and &lt;em&gt;should not be used in production&lt;/em&gt;. The Popover API is currently only available in Chrome Canary but is planned to be available in standard Chrome starting with version 114+.&lt;/p&gt;
&lt;h2&gt;The Good&lt;/h2&gt;
&lt;p&gt;The Popover API is being developed as a native web API proposed by the &lt;a href=&quot;https://open-ui.org/&quot;&gt;Open UI&lt;/a&gt; group. The &lt;a href=&quot;https://open-ui.org/components/popover.research.explainer/&quot;&gt;proposal&lt;/a&gt; had several great goals in mind for how popovers should function.&lt;/p&gt;
&lt;h3&gt;Accessible by default&lt;/h3&gt;
&lt;p&gt;Accessibility is an important consideration for any new features being added as native web APIs. The proposal for the popover API ensures a few things so popovers are accessible by default.&lt;/p&gt;
&lt;p&gt;Popover elements are still semantically relevant to the DOM, however, they are rendered in a layer on top of all other content. Elements in the top layer still retain all semantics, user input, and focus.&lt;/p&gt;
&lt;p&gt;Only one popover can be active at a time. Any elements added to the top layer will cause existing top-layer elements to be removed. This will prevent confusion or annoying interface behaviors that could be caused by popovers stacking on top of each other.&lt;/p&gt;
&lt;p&gt;Also, popovers include built-in &quot;light dismissal&quot; functionality, which means that users can close a popover with the &lt;code&gt;Esc&lt;/code&gt; key or click outside the popover as a default action. No need to write JavaScript to handle these actions.&lt;/p&gt;
&lt;h3&gt;Ease of use&lt;/h3&gt;
&lt;p&gt;To create a popover, simply add the &lt;code&gt;popover&lt;/code&gt; attribute to an element within the HTML.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&quot;my-popover&quot; popover&amp;gt;
  &amp;lt;p&amp;gt;This is a popover!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The default value for the &lt;code&gt;popover&lt;/code&gt; attribute is &lt;code&gt;auto&lt;/code&gt; which enables the standard behaviors such as the light dismissal. If you are using JavaScript to control the popovers, the value of &lt;code&gt;manual&lt;/code&gt; can be set to remove these standard behaviors.&lt;/p&gt;
&lt;p&gt;Elements with the &lt;code&gt;popover&lt;/code&gt; attribute are hidden with &lt;code&gt;display: none&lt;/code&gt; until opened. Active popovers are &lt;code&gt;position: fixed&lt;/code&gt; and centered in the viewport, with a barebones styling of white background and black border.&lt;/p&gt;
&lt;p&gt;There are a few ways to activate popovers, but as part of the proposal, popovers can be opened without needing any extra JavaScript using &lt;code&gt;popovertargetaction&lt;/code&gt; and &lt;code&gt;popovertarget&lt;/code&gt; attributes.&lt;/p&gt;
&lt;p&gt;Target actions include &lt;code&gt;toggle&lt;/code&gt; to open and close, &lt;code&gt;show&lt;/code&gt; to open, and &lt;code&gt;hide&lt;/code&gt; to close popovers.&lt;/p&gt;
&lt;p&gt;Targets point to the &lt;code&gt;id&lt;/code&gt; of the popover that the selected action should happen to, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button popovertargetaction=&quot;toggle&quot; popovertarget=&quot;my-popover&quot;&amp;gt;Open Toast&amp;lt;/button&amp;gt;

&amp;lt;div id=&quot;my-popover&quot; popover&amp;gt;
  &amp;lt;p&amp;gt;This is a popover!&amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This &lt;code&gt;button&lt;/code&gt; will open and close the popover element with the &lt;code&gt;id&lt;/code&gt; of &lt;code&gt;my-popover&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Popovers can be styled like any other element with &amp;lt;abbr title=&quot;cascading style sheets&quot;&amp;gt;CSS&amp;lt;/abbr&amp;gt;. Popovers can be targeted for styling using the &lt;code&gt;popover&lt;/code&gt; attribute:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[popover] {
  background: white;
  border: none;
  box-shadow: 0px 30px 80px rgba(0, 0, 0, 0.07);
  inline-size: min(100% - 1rem, 60ch);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similar to the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element, backdrops can be styled using the &lt;code&gt;::backdrop&lt;/code&gt; pseudo-element.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[popover]::backdrop {
  background: rgba(0, 0, 0, 0.5);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;figure role=&quot;group&quot; class=&quot;flow&quot;&amp;gt;
&amp;lt;video width=&quot;100%&quot; controls&amp;gt;
&amp;lt;source src=&quot;/videos/popover-api-demo.mp4&quot; type=&quot;video/mp4&quot; /&amp;gt;
&amp;lt;/video&amp;gt;
&amp;lt;figcaption&amp;gt;
&amp;lt;p style=&quot;margin-inline: 1rem&quot;&amp;gt;Video showing the Popover API in action.&amp;lt;/p&amp;gt;
&amp;lt;/figcaption&amp;gt;
&amp;lt;/figure&amp;gt;&lt;/p&gt;
&lt;p&gt;There are also JavaScript events and methods to work with popovers available as well.&lt;/p&gt;
&lt;p&gt;The two methods are &lt;code&gt;showPopover()&lt;/code&gt; and &lt;code&gt;hidePopover()&lt;/code&gt; which can be used to show and hide popovers respectively. Similarly, &lt;code&gt;onpopovershow&lt;/code&gt; and &lt;code&gt;onpopoverhide&lt;/code&gt; are the two new events that can be used to trigger further functionality when popovers are utilized.&lt;/p&gt;
&lt;h2&gt;The Bad&lt;/h2&gt;
&lt;h3&gt;Browser Support&lt;/h3&gt;
&lt;p&gt;The most obvious issue with the Popover API is the lack of browser support.&lt;/p&gt;
&lt;p&gt;This reminds me of the &lt;a href=&quot;https://developer.chrome.com/docs/web-platform/view-transitions/&quot;&gt;View Transitions API&lt;/a&gt;, which is a Chrome-only API that I&apos;m not sure will make it into other browsers (I certainly hope so!). Unlike the View Transitions API though, Popovers are not necessarily something that can easily be used as a progressive enhancement.&lt;/p&gt;
&lt;p&gt;As it is still definitely experimental and was proposed by Open UI, I&apos;m hoping Popovers can gain some traction with other browsers.&lt;/p&gt;
&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;The most similar alternative to Popovers is the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element, but there are some key differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As far as I&apos;m aware, the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element can only be opened and closed within JavaScript.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; does not have the same automatic light dismissals that Popovers do, another consideration that would need to be handled by JavaScript.&lt;/li&gt;
&lt;li&gt;I&apos;m also not sure I would consider every element in the top layer to be a dialog, so semantically sometimes it may make sense to use different elements.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Wrap up&lt;/h2&gt;
&lt;p&gt;It&apos;s difficult to see solutions to problems you are facing just out of reach like this, but I am still very excited to see how the Popover API evolves -- hopefully being adopted by more browsers.&lt;/p&gt;
&lt;p&gt;There are so many new features being proposed, developed, and added to the web which will reshape the way we develop websites and applications. I&apos;m always excited to learn more about new and potentially helpful features.&lt;/p&gt;
</content:encoded></item><item><title>The Mountain Goats at XL Live</title><link>https://ryantrimble.com/blog/the-mountain-goats-at-xl-live/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-mountain-goats-at-xl-live/</guid><description>I got to see The Mountain Goats and it was amazing.</description><pubDate>Sun, 23 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.mountain-goats.com/&quot;&gt;The Mountain Goats&lt;/a&gt; are currently on their &quot;Spectral Tide&quot; &lt;a href=&quot;https://www.mountain-goats.com/tour&quot;&gt;tour&lt;/a&gt; after releasing the album &lt;em&gt;Bleed Out&lt;/em&gt;, back in the fall of 2022.&lt;/p&gt;
&lt;p&gt;I went out to the Harrisburg, PA tour stop to watch them perform at the &lt;a href=&quot;https://www.xlhbg.com/&quot;&gt;XL Live&lt;/a&gt;. It was my first time visiting the venue and was super impressed with it, definitely look forward to my next visit.&lt;/p&gt;
&lt;h2&gt;Adeem the Artist&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.adeemtheartist.com/&quot;&gt;Adeem the Artist&lt;/a&gt; is a non-binary, alternative country musician and they ruled!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;When it comes to country music in central Pennsylvania, I tend to be a bit disenfranchised. I have listened to country music pretty much my whole life, mainly due to geographical reasons. Although there are certainly some great country artists out there, it is not my cup of tea. That said, I have been interested in some alternative country performers recently and Adeem the Artist certainly piqued my interest.&lt;/p&gt;
&lt;p&gt;Adeem&apos;s &lt;a href=&quot;https://www.setlist.fm/setlist/adeem-the-artist/2023/xl-live-harrisburg-pa-bb8c57e.html&quot;&gt;setlist&lt;/a&gt; included some great songs such as &lt;em&gt;I Never Came Out&lt;/em&gt;, personal favorite &lt;em&gt;Going to Hell&lt;/em&gt;, an awesome cover of &lt;em&gt;The Joker&lt;/em&gt; by the Steve Miller Band, and &lt;em&gt;Cast-Iron Pansexual&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Adeem was super fun and talented and spoke on some very important issues facing the LGBTQ+ community, specifically around trans rights in their home state of Tennessee.&lt;/p&gt;
&lt;h2&gt;The Mountain Goats&lt;/h2&gt;
&lt;p&gt;I&apos;m trying to buy more music rather than relying solely on streaming services. In doing so, I&apos;m following more bands on Bandcamp, which is where I noticed the Mountain Goats would be playing nearby. I&apos;ve been listening to them for years now, so I was excited at the idea of seeing them live.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I was captivated throughout the whole performance! Luckily we were able to get pretty close to the stage for their performance. Their &lt;a href=&quot;https://www.setlist.fm/setlist/the-mountain-goats/2023/xl-live-harrisburg-pa-1bb8c578.html&quot;&gt;setlist&lt;/a&gt; was broken up into four sections: full band performing, a solo set by frontman John Darnielle, the band returns, and finally an incredible encore.&lt;/p&gt;
&lt;h3&gt;First set&lt;/h3&gt;
&lt;p&gt;The band came out playing &lt;em&gt;In the Craters of the Moon&lt;/em&gt; from their &lt;em&gt;Heretic Pride&lt;/em&gt; album, which is a great song to hype up the crowd.&lt;/p&gt;
&lt;p&gt;I was immediately impressed with Matt Douglas, who started on saxophone but swapped between guitar, keyboard, synth, and vocals - sometimes seemingly within the same song.&lt;/p&gt;
&lt;h3&gt;John Darnielle Solo&lt;/h3&gt;
&lt;p&gt;John sounded great and you could tell he was having a lot of fun.&lt;/p&gt;
&lt;p&gt;His solo set included &lt;em&gt;Night of the Mules&lt;/em&gt;, &lt;em&gt;Grendel&apos;s Mother&lt;/em&gt;, &lt;em&gt;Jaipur&lt;/em&gt;, and &lt;em&gt;Color in Your Cheeks&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Amusingly, someone in the crowd called out for him to play &lt;em&gt;Noctifier Birmingham&lt;/em&gt; as that song specifically calls out Harrisburg, PA in the chorus. John admitted though that he tried to play it the night before in Philly, but forgot how to. Considering The Mountain Goats&apos; prolific discography, I can see forgetting how to play some songs.&lt;/p&gt;
&lt;h3&gt;Second set&lt;/h3&gt;
&lt;p&gt;The band returned playing &lt;em&gt;Lizard Suit&lt;/em&gt; from their album, &lt;em&gt;Dark in Here&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The second set also included some of their more well-known tracks &lt;em&gt;Love Love Love&lt;/em&gt;, &lt;em&gt;Up the Wolves&lt;/em&gt;, and &lt;em&gt;This Year&lt;/em&gt; which had the crowd singing along.&lt;/p&gt;
&lt;h3&gt;Encore&lt;/h3&gt;
&lt;p&gt;As someone who spent a lot of time going to hardcore and death metal shows in my younger days, encores are something I&apos;m still getting used to. Like they are this formality type thing at concerts: the band leaves, the crowd cheers, then the band comes back out. It&apos;s sort of weird.&lt;/p&gt;
&lt;p&gt;To be clear, I&apos;m not complaining - especially with this particular concert as they wrapped up the encore with my favorite song and the song that introduced me to The Mountain Goats, &lt;em&gt;No Children&lt;/em&gt;.&lt;/p&gt;
</content:encoded></item><item><title>I Love Cartoons</title><link>https://ryantrimble.com/blog/i-love-cartoons/</link><guid isPermaLink="true">https://ryantrimble.com/blog/i-love-cartoons/</guid><description>I&apos;m a fan of all things animated, here are a few great shows to check out.</description><pubDate>Mon, 17 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One of the many reasons I&apos;m so drawn (lol, drawn) to &amp;lt;abbr title=&quot;scalable vector graphics&quot;&amp;gt;SVG&amp;lt;/abbr&amp;gt; art and animation on the web is I &lt;em&gt;love&lt;/em&gt; cartoons. Anything from comics and graphic novels to major 3D animated movies.&lt;/p&gt;
&lt;p&gt;Cartoons are a versatile medium that offers a range of stylistic possibilities. From the unique use of color and surreal settings to the different types of animation techniques used, cartoons can be a feast for the senses. They often feature talented voice actors, beautiful scores, and fun sound effects that enhance the viewing experience.&lt;/p&gt;
&lt;p&gt;Whether telling engaging stories throughout a season or through simple one-off episodes, cartoons are enjoyable for people of all ages.&lt;/p&gt;
&lt;h2&gt;A few great shows&lt;/h2&gt;
&lt;h3&gt;Bojack Horseman&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=i1eJMig5Ik4&quot;&gt;Bojack Horseman&lt;/a&gt; is not only my favorite animated show, but one of my favorite shows &lt;em&gt;of all time&lt;/em&gt;. For a show based on anthropomorphic animals, its ability to reflect on real human emotion is top-notch.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;On the surface, there is great humor in the form of well-written dialogue, animal-based puns, and tongue twisters. Diving deeper you will find an incredible cast of characters voiced by talented actors and an overarching throughline of a deeply broken person (or horse, in this case). An exploration of depression and substance abuse and the effects on relationships.&lt;/p&gt;
&lt;p&gt;The episode titled &lt;em&gt;&quot;The View from Halfway Down&quot;&lt;/em&gt; from season 6 is my absolute favorite episode and also one I never want to watch again.&lt;/p&gt;
&lt;p&gt;Bojack Horseman was created by &lt;a href=&quot;https://www.imdb.com/name/nm4369688/&quot;&gt;Raphael Bob-Waksburg&lt;/a&gt; and can be watched on &lt;a href=&quot;https://www.netflix.com/title/70300800&quot;&gt;Netflix&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Arcane&lt;/h3&gt;
&lt;p&gt;As someone who has never once been interested in the &amp;lt;abbr title=&quot;multiplayer online battle arena&quot;&amp;gt;MOBA&amp;lt;/abbr&amp;gt; game &lt;a href=&quot;https://www.leagueoflegends.com/en-us/&quot;&gt;League of Legends&lt;/a&gt;, the show based on the game is &lt;em&gt;very&lt;/em&gt; good.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=fXmAurh012s&quot;&gt;Arcane&lt;/a&gt; has an incredible blend of 2D and 3D animation, with sequences reminiscent of &lt;a href=&quot;https://www.youtube.com/watch?v=g4Hbz2jLxvQ&quot;&gt;Spider-man: Into the Spider-verse&lt;/a&gt;. The creators provide such an emotional depth, bringing life to each character.&lt;/p&gt;
&lt;p&gt;I was not prepared to enjoy this show as much as I did and am eagerly awaiting the second season.&lt;/p&gt;
&lt;p&gt;Arcane was produced by &lt;a href=&quot;https://www.riotgames.com/en&quot;&gt;Riot Games&lt;/a&gt; with showrunners &lt;a href=&quot;https://www.imdb.com/name/nm13105261/&quot;&gt;Christian Linke&lt;/a&gt; and &lt;a href=&quot;https://www.imdb.com/name/nm13105263/&quot;&gt;Alex Yee&lt;/a&gt;. Arcane is available on &lt;a href=&quot;https://www.netflix.com/title/81435684&quot;&gt;Netflix&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Over the Garden Wall&lt;/h3&gt;
&lt;p&gt;Each year during fall, my wife and I have what we call a &quot;Fall Day&quot; where we get some soup, fall desserts, warm apple cider, and watch &lt;a href=&quot;https://www.youtube.com/watch?v=36mAsVSH_-s&quot;&gt;Over the Garden Wall&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The mini-series from &lt;a href=&quot;https://www.cartoonnetwork.com/&quot;&gt;Cartoon Network&lt;/a&gt; is ten 15-minute episodes with gorgeous set pieces, beautiful folksy music, and a touching story of two brothers lost in the Unknown.&lt;/p&gt;
&lt;p&gt;Over the Garden Wall has an amazing cast of voice actors such as Elijah Woods as Wirt, Collin Dean as Gregory, Melanie Lynskey as Beatrice, and Christopher Lloyd as The Woodsman. There are also great cameos by John Cleese, Chris Isaak, Tim Curry, Shannyn Sossamon, Thomas Lennon and many more.&lt;/p&gt;
&lt;p&gt;My favorite episode is &lt;em&gt;&quot;Welcome to Pottsville&quot;&lt;/em&gt; which captures the feeling of the fall season in ways I&apos;ve never seen before.&lt;/p&gt;
&lt;p&gt;Over the Garden Wall was created by &lt;a href=&quot;https://www.imdb.com/name/nm3239034/&quot;&gt;Patrick McHale&lt;/a&gt; and animated by &lt;a href=&quot;https://www.imdb.com/name/nm1043526/&quot;&gt;Nick Cross&lt;/a&gt; and is available to watch on &lt;a href=&quot;https://www.hbomax.com/series/urn:hbo:series:GXufwFQjcx8PCwgEAAA95&quot;&gt;HBO Max&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;The Owl House&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=1W1FFiT51lg&quot;&gt;The Owl House&lt;/a&gt; is something I never would have expected to see come out of Disney as its main themes are demons, witches, and inspiring examples of representation for the LGBTQ+ community.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The misunderstood Luz finds herself in the Demon Realm, where she meets up with Eda &quot;The Owl Lady&quot; and the demon, King. Luz is captivated by this new world and sets off on adventures to learn magic as a human, find friendship and love, and battle against an oppressive emperor in the process.&lt;/p&gt;
&lt;p&gt;Although The Owl House was canceled prematurely, the crew behind the show still managed to create an &lt;em&gt;excellent&lt;/em&gt; ending to the series.&lt;/p&gt;
&lt;p&gt;The Owl House was created with lots of love from &lt;a href=&quot;https://www.imdb.com/name/nm4869682/&quot;&gt;Dana Terrace&lt;/a&gt; and can be watched on &lt;a href=&quot;https://www.disneyplus.com/series/the-owl-house/4cOTrEy0YyaX&quot;&gt;Disney+&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Creative Takeaways&lt;/h2&gt;
&lt;p&gt;As a designer and developer, I feel that there are a lot of lessons to be learned from cartoons. I think cartoons can help you use your imagination to think a bit more creatively:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Noticing smaller details in scenes teaches you how to make a more complete design.&lt;/li&gt;
&lt;li&gt;Observing how characters interact with their surroundings to understand real-world interactions.&lt;/li&gt;
&lt;li&gt;Appreciating the fluidity and movement in animation to inspire dynamic and expressive creativity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Watch more cartoons!&lt;/p&gt;
</content:encoded></item><item><title>Arc Browser is Awesome</title><link>https://ryantrimble.com/blog/arc-browser-is-awesome/</link><guid isPermaLink="true">https://ryantrimble.com/blog/arc-browser-is-awesome/</guid><description>Product review of Arc Browser.</description><pubDate>Sat, 15 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://arc.net/&quot;&gt;Arc&lt;/a&gt; browser, by &lt;a href=&quot;https://thebrowser.company/&quot;&gt;The Browser Company of New York&lt;/a&gt;, is a new Chromium-based web browser that I have been using as my daily-driver browser. Arc is a refreshing take on a web browser in my opinion and has a few standout features.&lt;/p&gt;
&lt;h2&gt;Great Features&lt;/h2&gt;
&lt;p&gt;Arc has a lot of functionality built in that I like a lot. Many of these features could probably be attained through extensions in other browsers like Chrome and Firefox, but having them available out-of-the-box is super convenient.&lt;/p&gt;
&lt;h3&gt;Split Screen Tabs&lt;/h3&gt;
&lt;p&gt;One of the nicest features, which I&apos;m surprised other browsers haven&apos;t added, are split-screen tabs.&lt;/p&gt;
&lt;p&gt;Arc can split-screen in either horizontal or vertical layouts, and can quickly swap between the two. You can join two existing tabs together or separate existing split-screen tabs.&lt;/p&gt;
&lt;p&gt;For development, it is nice to be able to have your project and technical documentation open side-by-side.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Screenshots&lt;/h3&gt;
&lt;p&gt;The built-in screenshot tool is a super convenient feature. You can grab screenshots of the full-page, specific elements by hovering, or portions of a page by dragging to select.&lt;/p&gt;
&lt;p&gt;With Chrome, this is functionality that I usually need to reach for in an extension.&lt;/p&gt;
&lt;h3&gt;Workspaces&lt;/h3&gt;
&lt;p&gt;You can split up groups of tabs into easily switchable workspaces in Arc. I find this helpful whenever I want to have a separation between personal browsing and work-related tasks.&lt;/p&gt;
&lt;p&gt;Workspaces can be customized, given different colors and names to help distinguish between them.&lt;/p&gt;
&lt;h3&gt;Boosts&lt;/h3&gt;
&lt;p&gt;Boosts are super neat. I&apos;m not sure I have found a practical use case for them yet, but as a developer, I find them very interesting.&lt;/p&gt;
&lt;p&gt;Boosts give you the ability to add custom CSS or JavaScript to websites that you visit. These custom scripts and styles are persistent as well, so they will be applied anytime you visit a site where one is enabled.&lt;/p&gt;
&lt;h2&gt;One Drawback&lt;/h2&gt;
&lt;p&gt;The main thing I want from Arc is for it to become available on more operating systems. Currently, Arc is only available on macOS and iOS, with browser sync happening within iCloud.&lt;/p&gt;
&lt;p&gt;I am device agnostic. I use a Macbook, a Windows desktop, and an Android phone. It would be great to be able to use Arc on each, as well as synchronize my settings across devices. Arc for Windows is in the pipeline, so there is hope that it will become available for more devices.&lt;/p&gt;
&lt;h2&gt;Closing Thoughts&lt;/h2&gt;
&lt;p&gt;I&apos;m looking forward to how Arc browser evolves over time. Arc has received frequent updates as they are on a weekly release cycle. Their changelog is usually a fun read too.&lt;/p&gt;
&lt;p&gt;As mentioned, Arc is currently only available on Mac and iOS. At the time of this writing, Arc is also invite-only, but you can sign up to receive an invitation on their website.&lt;/p&gt;
</content:encoded></item><item><title>Why Astro is my Favorite Framework</title><link>https://ryantrimble.com/blog/why-astro-is-my-favorite-framework/</link><guid isPermaLink="true">https://ryantrimble.com/blog/why-astro-is-my-favorite-framework/</guid><description>Convincing you to use Astro.</description><pubDate>Sun, 09 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been following the development of &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; pretty much since the beginning. I feel like it is definitely at the point now that it is easy to recommend it when building a new website.&lt;/p&gt;
&lt;h2&gt;Experience with Astro&lt;/h2&gt;
&lt;p&gt;I think what made me seriously look into Astro was how frustrated I was with the tools we were using at work. We use a mish-mash of &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; and &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; for static sites and there seems to be frustration around developing with them.&lt;/p&gt;
&lt;p&gt;It feels like every time we run into an issue with Hugo, we spend a decent amount of time perusing forums for answers that aren&apos;t there. The community around Hugo also tends to be a bit irritable and unwelcoming, so it might be difficult to get answers.&lt;/p&gt;
&lt;p&gt;I tested out a couple of options: &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;11ty&lt;/a&gt; and Astro - both are &lt;em&gt;great&lt;/em&gt; tools with incredible communities and ultimately would recommend either. Personally speaking, the development experience with Astro is just a tad better.&lt;/p&gt;
&lt;p&gt;Astro makes things very straightforward. It uses JavaScript for templating. Pages, layouts, and partials are all Astro components. It has very simple flat-file routing. Also, their docs are &lt;em&gt;incredible&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While researching if it would be a good option at work, I was able to start building things very quickly. I built four small projects while learning what Astro had to offer:&lt;/p&gt;
&lt;h3&gt;Who&apos;s that Pokémon?&lt;/h3&gt;
&lt;p&gt;Who&apos;s that Pokémon is a small application I put together that displays a randomly selected Pokémon and reveals which one it is after 5 seconds.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The interesting thing with about this project is that it happens with no client-side JavaScript. Using Astro&apos;s server-side JavaScript, I made it so it will fetch from the &lt;a href=&quot;https://pokeapi.co/&quot;&gt;PokéAPI&lt;/a&gt; and render it at page load with Netlify&apos;s &amp;lt;abbr title=&quot;server-side rendering&quot;&amp;gt;SSR&amp;lt;/abbr&amp;gt;.&lt;/p&gt;
&lt;h3&gt;RIMdev Radio&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://rimdev-radio.netlify.app/&quot;&gt;RIMdev Radio&lt;/a&gt; was a small project I created to display some of our dev team&apos;s favorite music and manage a Spotify playlist. It didn&apos;t quite work out the way I was hoping, but that was more so my fault for not understanding the limitations of the Spotify API.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;With this project, I was able to test out Astro&apos;s &lt;a href=&quot;https://docs.astro.build/en/concepts/islands/&quot;&gt;component islands&lt;/a&gt; by using &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; alongside Astro. It was ridiculously easy to integrate and worked just as you would expect it to.&lt;/p&gt;
&lt;p&gt;I also was able to connect this to a &lt;a href=&quot;https://supabase.com/&quot;&gt;Supabase&lt;/a&gt; database easily and deploy it on &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt; using server-side rendering - this means as the database updates the site will stay up-to-date without needing to rebuild.&lt;/p&gt;
&lt;h3&gt;RIMdev Likes Food!&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://rimdev-likes-food.netlify.app/&quot;&gt;RIMdev Likes Food!&lt;/a&gt; was another team-oriented project, basically a way to list out the team&apos;s favorite places to eat. The site uses &lt;a href=&quot;https://www.mapbox.com/&quot;&gt;Mapbox&lt;/a&gt; to map out all the restaurant locations.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The goal of this project was mostly to play with content management, using Markdown and &lt;a href=&quot;https://mdxjs.com/&quot;&gt;MDX&lt;/a&gt; to display content. Each restaurant is a Markdown file that includes frontmatter data to populate information on the page, including the GPS coordinates for the map.&lt;/p&gt;
&lt;h3&gt;Friday Talk&lt;/h3&gt;
&lt;p&gt;We do Friday Talks at work where any member of the dev team can give a presentation on whatever topics they find interesting - they don&apos;t have to be work or dev related, but I often use these as an opportunity to talk about whatever it is I&apos;m currently excited about.&lt;/p&gt;
&lt;p&gt;I made a &lt;a href=&quot;https://astro-friday-talk-slides.netlify.app/&quot;&gt;slide deck&lt;/a&gt; and built a &lt;a href=&quot;https://astro-friday-talk.netlify.app/&quot;&gt;small site&lt;/a&gt; to demonstrate Astro&apos;s component islands for a talk. I had a Vue, React, and Svelte component all loading on the same page. I also demonstrated Astro&apos;s ability to use MDX by including a component inside a Markdown file.&lt;/p&gt;
&lt;p&gt;I believe this helped us decide to use Astro as a replacement for our static sites, as we started converting to it shortly after. We have converted about 4 of our sites now, with only a couple more left to do.&lt;/p&gt;
&lt;h2&gt;Favorite Features&lt;/h2&gt;
&lt;p&gt;Astro has a lot of functionality that helps make its development experience great. Here are a few of my favorite features.&lt;/p&gt;
&lt;h3&gt;Content Collections&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/content-collections/&quot;&gt;Content collections&lt;/a&gt; are a newer feature as they were only introduced in version &lt;code&gt;2.0&lt;/code&gt; of Astro, but were a life-saver during our conversions at work.&lt;/p&gt;
&lt;p&gt;These are essentially just a way to organize groups of related content into folders, outside of the flat-file routing structure.&lt;/p&gt;
&lt;p&gt;Content collections introduced a few great features along with it though:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using &lt;a href=&quot;https://zod.dev/&quot;&gt;Zod&lt;/a&gt;, you can set up a schema for markdown and MDX files to ensure you are always providing the right data in Frontmatter.&lt;/li&gt;
&lt;li&gt;Customizable slugs that enable you the ability to alter the permalink of posts. This came in very handy with how some of our website URL structures were set up.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;getCollection()&lt;/code&gt; function provides an easy way to grab all the files inside a collection.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Component Islands&lt;/h3&gt;
&lt;p&gt;We are a Vue shop at work, so being able to easily implement Vue components is super nice. Of course, this doesn&apos;t just work with Vue, just about any reactive &amp;lt;abbr title=&quot;user interface&quot;&amp;gt;UI&amp;lt;/abbr&amp;gt; framework is available as an integration.&lt;/p&gt;
&lt;p&gt;The component islands are amazing as they provide a way for developers to utilize tools that they are already familiar with or even component libraries that they built previously to integrate easily into any Astro project.&lt;/p&gt;
&lt;p&gt;Bonus points, since Astro runs JavaScript at build time, these components can render plain HTML &lt;em&gt;or&lt;/em&gt; be hydrated to run inside the client&apos;s browser.&lt;/p&gt;
&lt;h3&gt;Integrations&lt;/h3&gt;
&lt;p&gt;As previously mentioned, Astro has &lt;a href=&quot;https://astro.build/integrations&quot;&gt;integrations&lt;/a&gt; for most reactive UI frameworks, such as Vue, React, and Svelte, but they also have a bunch of other great tools to enhance websites as well.&lt;/p&gt;
&lt;p&gt;I am using a few integrations on this website:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/sitemap/&quot;&gt;Sitemaps&lt;/a&gt; - Generates your website&apos;s sitemap at build time.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/alextim/astro-lib/tree/main/packages/astro-robots-txt#readme&quot;&gt;Robots.txt&lt;/a&gt; - Creates a &lt;code&gt;robots.txt&lt;/code&gt; file for your site.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/astro-community/astro-compress#readme&quot;&gt;Compress&lt;/a&gt; - Minifies all HTML, CSS, and JavaScript files in the built version of your site.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Integrations can be used to connect to third-party tools as well. For my &lt;a href=&quot;https://plausible.io/&quot;&gt;Plausible&lt;/a&gt; website analytics script, I have installed the &lt;a href=&quot;https://partytown.builder.io/&quot;&gt;Partytown&lt;/a&gt; integration to move into a service worker and off the main thread.&lt;/p&gt;
&lt;h3&gt;Server-side Rendering&lt;/h3&gt;
&lt;p&gt;Astro is designed to render JavaScript at build time to deliver as little JavaScript to the client as possible.&lt;/p&gt;
&lt;p&gt;This gets even better by setting it up to utilize &lt;a href=&quot;https://docs.astro.build/en/guides/server-side-rendering/&quot;&gt;server-side rendering&lt;/a&gt; through a hosting provider such as Netlify as this enables you to build much more dynamic sites without needing to build the project every time.&lt;/p&gt;
&lt;h3&gt;Vite&lt;/h3&gt;
&lt;p&gt;Astro&apos;s dev and build processes are handled by another tool I am a big fan of, &lt;a href=&quot;https://vitejs.dev/&quot;&gt;Vite&lt;/a&gt;. Vite is ridiculously fast at building and hot module reloading. Vite is also a lot simpler to configure compared to other tools such as &lt;a href=&quot;https://webpack.js.org/&quot;&gt;Webpack&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Future Proof&lt;/h2&gt;
&lt;p&gt;It is hard to say what web development will look like in the future, especially with the &lt;a href=&quot;https://ryantrimble.com/blog/thoughts-on-artificial-intelligence/&quot;&gt;rise of artificial intelligence&lt;/a&gt;, but I believe that Astro is one of the most forward-thinking frameworks available.&lt;/p&gt;
&lt;p&gt;Its ability to adapt to most circumstances, excellent development experience, and commitment to producing fast and high-quality websites prove that it will continue to be a valuable tool in any developer&apos;s toolbox.&lt;/p&gt;
</content:encoded></item><item><title>The Animals that Live inside My House</title><link>https://ryantrimble.com/blog/the-animals-that-live-inside-my-house/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-animals-that-live-inside-my-house/</guid><description>Profiles of all of our pets.</description><pubDate>Sat, 01 Apr 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My wife and I love animals and probably would open a zoo if we could. We have 4 pets in total: three cats and one dog.&lt;/p&gt;
&lt;h2&gt;Current Lineup&lt;/h2&gt;
&lt;h3&gt;Sunshine&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Our oldest is Sunshine, our orange and white, fluffy cat. She has the softest fur of any cat I&apos;ve ever come across.&lt;/p&gt;
&lt;p&gt;She has gotten a bit grumpier in her old age, but she is surprisingly the most social of our cats as she likes to hang out with us when friends are over.&lt;/p&gt;
&lt;p&gt;Sunshine likes to stomp around on top of us when we try to sleep.&lt;/p&gt;
&lt;h3&gt;Aldi&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We weren&apos;t expecting to have a third cat at the time, but we rescued this little kitten and he stole our hearts.&lt;/p&gt;
&lt;p&gt;We witnessed him nearly run over by a car in front of us and we quickly tracked him down behind an &lt;a href=&quot;https://en.wikipedia.org/wiki/Aldi&quot;&gt;Aldi grocery store&lt;/a&gt;. We fished him out from under a dumpster with the help of a few of the Aldi employees. Obviously, we had to name him after the grocery store.&lt;/p&gt;
&lt;p&gt;Aldi is super fast and likes to demonstrate his speed by doing laps around the house in the middle of the night.&lt;/p&gt;
&lt;h3&gt;DD&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;DD is the youngest of our pets, only 7 months old at the time of this writing. She is a mini golden doodle pup with curly, apricot and white colored fur. She is one of the sweetest, floppiest, and funniest dogs I know.&lt;/p&gt;
&lt;p&gt;DD stands for Diamond Dog, like the &lt;a href=&quot;https://youtu.be/DGXunkHZ7CA&quot;&gt;David Bowie song&lt;/a&gt; (and a reference to &lt;a href=&quot;https://metalgear.fandom.com/wiki/DD&quot;&gt;Metal Gear Solid&lt;/a&gt;, my favorite video game series), but also just stands for Doodle Dog.&lt;/p&gt;
&lt;p&gt;DD loves meeting new people but is still sort of sketched out by other dogs. We are working on that, though. We have her attending puppy daycare where she can make all sorts of friends.&lt;/p&gt;
&lt;h3&gt;Beans&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Beans is a lovely little gray, tiger striped tabby cat we adopted through the &lt;a href=&quot;https://lovingcarecatrescue.org/&quot;&gt;Loving Care Cat Rescue&lt;/a&gt; out of Lemoyne, PA.&lt;/p&gt;
&lt;p&gt;I&apos;m still not totally sure why we named her Beans, but it really seems to fit. She is as adorable as she is stinky and she is &lt;em&gt;really&lt;/em&gt; adorable.&lt;/p&gt;
&lt;p&gt;Nicknames include: Beans, Beanie, Beanie Baby, Princess Tiabeanie, The Bean, Teeny-Beanie, and as an added bonus... every type of actual bean (Lima, Chickpea, Baked, Green, Fava, Mung, Coffee, you know just any bean).&lt;/p&gt;
&lt;h2&gt;In memoriam&lt;/h2&gt;
&lt;h3&gt;T3&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;T3 was the oldest of our pets at 17 years old and was my wife&apos;s friend even before I came into the picture back in &apos;08.&lt;/p&gt;
&lt;p&gt;Her full name was &lt;code&gt;TwentyTwoToes&lt;/code&gt;, as she was a &lt;a href=&quot;https://en.wikipedia.org/wiki/Polydactyl_cat&quot;&gt;polydactyl cat&lt;/a&gt; with a couple of extra toes. She was a gray and white, striped cat with a pink nose.&lt;/p&gt;
&lt;p&gt;She mostly stuck to the bedroom and was most certainly blind, but that didn&apos;t stop her from cuddling up with my wife every night.&lt;/p&gt;
&lt;h3&gt;Rylie&lt;/h3&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Rylie was a sheltie-pomeranian mix and a loyal friend to us, though not very nice to others. He had some behavioral issues, but we loved him and provided the best life possible for him.&lt;/p&gt;
&lt;p&gt;We got Rylie in 2010 and he was with us for 12 wonderful years. &lt;a href=&quot;https://rylie.dog/&quot;&gt;We miss you, buddy&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Thoughts on Artificial Intelligence</title><link>https://ryantrimble.com/blog/thoughts-on-artificial-intelligence/</link><guid isPermaLink="true">https://ryantrimble.com/blog/thoughts-on-artificial-intelligence/</guid><description>Sideline observations on artificial intelligence.</description><pubDate>Fri, 31 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you look at tech Twitter, it feels like artificial intelligence is the only thing anyone is discussing. AI is a topic worth exploring and something I should probably look into more myself.&lt;/p&gt;
&lt;p&gt;That being said, as someone watching from the sidelines, I do have some observations that I wanted to jot down somewhere.&lt;/p&gt;
&lt;h2&gt;The Tech&lt;/h2&gt;
&lt;p&gt;I think the technology behind these major AI projects is cool. I am a tech enthusiast through and through - so when new stuff like this comes along, I do find myself a bit giddy to try it out.&lt;/p&gt;
&lt;p&gt;I don&apos;t personally have any real-world use cases for adding AI to my current workflows, though I imagine there is some potential. Most of the experimentation I&apos;ve done with &lt;a href=&quot;https://openai.com/product/dall-e-2&quot;&gt;DALL-E 2&lt;/a&gt; or &lt;a href=&quot;https://openai.com/blog/chatgpt&quot;&gt;ChatGPT &lt;/a&gt;has been like a child with a new toy.&lt;/p&gt;
&lt;p&gt;I can see some helpfulness of it in solving some code-related problems, though I do feel like careful review is necessary when working with these tools.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Era of Close Enough&lt;/h2&gt;
&lt;p&gt;One thing that I quickly realized while playing with DALL-E 2 was that it is never quite what I want.&lt;/p&gt;
&lt;p&gt;Like whenever I write a prompt, I try to describe what I&apos;m picturing in my head - and although the AI comes up with some pretty great interpretations - it&apos;s still never &lt;em&gt;quite&lt;/em&gt; right.&lt;/p&gt;
&lt;p&gt;I&apos;m sure as these tools evolve, learning more and more, and with the right amount of iteration on a concept, I can get even closer to what was in my head, but I&apos;m not sure it will ever be exact.&lt;/p&gt;
&lt;h2&gt;How to Learn&lt;/h2&gt;
&lt;p&gt;AI learns by observing. This means it takes in large samples of text, art, music, code, and whatever else to figure out how to best generate a response.&lt;/p&gt;
&lt;p&gt;There is a very important argument to be made here about utilizing copyrighted materials, especially if the companies behind AI are profiting from it in any way. Even more so when AI is blatantly plagiarizing these copyrighted materials.&lt;/p&gt;
&lt;p&gt;There is another side of this that has crossed my mind: People &lt;em&gt;also&lt;/em&gt; learn by observing. People learn from others, including copyright materials.&lt;/p&gt;
&lt;p&gt;The speed and scale of how AI learns compared to humans is an obvious difference. Also, I&apos;m not sure if AI truly &lt;em&gt;knows&lt;/em&gt; something or if it&apos;s just ridiculously fast at looking things up. The core idea remains, though: learning by observation.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Taking Jobs&lt;/h2&gt;
&lt;p&gt;I don&apos;t think AI is going to be taking jobs anytime soon. Not saying it won&apos;t happen, automation has been an upward trend, but I don&apos;t think it will happen too quickly either.
AI is evolving very fast, maybe too fast to actually be a good idea to implement it as a core part of businesses. Plus, as it evolves, it becomes more and &lt;a href=&quot;https://openai.com/pricing&quot;&gt;more expensive&lt;/a&gt; to actually maintain.&lt;/p&gt;
&lt;p&gt;I think when companies stabilize the growth of this technology, it may become more of a concern.&lt;/p&gt;
&lt;h2&gt;New Opportunities&lt;/h2&gt;
&lt;p&gt;The more likely outcome of AI, rather than taking jobs, is the new opportunities it presents us. I think people implementing AI into work and creative flows do give us the chance to enhance what we do now.&lt;/p&gt;
&lt;p&gt;Learning to adapt alongside technology - just like we did with electricity, radio, and computers.&lt;/p&gt;
&lt;p&gt;I also believe AI could open up more avenues for assistive technologies, working with AI to perform tasks that may have been more difficult in the past.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;&quot;Normal&quot; People&lt;/h2&gt;
&lt;p&gt;At the end of the day, it is very easy to get caught up in the idea that AI is an invasion with the number of folks talking about it online. You tend to forget that these voices are not a representation of everyone. Just like the popularity of cryptocurrency and NFTs, this discourse mostly falls into the bubbles we put ourselves in.&lt;/p&gt;
&lt;p&gt;Most non-tech folks that don&apos;t necessarily spend their time doom-scrolling social media either have no knowledge of these topics or a cursory understanding at best. Once more &quot;normal&quot; people engage with AI, then I&apos;ll start to believe there is more to it than what it is now.&lt;/p&gt;
</content:encoded></item><item><title>My Favorite CSS Snippets</title><link>https://ryantrimble.com/blog/my-favorite-css-snippets/</link><guid isPermaLink="true">https://ryantrimble.com/blog/my-favorite-css-snippets/</guid><description>A few of my favorite CSS snippets.</description><pubDate>Mon, 27 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I know it isn&apos;t everyone&apos;s cup of tea, but I love CSS. I think a well-made CSS framework is great in the right context, but sometimes it is a bit overkill to add to every project. That being said, there are a few CSS snippets that I regularly reach for when developing a new project from scratch.&lt;/p&gt;
&lt;h2&gt;Reset&lt;/h2&gt;
&lt;p&gt;There are a few CSS resets that I like to use, but a more modern one I have been using lately is the &lt;a href=&quot;https://github.com/mayank99/reset.css&quot;&gt;@acab/reset.css&lt;/a&gt; by &lt;a href=&quot;https://www.mayank.co/&quot;&gt;Mayank&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I like that it is set up for use with cascade layers, so it&apos;s easy to drop into projects like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@import &apos;@acab/reset.css&apos; layer(reset);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mayank added some great features to this reset:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All rules are wrapped within a &lt;code&gt;:where&lt;/code&gt; selector to keep low specificity.&lt;/li&gt;
&lt;li&gt;Automatically works with dark mode.&lt;/li&gt;
&lt;li&gt;Includes a baked-in &lt;code&gt;.visually-hidden&lt;/code&gt; class.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Container&lt;/h2&gt;
&lt;p&gt;For a standard container class, I reach for &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Steph Eckles&apos;&lt;/a&gt; &quot;smol intrinsic container&quot; from her &lt;a href=&quot;https://moderncss.dev/&quot;&gt;Modern CSS&lt;/a&gt; and &lt;a href=&quot;https://smolcss.dev/&quot;&gt;SmolCSS&lt;/a&gt; projects:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.smol-container {
  width: min(100% - 3rem, var(--container-max, 60ch));
  margin-inline: auto;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This container is great for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It uses &lt;code&gt;min()&lt;/code&gt; functionality to ensure the container is responsive.&lt;/li&gt;
&lt;li&gt;The minimum width of the container is set to give &lt;em&gt;almost&lt;/em&gt; full width but gives some space on either side.&lt;/li&gt;
&lt;li&gt;The maximum width is variable, using the &lt;code&gt;--container-max&lt;/code&gt; custom property, and gives you a default max-width to fall back on.&lt;/li&gt;
&lt;li&gt;To center the container, it utilizes the &lt;code&gt;margin-inline: auto&lt;/code&gt; logical property to automatically fill the inline-start and inline-end space around the container&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Flow&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://every-layout.dev/&quot;&gt;Every Layout&lt;/a&gt; by Andy Bell and Heydon Pickering, they describe a technique called &quot;&lt;a href=&quot;https://every-layout.dev/layouts/stack/&quot;&gt;The Stack&lt;/a&gt;&quot; that is used to create great vertical flow on a group of stacked elements.&lt;/p&gt;
&lt;p&gt;Andy even explained on his blog that these are &lt;a href=&quot;https://andy-bell.co.uk/my-favourite-3-lines-of-css/&quot;&gt;his 3 favorite lines of CSS&lt;/a&gt;, though he prefers to call it &lt;code&gt;.flow&lt;/code&gt;, which I agree makes a bit more sense.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.flow &amp;gt; * + * {
  margin-block-start: var(--flow-space, 1em);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the &lt;a href=&quot;https://alistapart.com/article/axiomatic-css-and-lobotomized-owls/&quot;&gt;lobotomized owl selector&lt;/a&gt; in this way enables every child element, excluding the first child, inside the &lt;code&gt;.flow&lt;/code&gt; parent to receive a &lt;code&gt;margin-block-start&lt;/code&gt; of the value of &lt;code&gt;--flow-space&lt;/code&gt;. This provides a nice standard rhythm to grouped elements and since it uses a custom property, can be easily adjusted.&lt;/p&gt;
&lt;h2&gt;Fluid Type Scale&lt;/h2&gt;
&lt;p&gt;A fluid type scale means that font sizes can automatically adjust based on the viewport, helping fonts scale for various screens.&lt;/p&gt;
&lt;p&gt;The basic idea is to utilize the CSS &lt;code&gt;clamp()&lt;/code&gt; function to provide a minimum and maximum, which will then scale the font size somewhere between. This can be sort of difficult to figure out, so luckily the fine folks over at &lt;a href=&quot;https://clearleft.com/&quot;&gt;Clearleft&lt;/a&gt; created an excellent tool called &lt;a href=&quot;https://utopia.fyi/&quot;&gt;utopia.fyi&lt;/a&gt; to help calculate these fluid-type scales.&lt;/p&gt;
&lt;p&gt;Using the calculator, you can enter in values for the minimum and maximum font sizes and what font type scale you want to achieve, and it will output a lovely set of custom properties you can apply to your styles:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* @link https://utopia.fyi/type/calculator?c=320,18,1.2,1240,20,1.25,5,2,&amp;amp;s=0.75|0.5|0.25,1.5|2|3|4|6,s-l&amp;amp;g=s,l,xl,12 */

:root {
  --step--2: clamp(0.78rem, calc(0.77rem + 0.03vw), 0.8rem);
  --step--1: clamp(0.94rem, calc(0.92rem + 0.11vw), 1rem);
  --step-0: clamp(1.13rem, calc(1.08rem + 0.22vw), 1.25rem);
  --step-1: clamp(1.35rem, calc(1.28rem + 0.37vw), 1.56rem);
  --step-2: clamp(1.62rem, calc(1.5rem + 0.58vw), 1.95rem);
  --step-3: clamp(1.94rem, calc(1.77rem + 0.87vw), 2.44rem);
  --step-4: clamp(2.33rem, calc(2.08rem + 1.25vw), 3.05rem);
  --step-5: clamp(2.8rem, calc(2.45rem + 1.77vw), 3.82rem);
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>The Last of Us</title><link>https://ryantrimble.com/blog/the-last-of-us/</link><guid isPermaLink="true">https://ryantrimble.com/blog/the-last-of-us/</guid><description>My thoughts on the HBO adaption of The Last of Us.</description><pubDate>Sun, 26 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As a massive fan of the game, The Last of Us HBO series knocks it out of the park.&lt;/p&gt;
&lt;h2&gt;What they got right&lt;/h2&gt;
&lt;p&gt;The Last of Us HBO series manages to do a lot right.&lt;/p&gt;
&lt;h3&gt;Story&lt;/h3&gt;
&lt;p&gt;As my wife and I watched the show week-to-week, we also played The Last of Us Part I at the same pace to get an idea of how well the show kept to the original story.&lt;/p&gt;
&lt;p&gt;The 9-episode run manages to hit every major story beat very well when compared to the game, but the show is stripped of much of the gameplay-related action. This, unfortunately, means that there are a few in-game moments that TV viewers miss out on, but ultimately the show captures the main plot quite well.&lt;/p&gt;
&lt;h3&gt;Enhancing the Original&lt;/h3&gt;
&lt;p&gt;One thing that I think is the mark of a good adaption or sequel is when the folks adapting it use the opportunity to enhance the original. Craig Mazin and Neil Druckmann did this in a few ways that I think helped the original story.&lt;/p&gt;
&lt;p&gt;In the show, they used cold opens as a way to tell a backstory that wasn&apos;t necessarily present in the game. These additions added a bit more over-arching dread to an already dread-filled story.&lt;/p&gt;
&lt;p&gt;They also managed to fix up a few story bits that did not make as much sense in the game.&lt;/p&gt;
&lt;p&gt;For instance:&lt;/p&gt;
&lt;p&gt;In the game, Joel and Tess&apos; main goal in working with Marlene was to get weapons for some unknown reason.&lt;/p&gt;
&lt;p&gt;In the show, Joel is worried about his brother Tommy as he has not heard from him in a while, so he and Tess decide to work with Marlene to acquire a car battery to go search for Tommy.&lt;/p&gt;
&lt;p&gt;These types of small changes help make the characters&apos; motivations more believable in my opinion.&lt;/p&gt;
&lt;h3&gt;Acting&lt;/h3&gt;
&lt;p&gt;It is safe to say that Pedro Pascal might be one of the best actors working right now, and he is working a lot. This past year he has been in &lt;a href=&quot;https://youtu.be/uLtkt8BonwM&quot;&gt;The Last of Us&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/Znsa4Deavgg&quot;&gt;The Mandalorian&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/x2YHPZMj8r4&quot;&gt;The Unbearable Weight of Massive Talent&lt;/a&gt;, some weird advertisement for a &lt;a href=&quot;https://youtu.be/X8lagHPsC_U&quot;&gt;mobile game&lt;/a&gt;, and a few other roles.&lt;/p&gt;
&lt;p&gt;I&apos;m not quite sure Pedro captured the game Joel&apos;s personality perfectly. The game version of Joel feels more like a father figure than I think the TV show manages. Tonally, in the context of this show, Pedro does incredibly well as Joel however.&lt;/p&gt;
&lt;p&gt;I was one of the many that were a bit worried about how Bella Ramsey would pull off portraying Ellie. I had previously only seen Bella as Lyanna Mormont in Game of Thrones, which was excellent - but I wasn&apos;t sure how that would translate to the snarky, foul-mouthed Ellie. I shouldn&apos;t have worried, as Bella became Ellie throughout this first season.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I was also very delighted to see some of the game&apos;s stars making cameo appearances throughout the show as well. Troy Baker, Ashley Johnson, and Jeffrey Pierce show up as minor characters, Merle Dandridge brings Marlene from the game to the series, and Laura Bailey even manages to get a quick guest appearance in one of the later episodes.&lt;/p&gt;
&lt;h2&gt;What they got wrong&lt;/h2&gt;
&lt;p&gt;I think my only real complaint is the lack of clickers, especially in the later episodes. The few instances that the clickers do make appearances are great - especially the museum scene in episode two.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;HBO managed to bring the drama and story to life in the show, but I feel like they should have included more horror in the show, as the game is very much horror focused.&lt;/p&gt;
&lt;h2&gt;Final Review&lt;/h2&gt;
&lt;p&gt;This show is &lt;em&gt;incredibly&lt;/em&gt; well done, and I&apos;m still surprised they were able to pull it off. One of the best video game adaptions ever made, and I look forward to seeing how they tackle The Last of Us Part II. Highly recommend this show whether you are a fan of the games or not.&lt;/p&gt;
</content:encoded></item><item><title>Enhancing the Command Line with Fig</title><link>https://ryantrimble.com/blog/enhancing-the-command-line-with-fig/</link><guid isPermaLink="true">https://ryantrimble.com/blog/enhancing-the-command-line-with-fig/</guid><description>Product review of the CLI enhancing tool: Fig.</description><pubDate>Sat, 25 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I began using &lt;a href=&quot;https://fig.io/&quot;&gt;Fig&lt;/a&gt; when it was &lt;em&gt;just&lt;/em&gt; a tool to add autocomplete to the command line, but I have been following its development and it has made some pretty impressive additions to its feature set.&lt;/p&gt;
&lt;p&gt;Fig is a command line enhancing tool available on MacOS, Linux, and Windows - as of the time of writing, their autocomplete feature is only available on macOS.&lt;/p&gt;
&lt;h2&gt;Fig&apos;s Features&lt;/h2&gt;
&lt;h3&gt;Autocomplete&lt;/h3&gt;
&lt;p&gt;As mentioned, this was the original draw to Fig for me.&lt;/p&gt;
&lt;p&gt;Fig&apos;s &lt;a href=&quot;https://fig.io/user-manual/autocomplete&quot;&gt;autocomplete&lt;/a&gt; works great for browsing through directories, helps figure out commands to run for git and even can tell what npm scripts are available from your &lt;code&gt;package.json&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;Autocomplete supports a ton of CLI tools. I&apos;ve used it for node, dotnet, git, bash, and more.&lt;/p&gt;
&lt;p&gt;Fig&apos;s autocomplete spec is available open source, so completions can be added easily and made public for others to use. The pro version allows adding private autocompletion for your team&apos;s internal command line tools.&lt;/p&gt;
&lt;h3&gt;Scripting&lt;/h3&gt;
&lt;p&gt;Fig&apos;s &lt;a href=&quot;https://fig.io/user-manual/scripts&quot;&gt;scripting&lt;/a&gt; functionality is where things get pretty interesting.&lt;/p&gt;
&lt;p&gt;You can use their scripting editor to build out scripts that can prompt your input. This makes it easier to run sets of commands while keeping you focused on the more important parts.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Fig also has a script store where you can browse scripts created by others and add them to your list of scripts.&lt;/p&gt;
&lt;p&gt;Scripts can be shared with your team or made publicly available within the script store. Scripts will also sync across devices so you always have access to them.&lt;/p&gt;
&lt;h3&gt;Dotfiles&lt;/h3&gt;
&lt;p&gt;Fig lets you manage your shell configuration easily with their &lt;a href=&quot;https://fig.io/user-manual/dotfiles&quot;&gt;dotfile&lt;/a&gt; manager.&lt;/p&gt;
&lt;p&gt;I have found this particularly helpful with creating aliases for commands. As with scripting, dotfiles will synchronize across all devices you use Fig with, so aliases that you set up on one will work the same way on all your machines.&lt;/p&gt;
&lt;h3&gt;Plugins&lt;/h3&gt;
&lt;p&gt;The plugin store lets you add even more functionality to your setup.&lt;/p&gt;
&lt;p&gt;You can easily install shells and frameworks such as &lt;strong&gt;Oh My Zsh&lt;/strong&gt;, more auto-completion, color schemes, and much more.&lt;/p&gt;
&lt;p&gt;I have installed Oh My Zsh and the Spaceship Prompt using the plugin store.&lt;/p&gt;
&lt;h3&gt;Artificial Intelligence&lt;/h3&gt;
&lt;p&gt;As with all tech companies currently, Fig is also implementing &lt;a href=&quot;https://fig.io/user-manual/ai&quot;&gt;AI&lt;/a&gt;. I haven&apos;t tried this feature yet, but it does seem promising.&lt;/p&gt;
&lt;p&gt;The basic concept is that you can explain in plain language what you want to do in the command line and Fig&apos;s AI will be able to generate the proper command to use.&lt;/p&gt;
&lt;p&gt;The example on their website shows the user asking the AI to &quot;reverse most recent git commit&quot; and the AI spitting out:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git revert --soft HEAD^
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This certainly has the potential to save me time trying to search for the right command in sticky situations.&lt;/p&gt;
&lt;h2&gt;Final Review&lt;/h2&gt;
&lt;p&gt;My experience so far using Fig has been pretty great, honestly. I have run into some issues here and there, but they do provide an easy command to troubleshoot issues: &lt;code&gt;fig doctor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I feel the autocompletion is useful enough as is, but Fig has added a great feature set on top of that to help make using the command line simpler.&lt;/p&gt;
&lt;p&gt;I know there are some hardcore command line enthusiasts out there that will probably stray away from a tool like this, but I would still recommend giving it a shot and seeing if it could help improve your development process.&lt;/p&gt;
</content:encoded></item><item><title>Building with Polypane</title><link>https://ryantrimble.com/blog/building-with-polypane/</link><guid isPermaLink="true">https://ryantrimble.com/blog/building-with-polypane/</guid><description>Product review of Polypane, a favorite in my web developer toolkit.</description><pubDate>Fri, 17 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://polypane.app/&quot;&gt;Polypane&lt;/a&gt; has an extensive list of features that help find issues with responsive design, accessibility, search engine optimization, and much, much more.&lt;/p&gt;
&lt;h2&gt;What is Polypane?&lt;/h2&gt;
&lt;p&gt;Polypane is a web browser that is built for web development. Polypane was created by &lt;a href=&quot;https://kilianvalkhof.com/&quot;&gt;Kilian Valkhof&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whenever you load up Polypane, you&apos;ll notice that there are multiple panes for mobile, tablet, and desktop resolutions. These panes help you see your website in various screen resolutions all at the same time, helping you build great-looking designs at any screen size.&lt;/p&gt;
&lt;p&gt;This is just the tip of the iceberg though, as Polypane can help with all facets of the design and development process.&lt;/p&gt;
&lt;h2&gt;My Favorite Features&lt;/h2&gt;
&lt;p&gt;Polypane has a &lt;em&gt;lot&lt;/em&gt; of functionality. I discover new things it can do just about every time I open it up, probably because Kilian keeps adding useful features with every new version.&lt;/p&gt;
&lt;h3&gt;Workspaces&lt;/h3&gt;
&lt;p&gt;Workspaces allow you to set up panes for various types of devices, such as mobile, tablet, laptop, or desktop. Having a quick view of what a site will look like in all these different viewport sizes is incredibly handy and helps you spot potential issues a lot faster.&lt;/p&gt;
&lt;p&gt;By default you are given a standard set of viewports to work with; however, there are plenty of other options available. You can also create your workspaces manually or by scanning your site to see what breakpoints are being targeted in your CSS.&lt;/p&gt;
&lt;h3&gt;Info Tab&lt;/h3&gt;
&lt;p&gt;I use the Info tab in the Polypane dev tools as a pre-launch checklist. Polypane will display site information for things like search engine optimization, document outlines, and accessibility concerns.&lt;/p&gt;
&lt;p&gt;For search engine optimization, you can easily see all the meta information your page offers in one spot. This will give you a rundown of your page titles and descriptions, open graph and Twitter tags, icons, and even displays rich snippet and social previews.&lt;/p&gt;
&lt;p&gt;The document outline section provides an overview of the structure of your page regarding headings, landmarks, links, images, and focus order. I use the outline section to ensure I&apos;m delivering logical hierarchy and semantic web pages.&lt;/p&gt;
&lt;p&gt;Accessibility is one of the most important pieces of developing a website in my opinion, so having a tool to help find these issues is crucial. Not only does Polypane find problems, but it also suggests potential ways to correct them using best practices.&lt;/p&gt;
&lt;h3&gt;Screenshot Tool&lt;/h3&gt;
&lt;p&gt;Polypane&apos;s built-in screenshot tool is great as it allows you to quickly grab the full page, viewport, or specific elements on the page.&lt;/p&gt;
&lt;p&gt;With the screenshot editor, you can annotate, add stickers, redact, crop, and resize the screenshot. Redacting sensitive information in screenshots is very important with certain projects I have worked on.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h3&gt;Debug Tools&lt;/h3&gt;
&lt;p&gt;Polypane includes a variety of debugging tools to help out with things such as layouts, accessibility, and content.&lt;/p&gt;
&lt;p&gt;While I was writing this article I utilized the &lt;code&gt;a11y.css&lt;/code&gt; tools to identify more ways to improve accessibility on this site!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Excellent Support&lt;/h2&gt;
&lt;p&gt;I met Kilian through the Frontend Horse developer community and have reached out to him a couple of times regarding Polypane.&lt;/p&gt;
&lt;p&gt;The first time was due to an update to Polypane not working on my Macbook. Kilian had a patch out very quickly that got Polypane working for me.&lt;/p&gt;
&lt;p&gt;Recently I reached out to him about a feature request, and within 10 minutes, he already implemented the suggestion, and &lt;a href=&quot;https://twitter.com/polypane/status/1636439399746420745?s=20&quot;&gt;it will be a part of an upcoming release&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Needless to say, Polypane is very well supported.&lt;/p&gt;
&lt;h2&gt;Final Review&lt;/h2&gt;
&lt;p&gt;Polypane is absolutely one of my favorite tools to develop projects with and helps ensure that I can develop high-quality and accessible websites and applications.&lt;/p&gt;
&lt;p&gt;I recommend this to any web developers looking to improve their development process.&lt;/p&gt;
</content:encoded></item><item><title>JavaScript List Formatting and Astro</title><link>https://ryantrimble.com/blog/javascript-list-formatting-and-astro/</link><guid isPermaLink="true">https://ryantrimble.com/blog/javascript-list-formatting-and-astro/</guid><description>JavaScript features work well with Astro (obviously).</description><pubDate>Sat, 11 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Sometimes you write a bit of JavaScript that makes you remember why you like using JavaScript. I had one of these moments while working on a site conversion from &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; to &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;I ran into a dilemma where I needed to output a list of authors in the byline of a post, links on each of their names, and comma formatted.&lt;/p&gt;
&lt;p&gt;There are probably hundreds of ways to accomplish this, but I chose to use the &lt;code&gt;Intl.ListFormat&lt;/code&gt; (&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat&quot;&gt;reference&lt;/a&gt;) object.&lt;/p&gt;
&lt;p&gt;The functionality this provides is great as you basically just need to pass in an array and it automagically formats it in a variety of ways:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// This:
const array = [&apos;Apples&apos;, &apos;Strawberries&apos;, &apos;Bananas&apos;];
const listFormatter = new Intl.ListFormat();
listFormatter.format(array);

// Outputs as:
Apples, Strawberries, and Bananas
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It even includes an Oxford comma!&lt;/p&gt;
&lt;h2&gt;The solution&lt;/h2&gt;
&lt;p&gt;Using Astro functionality and vanilla JavaScript, we can figure out a pretty impressive solution for this.&lt;/p&gt;
&lt;h3&gt;Content collections&lt;/h3&gt;
&lt;p&gt;Astro has a great feature called content collections which was introduced in version &lt;code&gt;2.0&lt;/code&gt;. Content collections let you group relevant markdown files inside one folder like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/src/content/authors
  bruce-wayne.md
  clark-kent.md
  peter-parker.md
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Structuring the data&lt;/h3&gt;
&lt;p&gt;So with the &lt;code&gt;authors&lt;/code&gt; content collection created, I made a new Astro component called &lt;code&gt;PostAuthors.astro&lt;/code&gt; and inside imported the &lt;code&gt;getCollection&lt;/code&gt; function provided by Astro. Now I was able to return an array of authors from the content collection:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { getCollection } from &apos;astro:content&apos;;
const authorCollection = await getCollection(&apos;authors&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also want to be able to include this inside a layout where it can accept a list of the specific post&apos;s authors, so I set up an &lt;code&gt;authors&lt;/code&gt; prop:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const { authors } = Astro.props;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I could create a new array using the &lt;code&gt;.map&lt;/code&gt; array method by filtering down the &lt;code&gt;authors&lt;/code&gt; collection compared to the list of post authors, then flattening the new array:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const postAuthors = entry.data.authors
  .map(author =&amp;gt;
    authorsCollection.filter(a =&amp;gt; {
      return a.data.name == author;
    })
  )
  .flat();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This gives me a list of just the authors on the post but also contains all the necessary information from the author&apos;s entry in the content collection.&lt;/p&gt;
&lt;h3&gt;Intl.ListFormat in action&lt;/h3&gt;
&lt;p&gt;Now here&apos;s where the fun part comes in. Using &lt;code&gt;Intl.ListFormat&lt;/code&gt;, we can pass in an array of HTML which returns a comma formatted list containing links for each other:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const authorNames = new Intl.ListFormat(&apos;en&apos;).format(
  postAuthors.map(author =&amp;gt; {
    return `
      &amp;lt;a href=&quot;/author/${author.slug}&quot;&amp;gt;
      ${author.data.name}
      &amp;lt;/a&amp;gt;`;
  })
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inside the Astro template, we can utilize &lt;code&gt;Fragment&lt;/code&gt; and &lt;code&gt;set:html&lt;/code&gt; to output the results:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;Written by: &amp;lt;Fragment set:html=&quot;{authorNames}`&quot; /&amp;gt;.&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Why is this cool?&lt;/h2&gt;
&lt;p&gt;So why this is so fascinating to me because of how Astro itself works - much like backend scripting languages, such as PHP, it runs all this JavaScript before building the page.&lt;/p&gt;
&lt;p&gt;The client sees none of this and only receives a well-formatted piece of HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;p&amp;gt;
  Written by &amp;lt;a href=&quot;/author/bruce-wayne&quot;&amp;gt;Bruce Wayne&amp;lt;/a&amp;gt;, &amp;lt;a href=&quot;/author/clark-kent&quot;&amp;gt;Clark Kent&amp;lt;/a&amp;gt;, and
  &amp;lt;a href=&quot;/author/peter-parker&quot;&amp;gt;Peter Parker&amp;lt;/a&amp;gt;.
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moving this type of thing to the build process means we get to deliver a lot leaner experience for our users, and I think that is very cool.&lt;/p&gt;
&lt;h2&gt;Full component code&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;---
import { getCollection } from &apos;astro:content&apos;;
const authorCollection = await getCollection(&apos;authors&apos;);

const { authors } = Astro.props;

const postAuthors = entry.data.authors
  .map(author =&amp;gt; authorsCollection.filter(a =&amp;gt; {
    return a.data.name == author
  }))
  .flat();

const authorNames = new Intl.ListFormat(&apos;en&apos;).format(
  postAuthors.map(author =&amp;gt; {
    return `
      &amp;lt;a href=&quot;/author/${author.slug}&quot;&amp;gt;
      ${author.data.name}
      &amp;lt;/a&amp;gt;`
  })
);
---

&amp;lt;p&amp;gt;Written by: &amp;lt;Fragment set:html={authorNames}` /&amp;gt;.&amp;lt;/p&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>London Calling</title><link>https://ryantrimble.com/blog/london-calling/</link><guid isPermaLink="true">https://ryantrimble.com/blog/london-calling/</guid><description>I finally took an actual vacation and experienced the miracle of flight.</description><pubDate>Fri, 10 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I am now a world traveler. My wife and I finally took an actual vacation to London - where we got to experience a lot of new things!&lt;/p&gt;
&lt;h2&gt;First flight&lt;/h2&gt;
&lt;p&gt;I had never been on an airplane before this trip. I&apos;m not a fan of heights, but for some reason, I wasn&apos;t very nervous about the actual flying part. &lt;a href=&quot;https://flightaware.com/&quot;&gt;FlightAware&lt;/a&gt; eases my nerves about flying, as you can see how many airplanes are in the sky at any given moment.&lt;/p&gt;
&lt;p&gt;The part that made me most nervous was all airport-related:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have all the proper documents&lt;/li&gt;
&lt;li&gt;Arrive on time&lt;/li&gt;
&lt;li&gt;Find the right gate&lt;/li&gt;
&lt;li&gt;Luggage check&lt;/li&gt;
&lt;li&gt;TSA Security&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That stuff. Very intimidating for someone new to flying. Everything went smoothly, though, and we were able to board the plane.&lt;/p&gt;
&lt;p&gt;The flight from Baltimore to Iceland was the first flight. We flew &lt;a href=&quot;https://www.flyplay.com/&quot;&gt;Play Airlines&lt;/a&gt;, a budget airline that, while not the most comfortable, was still enjoyable. My wife did learn she gets motion sickness while on planes, unfortunately.&lt;/p&gt;
&lt;p&gt;The layover in Iceland was welcome after spending about six hours on a cramped, warm, and muggy plane. We stretched our legs and enjoyed the cold for a bit until we had to board the next flight to London.&lt;/p&gt;
&lt;p&gt;The London flight was a bit easier (and shorter), and we made it there in one piece! The next stop was our hotel.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;The hotel&lt;/h2&gt;
&lt;p&gt;After a long flight, we were ready to take a nap!&lt;/p&gt;
&lt;p&gt;We stayed at the &lt;a href=&quot;https://www.premierinn.com/gb/en/hotels/england/greater-london/london/hub-london-goodge-street.html&quot;&gt;hub by Premier Inn&lt;/a&gt; near Goodge Street station. Which was a decent spot, easy to walk around and find things or hop on the tube to other parts of the city.&lt;/p&gt;
&lt;p&gt;The staff was all super nice and accommodating. They had unlimited complimentary coffee and tea and served breakfast!&lt;/p&gt;
&lt;h2&gt;Our week in London&lt;/h2&gt;
&lt;p&gt;The main inspiration for the trip was my wife Vickie. She has met a lot of awesome folks from all around the world through her online writing community. This was a chance for them to finally meet in person and attend a &lt;a href=&quot;https://youtu.be/2HcVZm_4qAI&quot;&gt;K-pop concert&lt;/a&gt; they are all fans of. I&apos;m super glad she got this opportunity and was able to enjoy spending her time with her new friends.&lt;/p&gt;
&lt;p&gt;I am a very anxious person, and while I did manage to enjoy my trip, I had trouble planning anything. I pretty much winged it and even got to meet one of my friends from overseas.&lt;/p&gt;
&lt;h3&gt;Day 1&lt;/h3&gt;
&lt;p&gt;The band my wife was going to see was having a pop-up shop in Waterloo Station, so we walked there together. We probably could have taken a train, but we wanted to be able to explore and see some sights.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After the pop-up shop, we ventured onto our next destination, &lt;a href=&quot;https://www.britishmuseum.org/&quot;&gt;The British Museum&lt;/a&gt;. We stopped in at their pizzeria and had a wonderful pepperoni pizza with chili jam on it. It was delicious.&lt;/p&gt;
&lt;p&gt;I wasn&apos;t aware of how excited I was going to be to see the various exhibits at the museum until I was there. I was &lt;em&gt;very&lt;/em&gt; excited.&lt;/p&gt;
&lt;h3&gt;Day 2&lt;/h3&gt;
&lt;p&gt;My wife was finally getting to meet up with her friends! She went to brunch and had a wonderful time.&lt;/p&gt;
&lt;p&gt;I was exhausted from traveling, though - so day 2 was a bit of a non-starter for me. I stayed at the hotel, relaxed, and worked on coding projects. I know, I&apos;m not very fun!&lt;/p&gt;
&lt;p&gt;Later that night, we met back up for dinner at &lt;a href=&quot;https://dintaifung-uk.com/&quot;&gt;Din Tai Fung&lt;/a&gt; in Covent Garden and got to experience the deliciousness of soup dumplings for the first time.&lt;/p&gt;
&lt;h3&gt;Day 3&lt;/h3&gt;
&lt;p&gt;Much more exciting day: I got to meet one of my friends from the &lt;a href=&quot;https://frontend.horse/&quot;&gt;Frontend Horse&lt;/a&gt; community, Arran.&lt;/p&gt;
&lt;p&gt;Arran toured us around the London Bridge area. He told us all about the history of various places, even showing us some Roman ruins along the way.&lt;/p&gt;
&lt;p&gt;We explored the &lt;a href=&quot;https://cathedral.southwark.anglican.org/&quot;&gt;Southwark Cathedral&lt;/a&gt; where we got to meet Hodge, a cat that lives in the cathedral.&lt;/p&gt;
&lt;p&gt;We stopped in at the &lt;a href=&quot;https://boroughmarket.org.uk/&quot;&gt;Borough Market&lt;/a&gt;, had a delicious crumble, and talked politics.&lt;/p&gt;
&lt;p&gt;Later that night, Vickie went to the concert, and I met back up with Arran for more exploring. We walked and talked, stopping for snacks along the way. We finished off the night in a lovely British pub.&lt;/p&gt;
&lt;h3&gt;Day 4&lt;/h3&gt;
&lt;p&gt;We went to Paddington Station to visit the Paddington Bear statue and pick up a souvenir from the store.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;From Paddington Station, we took a walk to Hyde Park, where one of the best moments happened:&lt;/p&gt;
&lt;p&gt;Vickie loves birdwatching, but the only birds we had seen were pigeons. She expressed she was hoping to see different types of birds while in another country. Not a moment later, a parakeet landed in front of us. There are &lt;a href=&quot;https://www.theguardian.com/cities/2019/jun/06/the-great-green-expansion-how-ring-necked-parakeets-took-over-london&quot;&gt;tons of parakeets&lt;/a&gt; flying around in London! She was ecstatic!&lt;/p&gt;
&lt;p&gt;Before leaving the park, we stopped at the statue of Queen Victoria (Vickie&apos;s namesake). Next, we headed towards South Kensington to visit &lt;a href=&quot;https://designmuseum.org/&quot;&gt;The Design Museum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Design Museum is &lt;em&gt;gorgeous&lt;/em&gt;. Many wonderful pieces on display from various aspects of design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Fashion&lt;/li&gt;
&lt;li&gt;Graphic design&lt;/li&gt;
&lt;li&gt;Technology&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;A great stop if, like me, you are into that sort of thing.&lt;/p&gt;
&lt;p&gt;We rounded out the day by heading over to King&apos;s Cross Station. There we checked out Platform 9¾ and visited the Harry Potter shop.&lt;/p&gt;
&lt;h3&gt;Day 5&lt;/h3&gt;
&lt;p&gt;On the final day, we went to the &lt;a href=&quot;https://www.vam.ac.uk/&quot;&gt;V&amp;amp;A Museum&lt;/a&gt;. There was an exhibit there called ”&lt;a href=&quot;https://www.vam.ac.uk/exhibitions/hallyu-the-korean-wave&quot;&gt;Hallyu! The Korean Wave&lt;/a&gt;&quot; which showcased the global impact of South Korean pop culture. This was amazing!&lt;/p&gt;
&lt;p&gt;They had several items from our favorite movies, like &lt;a href=&quot;https://youtu.be/hBNBpNcuQHI&quot;&gt;Oldboy&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=5xH0HfJHsaY&quot;&gt;Parasite&lt;/a&gt;, as well as from K-pop and fashion.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;We checked out the rest of the museum as well, seeing awesome pieces from various eras and places. I especially enjoyed seeing items from Japan.&lt;/p&gt;
&lt;p&gt;After finishing up at the V&amp;amp;A, I heard there was a protest occurring outside the Russian Embassy. We decided to go check it out. Protestors painted the street in front of the embassy the color of the Ukraine flag, yellow and blue. People were there showing support for Ukraine, asking Russia to stop the invasion. Seeing this was quite an experience for me.&lt;/p&gt;
&lt;p&gt;We grabbed some food and returned to the hotel to rest up and get ready for our trip back home.&lt;/p&gt;
</content:encoded></item><item><title>New Website</title><link>https://ryantrimble.com/blog/new-website/</link><guid isPermaLink="true">https://ryantrimble.com/blog/new-website/</guid><description>Redesigning my website using Astro and modern CSS!</description><pubDate>Thu, 09 Mar 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve been obsessed with &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; for a while now; however, I hadn&apos;t converted my website. Time to change that!&lt;/p&gt;
&lt;h2&gt;Previous website&lt;/h2&gt;
&lt;p&gt;I&apos;m not sure I was ever happy with my previous website. I did a few neat things on there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Animations&lt;/li&gt;
&lt;li&gt;Themes&lt;/li&gt;
&lt;li&gt;Bold typography&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately I just never felt super excited about it, though.&lt;/p&gt;
&lt;p&gt;I intended on blogging at least once a month but failed miserably at that - eventually just removing the blog section from the site altogether.&lt;/p&gt;
&lt;h2&gt;Inspirations&lt;/h2&gt;
&lt;p&gt;Learning a lot about newer technologies, such as Astro and more modern approaches to CSS, has been causing an itch in my brain for a while.&lt;/p&gt;
&lt;h3&gt;Learning Astro&lt;/h3&gt;
&lt;p&gt;At work, we were in talks to refactor our static sites onto a platform other than &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;, so I began experimenting with Astro a bit. I developed a couple of websites for my work team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://rimdev-radio.netlify.app/&quot;&gt;RIMdev Radio&lt;/a&gt; - Displays songs we love and automatically updates a Spotify playlist.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://rimdev-likes-food.netlify.app/&quot;&gt;RIMdev Likes Food!&lt;/a&gt; - Another small site to display our favorite restaurants&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Astro impressed me a lot, and as a team, we began implementing Astro on a few of our sites.&lt;/p&gt;
&lt;h3&gt;Modern CSS&lt;/h3&gt;
&lt;p&gt;I took &lt;a href=&quot;https://thinkdobecreate.com/&quot;&gt;Stephanie Eckles&lt;/a&gt; Modern CSS workshop last year, and it was incredible! I want to implement the things I learned into &lt;em&gt;everything!&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I finally understand &lt;code&gt;grid&lt;/code&gt; and &lt;code&gt;clamp&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Building the aforementioned Astro projects using these newer techniques was great. Everything just seemed to be falling into place.&lt;/p&gt;
&lt;h3&gt;Content creation&lt;/h3&gt;
&lt;p&gt;I wrote an article for &lt;a href=&quot;https://12daysofweb.dev/&quot;&gt;12daysofweb.dev&lt;/a&gt; on the new &lt;a href=&quot;https://12daysofweb.dev/2022/view-transitions-api/&quot;&gt;View Transitions&lt;/a&gt; API and was just thrilled with the whole process.&lt;/p&gt;
&lt;p&gt;A driving force for the new website is that I want to do content creation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blogging&lt;/li&gt;
&lt;li&gt;Making Videos&lt;/li&gt;
&lt;li&gt;Tutorials&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am super excited about learning and want to be able to help pass along what I&apos;ve learned.&lt;/p&gt;
&lt;h2&gt;My new site&lt;/h2&gt;
&lt;p&gt;I want this site to be the best representation of myself and my skills. It will be a culmination of all the things I&apos;ve been learning and practicing over the past few years.&lt;/p&gt;
&lt;p&gt;I want to give this a shot and see what I can do with it. I won&apos;t have everything I have planned completed by the time I deploy, but I fully intend to iterate on this latest version and build something great.&lt;/p&gt;
</content:encoded></item><item><title>RIMdev Radio: Building with Astro</title><link>https://ryantrimble.com/blog/rimdev-radio-building-with-astro/</link><guid isPermaLink="true">https://ryantrimble.com/blog/rimdev-radio-building-with-astro/</guid><description>Re-upload of an article I originally published on RIMdev.io, discussing how to build a music application with Astro.</description><pubDate>Wed, 12 Oct 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My current favorite thing in web dev is a new site generator called &lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Astro is like &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; and &lt;a href=&quot;https://11ty.dev&quot;&gt;11ty&lt;/a&gt;, yet contains a few neat tricks right out of the box. The main goal of Astro is to deliver as little JavaScript to the browser as possible. It handles this by running JavaScript in the build process or when rendered server-side. That is not to say you can&apos;t run JavaScript in the browser though. In fact, you can include components from any of the major JS frameworks, such as Vue, React, and Svelte. This is possible through a concept Astro is pioneering: &lt;a href=&quot;https://docs.astro.build/en/concepts/islands/&quot;&gt;component islands&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I recently &lt;a href=&quot;https://astro-friday-talk-slides.netlify.app/1&quot;&gt;delivered a talk&lt;/a&gt; on Astro to our dev team as part of the &quot;Friday Talks&quot; we do here in RIMdev. I demonstrated how to build with Astro and its server-side rendering capability. The &lt;a href=&quot;https://astro-friday-talk.netlify.app/&quot;&gt;first demo&lt;/a&gt; shows off its framework agnostic abilities, and how to run JavaScript. The &lt;a href=&quot;http://astro-pokemon.netlify.app/&quot;&gt;second demo&lt;/a&gt; shows how you can run JavaScript server-side and deliver only HTML. These projects were fun to build, but I wanted to try and build something with a bit more substance.&lt;/p&gt;
&lt;h2&gt;RIMdev Radio&lt;/h2&gt;
&lt;p&gt;Annual enrollment period is RitterIM&apos;s busiest part of the year and we have been doing a lot of prep-work for it. Music is near essential as there is a lot of manual testing performed. I traded song recommendations with a few folks on the Front End team and thought it might be fun to make a site out of it. &lt;a href=&quot;https://rimdev-radio.netlify.app/&quot;&gt;RIMdev Radio&lt;/a&gt; is a place to display and listen to what music team members like the most.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I built the site using a few different technologies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt; - Site generator&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; - CSS preprocessor&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; - JavaScript framework&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://supabase.com/&quot;&gt;Supabase&lt;/a&gt; - a cloud PostgreSQL database&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.spotify.com/&quot;&gt;Spotify API&lt;/a&gt; - Searching and playlist management&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt; - Server-side rendering/hosting&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The idea was that team members would be able to search Spotify for songs and update the playlist. Recommendations get stored in a database table, which would then display on the home page. The idea didn&apos;t quite pan out due to limitations of the Spotify API, but still able to deliver with a slight pivot.&lt;/p&gt;
&lt;p&gt;In Spotify, you can set up collaborative playlists that allow you and friends to add songs to a playlist. This function is not available to the API though, as spammers could overrun playlists. I learned this at the finish line, so while I can update the playlist through the API - no one else can. Unfortunate as this was the main feature of the app.&lt;/p&gt;
&lt;p&gt;That&apos;s OK though! Team members that choose to take part can send me songs they would like included and I can update the playlist. This was a super fun weekend project and I was able to learn a lot, so no harm done!&lt;/p&gt;
&lt;h2&gt;Piecing it all together&lt;/h2&gt;
&lt;h3&gt;Astro&lt;/h3&gt;
&lt;p&gt;Everything happens inside Astro and luckily getting started is quite easy!&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;npm create astro@latest&lt;/code&gt; command walks you through the process of setting up a new instance. I choose the default options for everything, except opting out of using TypeScript.&lt;/p&gt;
&lt;p&gt;From there, the new site will scaffold and there are a few organizational things to take note of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Pages&lt;/strong&gt; directory is where each site page will live. These will use the &lt;code&gt;.astro&lt;/code&gt; file extension, and are capable of running JavaScript at build. This allows you to generate HTML code by running certain JavaScript functionality.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Components&lt;/strong&gt; directory will house UI components. These can be Astro components or components for whichever framework you prefer.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Layouts&lt;/strong&gt; directory is where you can include components used for layout purposes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I intended to use Sass for styling, I also added a &lt;code&gt;styles&lt;/code&gt; folder to the &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;Speaking of which, to set up Sass - you do need to install Sass as a dependency to use it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install -d sass
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;From there, your Sass file gets imported into your main &lt;code&gt;Layout.astro&lt;/code&gt; file like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import &apos;../styles/styles.scss&apos;;
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As Astro uses &lt;a href=&quot;https://vitejs.dev/&quot;&gt;Vite&lt;/a&gt; under the hood, Sass will get compiled and included as a linked asset in the HTML.&lt;/p&gt;
&lt;p&gt;I also wanted to be able to use Vue as a component framework. Astro provides easy-to-use integrations, so adding Vue to the project was a matter of running:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx astro add vue
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This automically installs the Vue package and includes it in the &lt;code&gt;astro.config.mjs&lt;/code&gt; file.&lt;/p&gt;
&lt;h3&gt;Supabase&lt;/h3&gt;
&lt;p&gt;I found myself liking the combination of Supabase and Astro&apos;s server-side rendering. Supabase is a cloud database service, like Google&apos;s &lt;a href=&quot;https://firebase.google.com/&quot;&gt;Firebase&lt;/a&gt;, but runs on PostgreSQL. For a project like this, it worked out nice!&lt;/p&gt;
&lt;p&gt;To use Supabase, create an account and a new database. Then you can install the package with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install @supabase/supabase-js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I created a &lt;code&gt;.env&lt;/code&gt; file in the root of the project and added my Supabase key:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SUPABASE_KEY={YOUR SUPABASE KEY}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Supabase also provides a database URL, which can also be in the &lt;code&gt;.env&lt;/code&gt; file. I did not, instead I added it direct in JavaScript.&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;pages/index.astro&lt;/code&gt;, you can import &lt;code&gt;createClient&lt;/code&gt; from the Supabase package. You can also grab the &lt;code&gt;.env&lt;/code&gt; variables and apply them as constants.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
import Layout from &apos;../layouts/Layout.astro&apos;;
import { createClient } from &apos;@supabase/supabase-js&apos;;

const supabaseUrl = {YOUR SUPABASE URL}
const supabaseKey = import.meta.env.SUPABASE_KEY
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can query the database and retrieve data from tables! For example, if we wanted to select all the rows of a table called &lt;code&gt;recommendations&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;let { data: recommendations, error } = await supabase.from(&apos;recommendations&apos;).select();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This query will run on page build (or on server-side render) and store it in the &lt;code&gt;recommendations&lt;/code&gt; array. From there, we can use &lt;code&gt;recommendations&lt;/code&gt; inside the template with normal JavaScript array methods.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
  {recommendations
    .sort((a, b) =&amp;gt; a.id - b.id)
    .reverse()
    .map(rec =&amp;gt; (
      &amp;lt;Recommendation recommendation={rec} /&amp;gt;
    ))}
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also insert data into the database using Supabase methods. I created a form within a Vue component and a method to submit items to the database. Inserting data to Supabase looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;await supabase.from(&apos;recommendations&apos;).insert([
  {
    name: &apos;Ryan&apos;,
    song: &apos;Moon Song&apos;,
  },
]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Definitely one of the simplest ways to use a database that I&apos;ve come across!&lt;/p&gt;
&lt;h3&gt;Spotify API&lt;/h3&gt;
&lt;p&gt;The Spotify API is available to anyone who has a premium plan with Spotify.&lt;/p&gt;
&lt;p&gt;Registering a new app will provide you with a client ID and client secret codes. Store these in your &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SPOTIFY_CLIENT_ID={YOUR CLIENT ID}
SPOTIFY_CLIENT_SECRET={YOUR CLIENT SECRET}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To use the Spotify API, it is necessary to be able to authenticate users with Spotify in some way.&lt;/p&gt;
&lt;p&gt;Spotify provides several methods to do so. As I intended on using server-side rendering, I could use the &lt;a href=&quot;https://developer.spotify.com/documentation/general/guides/authorization/client-credentials/&quot;&gt;Client Credential Flow&lt;/a&gt;. This method allows users to authenticate with Spotify, retrieve an OAuth code, which the app can then trade for an access token. Access tokens will be used to make API calls.&lt;/p&gt;
&lt;p&gt;I set up Astro pages to handle the authentication routing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pages/auth/login.astro&lt;/code&gt; - This is the page that initiates the authentication process with Spotify. Users will be redirected to the Spotify login page.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pages/auth/callback.astro&lt;/code&gt; - Callback is the page where users will be directed after logging into Spotify. There will be an OAuth token added as a URL search parameter that can be retrieved and used for the next step. I stored this temporarily in the browser&apos;s local storage.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pages/auth/token.astro&lt;/code&gt; - The Token page is where we pass the OAuth token back to Spotify to retrieve an access token. Here the access token is stored as a cookie with an one hour expiration. Spotify access tokens only last one hour. After successfully retrieving an access token, the user is redirected back to the home page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Within each of those pages, I included a corresponding Vue component to handle the client side JavaScript part of the authentication process.&lt;/p&gt;
&lt;p&gt;Once the authentication is out of the way, users can then use their access token to perform API calls such as searching the Spotify library.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const handleSearch = () =&amp;gt; {
  const endpoint = new URL(&apos;https://api.spotify.com/v1/search&apos;);
  endpoint.searchParams.append(&apos;query&apos;, search.value);
  endpoint.searchParams.append(&apos;type&apos;, &apos;track&apos;);
  endpoint.searchParams.append(&apos;market&apos;, &apos;US&apos;);
  if (access_token.value) searchSpotifyApi(endpoint.href);
};

const searchSpotifyApi = async url =&amp;gt; {
  options.value = [];
  return await fetch(url, {
    method: &apos;GET&apos;,
    headers: {
      Authorization: `Bearer ${access_token.value}`,
    },
  })
    .then(response =&amp;gt; response.json())
    .then(data =&amp;gt; {
      options.value = [...data.tracks.items];
    })
    .catch(err =&amp;gt; console.log(err));
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I set up a separate API call which adds items to a playlist, but as previously mentioned, does &lt;em&gt;not&lt;/em&gt; allow users to update playlists they do not own.&lt;/p&gt;
&lt;h3&gt;Netlify&lt;/h3&gt;
&lt;p&gt;Netlify is a great service for deploying static sites. Like Amazon Web Service&apos;s product Lambda, Netlify also provides the capability of running cloud functions. Astro can be built in a way to leverage this feature, enabling server-side rendering. This may sound complicated at first, but it is almost &lt;em&gt;too&lt;/em&gt; easy as Astro provides an integration to help set this up.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npx astro add netlify
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Running the add Netlify integration command will automatically install necessary packages and update the &lt;code&gt;astro.config.mjs&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Now all that is needed is to deploy the site to Netlify. I typically do this by connecting Netlify to the GitHub repo, which gives the added benefit of automatically re-deploying the site when pushing to the main branch. You can also use PR Previews to see changes to the site before a pull request is even merged to the main branch.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Overall, working with Astro is a super enjoyable experience. I&apos;m looking forward to building more projects with it!&lt;/p&gt;
&lt;p&gt;I&apos;d like to give a special shout out to my friend &lt;a href=&quot;https://twitter.com/MaciejPedzich&quot;&gt;Mac&lt;/a&gt; for help navigating the Spotify API.&lt;/p&gt;
&lt;p&gt;You can find the full code available on the &lt;a href=&quot;https://github.com/mrtrimble/rimdev-radio&quot;&gt;RIMdev Radio repo&lt;/a&gt; on Github.&lt;/p&gt;
</content:encoded></item><item><title>Recreating the Spotify &quot;Like&quot; Button</title><link>https://ryantrimble.com/blog/recreating-the-spotify-like-button/</link><guid isPermaLink="true">https://ryantrimble.com/blog/recreating-the-spotify-like-button/</guid><description>Re-upload of an article I originally published on RIMdev.io, discussing how to recreate the Spotify like button with CSS and SVG.</description><pubDate>Thu, 11 Aug 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently a fellow team member challenged me to recreate the new Spotify &quot;Like&quot; button using only CSS. Honestly I&apos;m not sure if he &lt;em&gt;challenged&lt;/em&gt; me necessarily, but posed the question &quot;can you pull this off with css?&quot; - that was enough for me.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Breaking down the animation&lt;/h2&gt;
&lt;p&gt;The Spotify Like button has a few neat animations happening:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Before liking a song, it looks like a traditional heart shaped icon, with a white outline and transparent fill.&lt;/li&gt;
&lt;li&gt;Upon liking a song, several smaller hearts seemingly explode out of it and float upward.&lt;/li&gt;
&lt;li&gt;A green circular pulse emits from the central heart&lt;/li&gt;
&lt;li&gt;The heart icon itself fills in with the Spotify green color&lt;/li&gt;
&lt;li&gt;Unliking a song also has a small animation of the heart icon shaking and reverting back to the white outline and transparent fill.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;Getting started&lt;/h2&gt;
&lt;p&gt;I did a quick search for a simple heart shape SVG on Google and &lt;a href=&quot;https://freesvg.org/black-heart-icon&quot;&gt;found a perfect option&lt;/a&gt;. Next I took that SVG and tossed it into &lt;a href=&quot;https://figma.com/&quot;&gt;Figma&lt;/a&gt; to make a few quick adjustments. Mostly just changing colors and including the extra &quot;exploding&quot; hearts in the SVG that we&apos;ll later animate.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;After grouping all relevant elements together, I used Figma&apos;s incredibly useful &lt;strong&gt;copy to SVG&lt;/strong&gt; feature to grab the SVG code and paste it into a new &lt;a href=&quot;https://www.codepen.io/&quot;&gt;Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I also converted the outline strokes of the SVG elements into paths.&lt;/p&gt;
&lt;h2&gt;HTML structure&lt;/h2&gt;
&lt;p&gt;I decided that since the goal was to not use any JavaScript, I would utilize the checkbox trick for managing the state of the like button.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;input type=&quot;checkbox&quot; id=&quot;like&quot; name=&quot;like&quot;&amp;gt;
&amp;lt;label for=&quot;like&quot;&amp;gt;
 &amp;lt;!--SVG Code here!--&amp;gt;
&amp;lt;/like&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Including the SVG inside the &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; tag means that clicking on the SVG will check the checkbox!&lt;/p&gt;
&lt;h2&gt;Adding default CSS&lt;/h2&gt;
&lt;p&gt;For the default stylings of this Like button, there are a few things needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The checkbox itself does not actually need to be displayed, so I hid it with &lt;code&gt;display: none&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The central heart needed a transparent fill and a white border.&lt;/li&gt;
&lt;li&gt;The smaller hearts don&apos;t need to be shown yet either, however they will need to animate and set the opacity to &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The CSS sibling selector makes it possible to easily target the label that appears next to the input like so: &lt;code&gt;input[type=&quot;checkbox&quot;] + label&lt;/code&gt;. This is super useful in applying different styles to elements within the label when the input is checked versus unchecked.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;input[type=&apos;checkbox&apos;] + label {
  /* Unchecked styles... */
}

input[type=&apos;checked&apos;]:checked + label {
  /* Checked styles */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Creating the animations&lt;/h2&gt;
&lt;p&gt;I ended up creating two keyframe animations and one transition to make this look nice.&lt;/p&gt;
&lt;h3&gt;Center heart&lt;/h3&gt;
&lt;p&gt;The center heart icon that user&apos;s click utilizes a CSS transition to go from it&apos;s unchecked to checked state:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Center heart */
input[type=&apos;checkbox&apos;] + label #center-heart #inner {
  fill: transparent;
  transition: 0.2s ease;
}
input[type=&apos;checkbox&apos;] + label #center-heart #outer {
  fill: white;
  transition: 0.2s ease;
}

input[type=&apos;checkbox&apos;]:checked + label #center-heart #inner {
  fill: #64d26d;
}
input[type=&apos;checkbox&apos;]:checked + label #center-heart #outer {
  fill: #64d26d;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is great as it will reverse the transition when unchecking as well!&lt;/p&gt;
&lt;h3&gt;Exploding hearts&lt;/h3&gt;
&lt;p&gt;The exploding hearts required a percentage based keyframe animation to make the hearts visible, apply the floating effect, and then finally disappear again.&lt;/p&gt;
&lt;p&gt;For the animation&apos;s easing-function, I played around with a custom &lt;a href=&quot;https://cubic-bezier.com/#.12,.84,.5,.44&quot;&gt;cubic bezier&lt;/a&gt; &lt;code&gt;in-and-out&lt;/code&gt; type curve to make the animation a little smoother looking.&lt;/p&gt;
&lt;p&gt;I did not want all the exploding hearts to animate at the exact same time though, so I added an &lt;code&gt;animation-delay&lt;/code&gt; to those specific elements at various timings - just to mix it up a little bit.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Exploading hearts */
input[type=&apos;checkbox&apos;]:checked + label #left-hearts &amp;gt; *,
input[type=&apos;checkbox&apos;]:checked + label #right-hearts &amp;gt; * {
  transform-origin: center center;
  animation: floatingHearts 0.65s cubic-bezier(0.12, 0.84, 0.5, 0.44) forwards;
}
input[type=&apos;checkbox&apos;]:checked + label #right-hearts g:first-child {
  animation-delay: 0.3s;
}
input[type=&apos;checkbox&apos;]:checked + label #right-hearts g:last-child {
  animation-delay: 0.1s;
}
input[type=&apos;checkbox&apos;]:checked + label #left-hearts g:first-child {
  animation-delay: 0.2s;
}
input[type=&apos;checkbox&apos;]:checked + label #left-hearts g:last-child {
  animation-delay: 0.5s;
}

@keyframes floatingHearts {
  0% {
    opacity: 0;
    transform: translateY(10px);
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 0;
    transform: translateY(-50px);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Pulsing effect&lt;/h3&gt;
&lt;p&gt;The final animation I wanted to include was the pulsing effect that happens upon clicking the button. I did not need to create any other HTML or SVG elements for this, but instead utilized CSS &lt;code&gt;::before&lt;/code&gt; and &lt;code&gt;::after&lt;/code&gt; pseudo-selectors to create rings around the SVG. The rings would transform by scaling from &lt;code&gt;0&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; then finally disappear by changing the opacity to &lt;code&gt;0&lt;/code&gt;. For this I used another percentage based keyframe animation.&lt;/p&gt;
&lt;p&gt;I utilized the same &lt;a href=&quot;https://cubic-bezier.com/#.12,.84,.5,.44&quot;&gt;cubic bezier&lt;/a&gt; curve for this animation&apos;s easing-function animation as well.&lt;/p&gt;
&lt;p&gt;And similarly to the exploding hearts, I targeted one of the rings to have a slight animation delay to provide a slightly neater looking animation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;input[type=&apos;checkbox&apos;]:checked + label::before,
input[type=&apos;checkbox&apos;]:checked + label::after {
  content: &apos;&apos;;
  display: grid;
  border-radius: 100%;
  position: absolute;
  outline: 25px solid #64d26d;
  height: 300px;
  width: 300px;
  animation: scalePulse 0.5s cubic-bezier(0.12, 0.84, 0.5, 0.44) forwards;
}

input[type=&apos;checkbox&apos;]:checked + label::after {
  animation-delay: 0.2s;
}

@keyframes scalePulse {
  from {
    transform: scale(0);
  }
  to {
    transform: scale(1.1);
    opacity: 0;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Bringing it all together&lt;/h2&gt;
&lt;p&gt;After all the CSS is in place, clicking on the heart button should provide a great looking animation that is very similar to the one found in Spotify when liking a song.&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe
height=&quot;500&quot;
style=&quot;width: 100%;&quot;
scrolling=&quot;no&quot;
title=&quot;CSS Only Spotify Like Button&quot;
src=&quot;https://codepen.io/mrtrimble/embed/KKoBYxZ?default-tab=result&amp;amp;theme-id=dark&quot;
frameborder=&quot;no&quot;
loading=&quot;lazy&quot;
allowtransparency=&quot;true&quot;
allowfullscreen=&quot;true&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;See the Pen &amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/KKoBYxZ&quot;&amp;gt;CSS Only Spotify Like Button&amp;lt;/a&amp;gt; by Ryan Trimble (
&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;p&gt;Full code available on &lt;a href=&quot;https://codepen.io/mrtrimble/pen/KKoBYxZ&quot;&gt;Codepen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The animation I ended up was ultimately slightly different than the Spotify animation itself, however I think it still turned out nicely!&lt;/p&gt;
</content:encoded></item><item><title>Building an Online Store with Platform UI and Hugo</title><link>https://ryantrimble.com/blog/building-an-online-store-with-platform-ui-and-hugo/</link><guid isPermaLink="true">https://ryantrimble.com/blog/building-an-online-store-with-platform-ui-and-hugo/</guid><description>Re-upload of an article I originally published on RIMdev.io, discussing how to build a JAMstack Online Store using Platform UI, Hugo, and Snipcart.</description><pubDate>Thu, 16 Jun 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;With the release of our CSS Framework, &lt;a href=&quot;https://www.platformui.com/&quot;&gt;Platform UI&lt;/a&gt;, it might be fun to actually build something with it!&lt;/p&gt;
&lt;p&gt;At RitterIM, we have an internal store to buy RitterIM merch, such as shirts, office supplies, and more. Employees can buy products with cash or use &quot;Ritter Bucks&quot;. &lt;strong&gt;Ritter Bucks&lt;/strong&gt; are not some fancy new crypto-currency, but instead a way to incentivise great work!&lt;/p&gt;
&lt;p&gt;The Ritter Store is only at our Harrisburg office, so as the basis of this project: let&apos;s build an online store!&lt;/p&gt;
&lt;h2&gt;What We&apos;ll Use&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.platformui.com/&quot;&gt;Platform UI&lt;/a&gt; - Our latest public release and the CSS framework we use for our applications.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt; - Static Site Generator based on the Go programming language.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://snipcart.com/&quot;&gt;Snipcart&lt;/a&gt; - A simple way to add a store to any website.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Installing Hugo&lt;/h2&gt;
&lt;p&gt;The first step to working on a Hugo site is installing Hugo. There are a few ways to go about that depending on which operating system you are working on.&lt;/p&gt;
&lt;p&gt;For MacOS, make sure you have &lt;a href=&quot;https://brew.sh/&quot;&gt;Homebrew&lt;/a&gt; setup and run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install hugo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For Windows, you can install via &lt;a href=&quot;https://chocolatey.org/&quot;&gt;Chocolatey&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;choco install hugo -confirm
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;See the Hugo &lt;a href=&quot;https://gohugo.io/getting-started/installing&quot;&gt;installation guide&lt;/a&gt; for further information and installation on other operating systems.&lt;/p&gt;
&lt;h2&gt;Creating a Hugo Site&lt;/h2&gt;
&lt;p&gt;Hugo installs on systems globally, so you can now run Hugo commands.&lt;/p&gt;
&lt;p&gt;In your terminal, navigate to the directory you&apos;d like to setup the new site. Once there, run the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hugo new site hugo-store
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will scaffold a new Hugo project for us. Browse into the new site. Next we will want to create a Hugo theme to use for the store - to do that, run:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hugo new theme store-theme
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we can apply that theme by opening the &lt;code&gt;config.toml&lt;/code&gt; file and adding:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;theme = &quot;hugo-store&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To actually view the Hugo site, we can run the command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hugo server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Though there isn&apos;t much going on there at the moment, this will start the Hugo server and serve up pages we&apos;ll create throughout this project.&lt;/p&gt;
&lt;p&gt;Let&apos;s add in some content, then we can dive into building out our theme!&lt;/p&gt;
&lt;h2&gt;Adding Content&lt;/h2&gt;
&lt;p&gt;Content in Hugo can be added in many different ways, however one of the simplest approaches is by adding markdown files to the &lt;code&gt;~/hugo-site/content&lt;/code&gt; directory. Content can also be organized by creating subfolders of the content directory. For our store example, we want to organize products into different categories, such as &quot;Home Goods&quot; or &quot;Office Supplies.&quot; Let&apos;s begin adding content by setting up our categories.&lt;/p&gt;
&lt;h3&gt;Categories&lt;/h3&gt;
&lt;p&gt;Browse to &lt;code&gt;~/hugo-site/content&lt;/code&gt; and add folders for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clothes&lt;/li&gt;
&lt;li&gt;Home Goods&lt;/li&gt;
&lt;li&gt;Office Supplies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Inside each newly created category folder, add an &lt;code&gt;_index.md&lt;/code&gt; markdown file. Each index file will contain very simple front matter:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/hugo-site/content/clothes/_index.md&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Clothes
layout: list
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;~/hugo-site/content/home-goods/_index.md&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Home Goods
layout: list
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;~/hugo-site/content/office-supplies/_index.md&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: Office Supples
layout: list
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As noted in the markdown file&apos;s front matter, each of these pages will use the &lt;code&gt;list&lt;/code&gt; layout that we will create in just a bit. This is all we will need to add categories. Feel free to add as many categories as you&apos;d like!&lt;/p&gt;
&lt;h3&gt;Products&lt;/h3&gt;
&lt;p&gt;We can now add products inside category folders. For example, let&apos;s create a T-Shirt markdown file inside the &lt;code&gt;clothes&lt;/code&gt; folder:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/hugo-store/content/clothes/t-shirt.md&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;---
title: T-Shirt
layout: single
id: t-shirt-knight
price: 11
tags:
  - knight logo
image: /images/products/tshirt.jpeg
image_alt: T-Shirt with Knight logo.
---

RitterIM branded, t-shirt with Knight logo.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For each product, we are looking to add the following data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Title - name of the product.&lt;/li&gt;
&lt;li&gt;Layout - the layout the product page will use, for our demo this will be &lt;code&gt;single&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;ID - this is a unique identifier for the product, this will come in handy later when we implement Snipcart.&lt;/li&gt;
&lt;li&gt;Price - the price of the product.&lt;/li&gt;
&lt;li&gt;Tags - used to describe the product, add as many descriptive tags as needed.&lt;/li&gt;
&lt;li&gt;Image - the path to an image of a product. In Hugo, static files such as images get added to the &lt;code&gt;~/hugo-store/themes/store-theme/static/&lt;/code&gt; directory. I&apos;ve organized mine to include an &lt;code&gt;images&lt;/code&gt; folder and a &lt;code&gt;products&lt;/code&gt; sub-folder.&lt;/li&gt;
&lt;li&gt;Image Alt - this is an alternative text description that gets included on images.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outside of the front matter, we can include the content of the page. This will reflect as the description of a product shown on our store.&lt;/p&gt;
&lt;p&gt;Add as many products as you&apos;d like, I&apos;m going to add the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clothes
&lt;ul&gt;
&lt;li&gt;Cardigan&lt;/li&gt;
&lt;li&gt;Hoodie&lt;/li&gt;
&lt;li&gt;Jacket&lt;/li&gt;
&lt;li&gt;T-Shirt&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Home Goods
&lt;ul&gt;
&lt;li&gt;Blanket&lt;/li&gt;
&lt;li&gt;Coaster&lt;/li&gt;
&lt;li&gt;Frisbee&lt;/li&gt;
&lt;li&gt;Picture Frame&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Office Supplies
&lt;ul&gt;
&lt;li&gt;Laptop Bag&lt;/li&gt;
&lt;li&gt;Mouse Pad&lt;/li&gt;
&lt;li&gt;Notebook&lt;/li&gt;
&lt;li&gt;Pen&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Building a Theme&lt;/h2&gt;
&lt;p&gt;Let&apos;s set up a simple theme that we can use for our store.&lt;/p&gt;
&lt;h3&gt;Adding Platform UI&lt;/h3&gt;
&lt;p&gt;A super simple way to get started using Platform UI is by &lt;a href=&quot;https://platformui.com/docs/getting-started/cdn/&quot;&gt;linking to the CDN&lt;/a&gt; via jsdelivr.&lt;/p&gt;
&lt;p&gt;Browse to the &lt;code&gt;~/hugo-store/themes/store-theme/layouts/partials/head.html&lt;/code&gt; file and include the CDN like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- head.html --&amp;gt;
&amp;lt;link rel=&quot;preconnect&quot; href=&quot;cdn.jsdelivr.net/&quot; crossorigin /&amp;gt;
&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;cdn.jsdelivr.net/npm/@ritterim/platform-ui/dist/platform-ui.min.css&quot; crossorigin /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will include the main CSS stylings for the Platform UI framework. While we are in the &lt;code&gt;head.html&lt;/code&gt; file, let&apos;s add a title for the site:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- head.html --&amp;gt;
&amp;lt;link rel=&quot;preconnect&quot; href=&quot;cdn.jsdelivr.net/&quot; crossorigin /&amp;gt;
&amp;lt;link rel=&quot;stylesheet&quot; href=&quot;cdn.jsdelivr.net/npm/@ritterim/platform-ui/dist/platform-ui.min.css&quot; crossorigin /&amp;gt;

&amp;lt;title&amp;gt;Hugo Store&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Platform UI also includes JavaScript functionality for things like accordions, drawers, and modals. To include this in our site, add the CDN link to &lt;code&gt;~/hugo-store/themes/store-theme/partials/footer.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- footer.html --&amp;gt;
&amp;lt;script src=&quot;cdn.jsdelivr.net/npm/@ritterim/platform-ui/dist/js/platform-ui.min.js&quot; crossorigin defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can take advantage of everything Platform UI has to offer!&lt;/p&gt;
&lt;h3&gt;Header&lt;/h3&gt;
&lt;p&gt;We can use Platform UI&apos;s &lt;a href=&quot;https://platformui.com/docs/menus/site-menu/&quot;&gt;site menu&lt;/a&gt; to get this set up. Open up &lt;code&gt;~/hugo-store/themes/store-theme/partials/header.html&lt;/code&gt; and add in the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- header.html --&amp;gt;
&amp;lt;header id=&quot;header&quot; class=&quot;header site-header background--lightblue&quot;&amp;gt;
  &amp;lt;div class=&quot;max-container h-100&quot;&amp;gt;
    &amp;lt;a class=&quot;site-logo p-2 h-100 flex flex--align-center text--bold text--size-lg&quot; href=&quot;/&quot;&amp;gt; Hugo Store &amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/header&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A quick explanation of what is happening:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We create a site header by adding the &lt;code&gt;site-header&lt;/code&gt; class to the &lt;code&gt;&amp;lt;header&amp;gt;&lt;/code&gt; element.&lt;/li&gt;
&lt;li&gt;We can also set the background color using the &lt;code&gt;background--lightblue&lt;/code&gt; class. This is part of Platform UI&apos;s &lt;a href=&quot;https://platformui.com/docs/colors/colors/&quot;&gt;color&lt;/a&gt; classes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;max-container&lt;/code&gt; on the inner &lt;code&gt;div&lt;/code&gt; applies a centered, &lt;a href=&quot;https://platformui.com/docs/layout/max-width/&quot;&gt;max-width container&lt;/a&gt; to the header.&lt;/li&gt;
&lt;li&gt;On the &lt;code&gt;site-logo&lt;/code&gt; we are applying flex utility classes to center the link text. We are also adding some &lt;a href=&quot;https://platformui.com/docs/typography/typography/&quot;&gt;typographical&lt;/a&gt; utilities to enlarge (&lt;code&gt;text--size-lg&lt;/code&gt;) and bold the text (&lt;code&gt;text--bold&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the purposes of this demo, this is all we need, though this could be expanded further by adding in a navigation!&lt;/p&gt;
&lt;h3&gt;Category / List Pages&lt;/h3&gt;
&lt;p&gt;The category pages will be what we use to display all the categories related products. In Hugo, this is as known as a &quot;list&quot; page, as it lists out all the related content. You can rename this file as something other than &lt;code&gt;list&lt;/code&gt;, but for our example we will keep it as the default.&lt;/p&gt;
&lt;p&gt;We can leverage Platform UI&apos;s layout &lt;a href=&quot;https://platformui.com/docs/layout/blocks/&quot;&gt;blocks&lt;/a&gt; to display the products on the page. Blocks enable a responsive grid of rows and columns to create layouts.&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;~/hugo-store/themes/store-theme/layouts/_default/list.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- list.html --&amp;gt;
{{ &apos;{{&apos; }} define &quot;main&quot; }}
&amp;lt;article class=&quot;max-container pt-4&quot;&amp;gt;
  &amp;lt;div class=&quot;flex flex--center-content&quot;&amp;gt;
    &amp;lt;h2&amp;gt;{{ &apos;{{&apos; }} .Title }}&amp;lt;/h2&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;ul class=&quot;list block-container blocks tablet-up-2 lg-tablet-up-3 laptop-up-4&quot;&amp;gt;&amp;lt;/ul&amp;gt;
&amp;lt;/article&amp;gt;
{{ &apos;{{&apos; }} end }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we are outputting the &lt;code&gt;.Title&lt;/code&gt; of the category and setting up the &lt;code&gt;block-container&lt;/code&gt; to list products. The &lt;code&gt;blocks&lt;/code&gt; class enables the mobile-first responsive layout. We can tell the container how many blocks should be in each row at different breakpoints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By default a block will take up 100% of the row, which works well for mobile devices.&lt;/li&gt;
&lt;li&gt;On tablet and up, &lt;code&gt;tablet-up-2&lt;/code&gt; specifies that there will be two blocks per row.&lt;/li&gt;
&lt;li&gt;For larger tablets and up, &lt;code&gt;lg-tablet-up-3&lt;/code&gt; means there will be three blocks per row.&lt;/li&gt;
&lt;li&gt;Finally for laptop screens and up, &lt;code&gt;laptop-up-4&lt;/code&gt; will display four blocks per row.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To actually iterate over the products available, we can use Hugo&apos;s &lt;code&gt;range&lt;/code&gt; function. The range we will be looping through is the category&apos;s &lt;code&gt;.Pages&lt;/code&gt;, so inside the &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; we can include the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{ &apos;{{&apos; }} range .Pages }}
&amp;lt;li class=&quot;block&quot;&amp;gt;&amp;lt;/li&amp;gt;
{{ &apos;{{&apos; }} end }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This means an &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element will output for each page created within the category.&lt;/p&gt;
&lt;p&gt;As far as actually displaying a product, we can use Platform UI&apos;s &lt;a href=&quot;https://platformui.com/docs/components/cards/&quot;&gt;card&lt;/a&gt; component. We want to include the following information inside the card:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Product Image (if available)&lt;/li&gt;
&lt;li&gt;Product Title&lt;/li&gt;
&lt;li&gt;Product Description&lt;/li&gt;
&lt;li&gt;Product Sizes&lt;/li&gt;
&lt;li&gt;Product Tags&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&apos;s create a card inside the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;card m-2&quot;&amp;gt;
  {{ &apos;{{&apos; }} with .Params.image }}
  &amp;lt;img class=&quot;card__image&quot; src=&quot;{{ &apos;{{&apos; }} . }}&quot; /&amp;gt;
  {{ &apos;{{&apos; }} end }}
  &amp;lt;div class=&quot;card__header flex flex--align-center flex--justify-between&quot;&amp;gt;
    &amp;lt;h3 class=&quot;product__name text--navy text--bold text--uppercase text--size-md mb-0&quot;&amp;gt;{{ &apos;{{&apos; }} .Params.title }}&amp;lt;/h3&amp;gt;
    &amp;lt;span class=&quot;product__price text--bold text--navy text--size-md&quot;&amp;gt; ${{ &apos;{{&apos; }} .Params.price }} &amp;lt;/span&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;card__content&quot;&amp;gt;
    &amp;lt;div class=&quot;flex&quot;&amp;gt;
      {{ &apos;{{&apos; }} with .Params.tags }} {{ &apos;{{&apos; }} range . }}
      &amp;lt;span class=&quot;pill mr-1&quot;&amp;gt;{{ &apos;{{&apos; }} . }}&amp;lt;/span&amp;gt;
      {{ &apos;{{&apos; }} end }} {{ &apos;{{&apos; }} end }}
    &amp;lt;/div&amp;gt;
    &amp;lt;p class=&quot;product__description&quot;&amp;gt;{{ &apos;{{&apos; }} .Content }}&amp;lt;/p&amp;gt;
    &amp;lt;div class=&quot;product__button-container&quot;&amp;gt;
      &amp;lt;a class=&quot;button&quot; href=&quot;{{ &apos;{{&apos; }} .Permalink }}&quot;&amp;gt; View Details &amp;lt;/a&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a lot going on here, so let&apos;s break a few things down!&lt;/p&gt;
&lt;p&gt;On each of the product markdown files, there is some default metadata each product includes, such as &lt;code&gt;.Content&lt;/code&gt; and &lt;code&gt;.Permalink&lt;/code&gt;. For more custom data, &lt;code&gt;.Params&lt;/code&gt; match up to front matter found inside the markdown file.&lt;/p&gt;
&lt;p&gt;Depending on the product, you might not have an image or tags params available. To make up for this, we use Hugo&apos;s &lt;code&gt;with&lt;/code&gt; check to see if a parameter exists and display it if so. The &lt;code&gt;with&lt;/code&gt; check also scopes the contextual data of the param, so it can then be output by using &lt;code&gt;{{ &apos;{{&apos; }} . }}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We are also using Hugo&apos;s &lt;code&gt;range&lt;/code&gt; to output product tags as Platform UI &lt;a href=&quot;https://platformui.com/docs/components/pill/&quot;&gt;pills&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Product / Single Pages&lt;/h3&gt;
&lt;p&gt;Like &lt;code&gt;list&lt;/code&gt; pages, Hugo uses &lt;code&gt;single&lt;/code&gt; for individual pages within the site. In our demo, these are pages for specific products. We could rename this page to &lt;code&gt;product&lt;/code&gt; if we wanted, but for the purposes of the example we will keep it as is.&lt;/p&gt;
&lt;p&gt;Single pages are like the &lt;code&gt;list&lt;/code&gt; file, displaying data and front matter from the markdown files.&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;~/hugo-store/themes/store-theme/layouts/_default/single.html&lt;/code&gt; let&apos;s add the following markup:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- single.html --&amp;gt;
{{ &apos;{{&apos; }} define &quot;main&quot; }}
&amp;lt;article class=&quot;max-container&quot;&amp;gt;
  &amp;lt;section class=&quot;block-container&quot;&amp;gt;
    &amp;lt;div class=&quot;block lg-tablet-up-6 p-4&quot;&amp;gt;
      &amp;lt;figure class=&quot;figure-hover&quot;&amp;gt;
        &amp;lt;img src=&quot;{{ &apos;{{&apos; }} .Params.Image }}&quot; alt=&quot;{{ &apos;{{&apos; }} .Params.Image_alt }}&quot; /&amp;gt;
        &amp;lt;figcaption&amp;gt;{{ &apos;{{&apos; }} .Params.Image_alt }}&amp;lt;/figcaption&amp;gt;
      &amp;lt;/figure&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;block lg-tablet-up-6 my-4&quot;&amp;gt;
      &amp;lt;div class=&quot;card&quot;&amp;gt;
        &amp;lt;div class=&quot;flex flex--justify-between flex--align-center border-b border--width-2 border--color-orange mb-3&quot;&amp;gt;
          &amp;lt;h1 class=&quot;text--bold text--navy&quot;&amp;gt;{{ &apos;{{&apos; }}.Title}}&amp;lt;/h1&amp;gt;
          &amp;lt;span class=&quot;text--bold text--navy text--size-lg&quot;&amp;gt; ${{ &apos;{{&apos; }} .Params.Price }} &amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;flex mb-4&quot;&amp;gt;
          {{ &apos;{{&apos; }} with .Params.Tags }} {{ &apos;{{&apos; }} range . }}
          &amp;lt;span class=&quot;pill mr-1&quot;&amp;gt; {{ &apos;{{&apos; }} . }} &amp;lt;/span&amp;gt;
          {{ &apos;{{&apos; }} end }} {{ &apos;{{&apos; }} end }}
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;text--size-md&quot;&amp;gt;{{ &apos;{{&apos; }} .Content }}&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/section&amp;gt;
&amp;lt;/article&amp;gt;
{{ &apos;{{&apos; }} end }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are using an alternative method of Platform UI &lt;a href=&quot;https://platformui.com/docs/layout/blocks/&quot;&gt;blocks&lt;/a&gt; this time. Instead of defining how many columns to display on the container, we can apply these classes to the actual block elements. We want each block to take up the full row width on mobile, but then switch to 50% width on large tablet viewports and higher. To do this, we can add &lt;code&gt;lg-tablet-up-6&lt;/code&gt; to the block.&lt;/p&gt;
&lt;p&gt;Platform UI has a great &lt;a href=&quot;https://platformui.com/docs/components/figure-hover/&quot;&gt;figure-hover&lt;/a&gt; component to display the product image. This allows us to display the alt text of the image as a caption.&lt;/p&gt;
&lt;p&gt;While displaying the product title, we can add a bottom border using the Platform UI &lt;a href=&quot;https://platformui.com/docs/utilities/borders/&quot;&gt;border&lt;/a&gt; utilities. Border utilities can determine the side, width, and color of borders.&lt;/p&gt;
&lt;p&gt;And just like before, we are using Hugo&apos;s &lt;code&gt;range&lt;/code&gt; function to loop through and output the product tags as Platform UI &lt;a href=&quot;https://platformui.com/docs/components/pill/&quot;&gt;pills&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Homepage&lt;/h3&gt;
&lt;p&gt;To finish up the theme, let&apos;s create a homepage!&lt;/p&gt;
&lt;p&gt;Our goal for the homepage will be to display a section for all categories and a few products in each. We&apos;ll also include a link to view all products within a single category. We can reuse most of what we learned already to accomplish this!&lt;/p&gt;
&lt;p&gt;Hugo sets the &lt;code&gt;~/hugo-store/themes/store-theme/layouts/index.html&lt;/code&gt; as the homepage.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{{ &apos;{{&apos; }} define &quot;main&quot; }}
&amp;lt;article class=&quot;block-container max-container pt-4&quot;&amp;gt;
  {{ &apos;{{&apos; }} range .Pages }}
  &amp;lt;section class=&quot;category w-100 flex flex--column flex--justify-center mb-4&quot;&amp;gt;
    &amp;lt;div class=&quot;category__header&quot;&amp;gt;
      &amp;lt;h2 class=&quot;flex flex--justify-center text--bold text--navy mb-0 pb-0&quot;&amp;gt;{{ &apos;{{&apos; }} .Title }}&amp;lt;/h2&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;div class=&quot;category__products&quot;&amp;gt;
      // Category products will go here!
      &amp;lt;div class=&quot;block-container w-100 flex--center-content mt-4 mb-6&quot;&amp;gt;
        &amp;lt;a class=&quot;button button--salmon text--white button--lg&quot; href=&quot;{{ &apos;{{&apos; }} .Permalink }}&quot;&amp;gt;
          View All {{ &apos;{{&apos; }} .Title }}
          &amp;lt;i class=&quot;pi-arrow-right&quot;&amp;gt;&amp;lt;/i&amp;gt;
        &amp;lt;/a&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/section&amp;gt;
  {{ &apos;{{&apos; }} end }}
&amp;lt;/article&amp;gt;
{{ &apos;{{&apos; }} end }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first &lt;code&gt;range&lt;/code&gt; we&apos;ll set up loops through pages within the &lt;code&gt;~/hugo-store/content&lt;/code&gt; folder. This will display a &lt;code&gt;&amp;lt;section&amp;gt;&lt;/code&gt; for each of our categories.&lt;/p&gt;
&lt;p&gt;Metadata from the category pages allows us to output the &lt;code&gt;.Title&lt;/code&gt; and &lt;code&gt;.Permalink&lt;/code&gt; of the category. We are linking to the category page using a Platform UI &lt;a href=&quot;https://platformui.com/docs/components/buttons/&quot;&gt;button&lt;/a&gt; and the button includes a Platform Icon. &lt;a href=&quot;https://platformui.com/icons/&quot;&gt;Platform Icons&lt;/a&gt; are a custom icon font included with Platform UI.&lt;/p&gt;
&lt;p&gt;Inside this &lt;code&gt;range&lt;/code&gt; we will add another &lt;code&gt;range&lt;/code&gt; to iterate through each of the product pages. Replace the comment &lt;code&gt;//Category products will go here!&lt;/code&gt; with the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;ul class=&quot;list block-container blocks tablet-up-2 lg-tablet-up-3 laptop-up-4&quot;&amp;gt;
  {{ &apos;{{&apos; }} range first 4 .Pages }}
  &amp;lt;li class=&quot;block&quot;&amp;gt;
    &amp;lt;div class=&quot;card m-2&quot;&amp;gt;
      {{ &apos;{{&apos; }} with .Params.image }}
      &amp;lt;img class=&quot;card__image&quot; src=&quot;{{ &apos;{{&apos; }} . }}&quot; alt=&quot;&quot; /&amp;gt;
      {{ &apos;{{&apos; }} end }}
      &amp;lt;div class=&quot;card__header flex flex--align-center flex--justify-between&quot;&amp;gt;
        &amp;lt;h3 class=&quot;product__name text--navy text--bold text--uppercase text--size-md mb-0&quot;&amp;gt;
          {{ &apos;{{&apos; }} .Params.title }}
        &amp;lt;/h3&amp;gt;
        &amp;lt;span class=&quot;product__price text--bold text--navy text--size-md&quot;&amp;gt; ${{ &apos;{{&apos; }} .Params.price }} &amp;lt;/span&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div class=&quot;card__content&quot;&amp;gt;
        &amp;lt;div class=&quot;flex&quot;&amp;gt;
          {{ &apos;{{&apos; }} with .Params.tags }} {{ &apos;{{&apos; }} range . }}
          &amp;lt;span class=&quot;pill mr-1&quot;&amp;gt; {{ &apos;{{&apos; }} . }} &amp;lt;/span&amp;gt;
          {{ &apos;{{&apos; }} end }} {{ &apos;{{&apos; }} end }}
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;product__description&quot;&amp;gt;{{ &apos;{{&apos; }} .Content }}&amp;lt;/div&amp;gt;
        &amp;lt;div class=&quot;product__button-container&quot;&amp;gt;
          &amp;lt;a class=&quot;button&quot; href=&quot;{{ &apos;{{&apos; }} .Permalink }}&quot;&amp;gt; View Details &amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/li&amp;gt;
  {{ &apos;{{&apos; }} end }}
&amp;lt;/ul&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This time we add a parameter to the &lt;code&gt;range&lt;/code&gt; function of &lt;code&gt;first 4&lt;/code&gt; - this only outputs the first four product pages. Just like on our other pages, we can list the products metadata and front matter.&lt;/p&gt;
&lt;p&gt;At this point, we should have a working website! There is one important piece missing from the store though, the actual store logic. Let&apos;s now explore how to add Snipcart!&lt;/p&gt;
&lt;h2&gt;Setting up Snipcart&lt;/h2&gt;
&lt;p&gt;Snipcart is a simple tool to add an online store to any website. As you would expect, you can enable visitors to pay for products online using a credit card. You can also enable promo codes and much more!&lt;/p&gt;
&lt;p&gt;Head over to Snipcart&apos;s website and &lt;a href=&quot;https://app.snipcart.com/register&quot;&gt;register&lt;/a&gt; for an account. Snipcart is a paid service for production sites, but provides free usage for development. So until you are ready to actually open up shop, you don&apos;t have to spend anything!&lt;/p&gt;
&lt;p&gt;After registering, browse to the &lt;a href=&quot;https://app.snipcart.com/dashboard/account/credentials&quot;&gt;API Keys section&lt;/a&gt; of your account to find your public test API key. This is used to connect your Hugo site to Snipcart.&lt;/p&gt;
&lt;h3&gt;Adding Dependencies&lt;/h3&gt;
&lt;p&gt;Snipcart requires surprisingly little to get running, we will just need to include the following bit of JavaScript in our footer.&lt;/p&gt;
&lt;p&gt;Open up &lt;code&gt;~/hugo-store/themes/store-theme/partials/footer.html&lt;/code&gt; and add JavaScript here:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- footer.html --&amp;gt;
&amp;lt;script src=&quot;cdn.jsdelivr.net/npm/@ritterim/platform-ui/dist/js/platform-ui.min.js&quot; crossorigin defer&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;
  window.SnipcartSettings = {
    publicApiKey: &apos;[YOUR API KEY]&apos;,
    loadStrategy: &apos;on-user-interaction&apos;,
  };

  (function () {
    var c, d;
    (d = (c = window.SnipcartSettings).version) != null || (c.version = &apos;3.0&apos;);
    var s, S;
    (S = (s = window.SnipcartSettings).currency) != null || (s.currency = &apos;usd&apos;);
    var l, p;
    (p = (l = window.SnipcartSettings).timeoutDuration) != null || (l.timeoutDuration = 2750);
    var w, u;
    (u = (w = window.SnipcartSettings).domain) != null || (w.domain = &apos;cdn.snipcart.com&apos;);
    var m, g;
    (g = (m = window.SnipcartSettings).protocol) != null || (m.protocol = &apos;https&apos;);
    var f, v;
    (v = (f = window.SnipcartSettings).loadCSS) != null || (f.loadCSS = !0);
    var E =
        window.SnipcartSettings.version.includes(&apos;v3.0.0-ci&apos;) ||
        (window.SnipcartSettings.version != &apos;3.0&apos; &amp;amp;&amp;amp;
          window.SnipcartSettings.version.localeCompare(&apos;3.4.0&apos;, void 0, { numeric: !0, sensitivity: &apos;base&apos; }) === -1),
      y = [&apos;focus&apos;, &apos;mouseover&apos;, &apos;touchmove&apos;, &apos;scroll&apos;, &apos;keydown&apos;];
    window.LoadSnipcart = o;
    document.readyState === &apos;loading&apos; ? document.addEventListener(&apos;DOMContentLoaded&apos;, r) : r();
    function r() {
      window.SnipcartSettings.loadStrategy
        ? window.SnipcartSettings.loadStrategy === &apos;on-user-interaction&apos; &amp;amp;&amp;amp;
          (y.forEach(function (t) {
            return document.addEventListener(t, o);
          }),
          setTimeout(o, window.SnipcartSettings.timeoutDuration))
        : o();
    }
    var a = !1;
    function o() {
      if (a) return;
      a = !0;
      let t = document.getElementsByTagName(&apos;head&apos;)[0],
        n = document.querySelector(&apos;#snipcart&apos;),
        i = document.querySelector(
          &apos;src[src^=&quot;&apos;
            .concat(window.SnipcartSettings.protocol, &apos;://&apos;)
            .concat(window.SnipcartSettings.domain, &apos;&quot;][src$=&quot;snipcart.js&quot;]&apos;)
        ),
        e = document.querySelector(
          &apos;link[href^=&quot;&apos;
            .concat(window.SnipcartSettings.protocol, &apos;://&apos;)
            .concat(window.SnipcartSettings.domain, &apos;&quot;][href$=&quot;snipcart.css&quot;]&apos;)
        );
      (n ||
        ((n = document.createElement(&apos;div&apos;)),
        (n.id = &apos;snipcart&apos;),
        n.setAttribute(&apos;hidden&apos;, &apos;true&apos;),
        document.body.appendChild(n)),
        $(n),
        i ||
          ((i = document.createElement(&apos;script&apos;)),
          (i.src = &apos;&apos;
            .concat(window.SnipcartSettings.protocol, &apos;://&apos;)
            .concat(window.SnipcartSettings.domain, &apos;/themes/v&apos;)
            .concat(window.SnipcartSettings.version, &apos;/default/snipcart.js&apos;)),
          (i.async = !0),
          t.appendChild(i)),
        !e &amp;amp;&amp;amp;
          window.SnipcartSettings.loadCSS &amp;amp;&amp;amp;
          ((e = document.createElement(&apos;link&apos;)),
          (e.rel = &apos;stylesheet&apos;),
          (e.type = &apos;text/css&apos;),
          (e.href = &apos;&apos;
            .concat(window.SnipcartSettings.protocol, &apos;://&apos;)
            .concat(window.SnipcartSettings.domain, &apos;/themes/v&apos;)
            .concat(window.SnipcartSettings.version, &apos;/default/snipcart.css&apos;)),
          t.prepend(e)),
        y.forEach(function (h) {
          return document.removeEventListener(h, o);
        }));
    }
    function $(t) {
      !E ||
        ((t.dataset.apiKey = window.SnipcartSettings.publicApiKey),
        window.SnipcartSettings.addProductBehavior &amp;amp;&amp;amp;
          (t.dataset.configAddProductBehavior = window.SnipcartSettings.addProductBehavior),
        window.SnipcartSettings.modalStyle &amp;amp;&amp;amp; (t.dataset.configModalStyle = window.SnipcartSettings.modalStyle),
        window.SnipcartSettings.currency &amp;amp;&amp;amp; (t.dataset.currency = window.SnipcartSettings.currency),
        window.SnipcartSettings.templatesUrl &amp;amp;&amp;amp; (t.dataset.templatesUrl = window.SnipcartSettings.templatesUrl));
    }
  })();
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;[YOUR API KEY]&lt;/code&gt; with the public test API key provided in your Snipcart account.&lt;/p&gt;
&lt;h3&gt;Add to Cart Button&lt;/h3&gt;
&lt;p&gt;The add to cart button could potentially be used in many places, so it would be a great time to build a Hugo partial.&lt;/p&gt;
&lt;p&gt;Browse to &lt;code&gt;~/hugo-store/themes/store-theme/layouts/partials/&lt;/code&gt; and create a file called &lt;code&gt;add-to-cart.html&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Inside this file, lets add the following button:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- add-to-cart.html --&amp;gt;
&amp;lt;button
 class=&quot;snipcart-add-item buy-button button button--salmon text--white my-3&quot;
 data-item-id=&quot;{{ &apos;{{&apos; }} .Params.id }}&quot;

 {{ &apos;{{&apos; }} if .Params.Image }}
  data-item-image=&quot;{{ &apos;{{&apos; }} .Params.Image }}&quot;
 {{ &apos;{{&apos; }} end }}

 data-item-name=&quot;{{ &apos;{{&apos; }} .Title }}&quot;
 data-item-price=&quot;{{ &apos;{{&apos; }} .Params.Price }}&quot;
 data-item-url=&quot;{{ &apos;{{&apos; }} .Permalink }}&quot;
 data-item-description=&quot;{{ &apos;{{&apos; }} .Content }}&quot;
&amp;gt;
  Add to Cart
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Snipcart utilizes data attributes on the add to cart button to discover what products get added to the cart. We can use the same product metadata and front matter params we set up to pass along this information. We are conditionally passing over an image, if it is present.&lt;/p&gt;
&lt;p&gt;With the partial added, it can now be included inside layout files. We will want to add this in a few spots: products displayed on the home page, category list page and the product&apos;s single page.&lt;/p&gt;
&lt;p&gt;Open &lt;code&gt;~/hugo-store/themes/store-theme/layouts/index.html&lt;/code&gt; and add the partial beside the &quot;View Details&quot; button.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;product__button-container&quot;&amp;gt;
  {{ &apos;{{&apos; }} partial &quot;add-to-cart&quot; . }}
  &amp;lt;a class=&quot;button&quot; href=&quot;{{ &apos;{{&apos; }} .Permalink }}&quot;&amp;gt; View Details &amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The exact same thing can happen inside &lt;code&gt;~/hugo-store/themes/store-theme/layouts/default/list.html&lt;/code&gt; for category pages.&lt;/p&gt;
&lt;p&gt;Finally, let&apos;s add the partial on the single product page, by opening &lt;code&gt;~/hugo-store/themes/store-theme/layouts/default/single.html&lt;/code&gt; and including it after the &lt;code&gt;.Content&lt;/code&gt; section:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;text--size-md&quot;&amp;gt;{{ &apos;{{&apos; }} .Content }}&amp;lt;/div&amp;gt;

{{ &apos;{{&apos; }} partial &quot;add-to-cart&quot; . }}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when visitors click the &quot;Add to Cart&quot; button, the product will be added to the cart. This will also open the Snipcart drawer to display all of the cart information.&lt;/p&gt;
&lt;h3&gt;View Cart Button&lt;/h3&gt;
&lt;p&gt;We want to include a button that allows visitors to open the cart at anytime. This can easily be added to the theme by adding a button inside the &lt;code&gt;~/hugo-store/themes/store-theme/layouts/default/_baseof.html&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Right before where we include the &lt;code&gt;footer&lt;/code&gt; partial, let&apos;s add the button like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;snipcart-checkout pos-fix pin-bottom pin-right mr-4 mb-4&quot;&amp;gt;
  &amp;lt;button class=&quot;snipcart-summary button button--lg button--salmon text--white&quot;&amp;gt;
    &amp;lt;span class=&quot;mr-2 flex flex--align-center&quot;&amp;gt;
      &amp;lt;span class=&quot;ml-2&quot;&amp;gt;Cart: &amp;lt;/span&amp;gt;
    &amp;lt;/span&amp;gt;
    &amp;lt;span class=&quot;snipcart-total-price&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With Platform UI&apos;s &lt;a href=&quot;https://platformui.com/docs/utilities/position/&quot;&gt;position&lt;/a&gt; utilities, we can fix the button to the bottom right of the viewport with &lt;code&gt;pos-fix pin-bottom pin-right&lt;/code&gt; classes.&lt;/p&gt;
&lt;p&gt;Snipcart&apos;s JavaScript will update the &lt;code&gt;snipcart-total-price&lt;/code&gt; to display the current total cart cost. Now clicking the button will open the cart, allowing visitors to checkout!&lt;/p&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;With Snipcart now integrated into our Hugo site, we have a fully-functioning online store! We could expand the store in a few different ways as well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Options for product sizes, colors, and more.&lt;/li&gt;
&lt;li&gt;Better navigation to allow for easier browsing around.&lt;/li&gt;
&lt;li&gt;Store search functionality.&lt;/li&gt;
&lt;li&gt;A footer that provides more information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I definitely encourage exploring things further, but this should be a great baseline example for setting up an online store with Platform UI, Hugo, and Snipcart.&lt;/p&gt;
&lt;p&gt;If you would like to view the completed code, please check it out over on &lt;a href=&quot;https://github.com/mrtrimble/hugo-store&quot;&gt;Github&lt;/a&gt;!&lt;/p&gt;
</content:encoded></item><item><title>Animated Scroll Effects</title><link>https://ryantrimble.com/blog/animated-scroll-effects/</link><guid isPermaLink="true">https://ryantrimble.com/blog/animated-scroll-effects/</guid><description>Re-upload of an article I originally published on RIMdev.io, discussing how to use GSAP for scroll-triggered animations</description><pubDate>Wed, 18 May 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m a huge fan of animation on the web, especially when it comes to user interaction. A simple way to include such a thing on webpages is by triggering some sort of effect when scrolling.&lt;/p&gt;
&lt;p&gt;Elements fading in and out to tell a story. Background colors changing to differentiate page sections. Cards and content popping in at various points on the page. These types of things can enhance the user experience on your page.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API&quot;&gt;intersection observer API&lt;/a&gt; provides a vanilla JavaScript approach to adding scroll effects by triggering functions when elements intersect certain points of the viewport. Intersection observer can be difficult to work with, so a library such as &lt;a href=&quot;https://michalsnik.github.io/aos/&quot;&gt;Animate on scroll&lt;/a&gt; may make things simpler.&lt;/p&gt;
&lt;p&gt;My personal favorite library to animate with is the &lt;a href=&quot;https://greensock.com/&quot;&gt;GreenSock Animation Platform&lt;/a&gt;. GSAP is useful for all sorts of animations, including scroll triggered effects.&lt;/p&gt;
&lt;p&gt;To show this off, let’s build a neat effect I came across on a website recently! The website included a hero section containing text. As you scroll the page, the text scales to highlight the importance of the message.&lt;/p&gt;
&lt;p&gt;For this demo I have created a &lt;a href=&quot;https://codepen.io/mrtrimble/pen/gOvLPgM&quot;&gt;Codepen&lt;/a&gt; to follow along with. I already included HTML, CSS, GSAP, and the ScrollTrigger plugin, so no need to set anything up! We’ll focus on the JavaScript to find out that with a few lines of code, we can build a neat scroll trigger animation.&lt;/p&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;p&gt;One of the key things GSAP provides as a library is the ability to create animations based on a &lt;strong&gt;timeline&lt;/strong&gt;. This enables much more complex animations than what CSS keyframes provide. To create a GSAP timeline, we can initialize like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const tl = new gsap.timeline();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we are able to describe what animations should occur within that timeline - we can do that with &lt;strong&gt;tweens&lt;/strong&gt;. Tweens explain what the animation should do be&lt;strong&gt;tween&lt;/strong&gt; the start and end of the timeline.&lt;/p&gt;
&lt;p&gt;Tweens take in two key parameters:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The element you want to animate.&lt;/li&gt;
&lt;li&gt;An object explaining how the element will animate, including CSS properties to animate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can include as many tweens as needed to complete the animation. GSAP includes three different types of tweens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.to()&lt;/code&gt; - animates an element &lt;em&gt;to&lt;/em&gt; something.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.from()&lt;/code&gt; - animates an element &lt;em&gt;from&lt;/em&gt; something.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.fromTo()&lt;/code&gt; - animates an element &lt;em&gt;from&lt;/em&gt; one thing &lt;em&gt;to&lt;/em&gt; another.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pretty straightforward! To create tweens, we can tack them onto the timeline. To make things even easier, we can chain tweens together.&lt;/p&gt;
&lt;p&gt;So in our example, we want to create a tween that scales the &lt;code&gt;.scale-text&lt;/code&gt; element to a large size:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const tl = new gsap.timeline();

tl.to(&apos;.scale-text&apos;, {
  scale: 10,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The animation should trigger, however that is not quite what we want yet - we want this to happen on scroll. This is where the GSAP ScrollTrigger plugin comes in!&lt;/p&gt;
&lt;p&gt;Inside where we initialized our timeline, we can configure ScrollTrigger:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const tl = new gsap.timeline({
  scrollTrigger: {
    trigger: &apos;.hero&apos;,
    start: &apos;top top&apos;,
    scrub: 1,
  },
});

tl.to(&apos;.scale-text&apos;, {
  scale: 10,
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;scrollTrigger&lt;/code&gt; object contains some configuration properties:
&lt;code&gt;trigger&lt;/code&gt; - specifies what element will trigger the animation.
&lt;code&gt;start&lt;/code&gt; - tells GSAP at what point to start the animation. In our example it is when the top of the element reaches the top of the viewport.
&lt;code&gt;scrub&lt;/code&gt; - enables the scrollbar to become the scrubber for the animation. Setting this as &lt;code&gt;true&lt;/code&gt; will enable this, but specifying a duration will smooth out an animation.&lt;/p&gt;
&lt;p&gt;There is a lot of ways to configure ScrollTrigger. I recommend checking out the &lt;a href=&quot;https://greensock.com/scrolltrigger/&quot;&gt;GSAP ScrollTrigger documentaiton page&lt;/a&gt; to find out more!&lt;/p&gt;
&lt;p&gt;Now, our animation may not look like it is doing anything, but when you start scrolling you should see it kick off. The text &quot;empowering people&quot; will scale up in size. Our scroll trigger animation is working and we did that with only a single tween too!&lt;/p&gt;
&lt;p&gt;Here are a couple of small enhancements we can add as well:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const tl = new gsap.timeline({
  scrollTrigger: {
    trigger: &apos;.hero&apos;,
    start: &apos;top top&apos;,
    scrub: 1,
  },
});

tl.to(&apos;.scale-text&apos;, {
  scale: 10,
})
  .to(
    &apos;.hero&apos;,
    {
      opacity: 0,
    },
    &apos;&amp;lt;25%&apos;
  )
  .to(
    &apos;.cards&apos;,
    {
      opacity: 1,
      duration: 1,
      y: 0,
      stagger: 0.5,
      ease: &apos;back.out(1.7)&apos;,
    },
    &apos;&amp;lt;25%&apos;
  );
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I added two more tweens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first will fade out the &lt;code&gt;.hero&lt;/code&gt; element as it scrolls out of view.&lt;/li&gt;
&lt;li&gt;The second will pop the cards into view as they scroll.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This adds slightly more interesting effects to the page. There are a couple of other fun things to note happening as well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;&amp;lt;25%&lt;/code&gt; part is a positional timing parameter that tells the tween when to start. Tweens generally start right after another, but with this we can tell the tween to start sooner or later in the timeline.&lt;/li&gt;
&lt;li&gt;GSAP can animate a single element or an array of elements, such as our &lt;code&gt;.card&lt;/code&gt; elements. We don&apos;t want all the cards to animate in at the same time, so we include a &lt;code&gt;stagger&lt;/code&gt; property to make each have a delay.&lt;/li&gt;
&lt;li&gt;Easing is a method of smoothing out animations and can make tweens feel more natural while transitioning. GSAP can handle easing with the &lt;code&gt;ease&lt;/code&gt; property and has several built in easing functions. You can play with these eases with the &lt;a href=&quot;https://greensock.com/ease-visualizer/&quot;&gt;ease visualizer&lt;/a&gt; and find out which is best for your animations.&lt;/li&gt;
&lt;li&gt;GSAP also includes shorthand properties such as &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; that correspond with the CSS &lt;code&gt;transform&lt;/code&gt; property.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Final Result&lt;/h3&gt;
&lt;p&gt;So there you have it, a super neat animated scroll trigger effect that is only a few lines of JavaScript!&lt;/p&gt;
&lt;p&gt;&amp;lt;iframe
height=&quot;500&quot;
style=&quot;width: 100%;&quot;
scrolling=&quot;no&quot;
title=&quot;Finished - Scroll Trigger Demo&quot;
src=&quot;https://codepen.io/mrtrimble/embed/zYRoGgZ/7545ac69b915f060e1585b886719a856?default-tab=result&quot;
frameborder=&quot;no&quot;
loading=&quot;lazy&quot;
allowtransparency=&quot;true&quot;
allowfullscreen=&quot;true&quot;&lt;/p&gt;
&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;p&gt;See the Pen{&apos; &apos;}
&amp;lt;a href=&quot;https://codepen.io/mrtrimble/pen/zYRoGgZ/7545ac69b915f060e1585b886719a856&quot;&amp;gt;Finished - Scroll Trigger Demo&amp;lt;/a&amp;gt;{&apos; &apos;}
by Ryan Trimble (&amp;lt;a href=&quot;https://codepen.io/mrtrimble&quot;&amp;gt;@mrtrimble&amp;lt;/a&amp;gt;) on &amp;lt;a href=&quot;https://codepen.io&quot;&amp;gt;CodePen&amp;lt;/a&amp;gt;.
&amp;lt;/iframe&amp;gt;&lt;/p&gt;
&lt;p&gt;(For best results, view on &lt;a href=&quot;https://codepen.io/mrtrimble/pen/zYRoGgZ/7545ac69b915f060e1585b886719a856&quot;&gt;Codepen&lt;/a&gt;)&lt;/p&gt;
</content:encoded></item></channel></rss>