<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: James Robert Lund III </title>
    <description>The latest articles on DEV Community by James Robert Lund III  (@lundjrl).</description>
    <link>https://dev.to/lundjrl</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1078446%2F83831fd5-f4ec-4835-a768-407a94c2e2b5.png</url>
      <title>DEV Community: James Robert Lund III </title>
      <link>https://dev.to/lundjrl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lundjrl"/>
    <language>en</language>
    <item>
      <title>It took me a long time to settle on a "good" note taking system. See what I have to say!</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Mon, 14 Apr 2025 12:57:17 +0000</pubDate>
      <link>https://dev.to/lundjrl/it-took-me-a-long-time-to-settle-on-a-good-note-taking-system-see-what-i-have-to-say-3o43</link>
      <guid>https://dev.to/lundjrl/it-took-me-a-long-time-to-settle-on-a-good-note-taking-system-see-what-i-have-to-say-3o43</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b" class="crayons-story__hidden-navigation-link"&gt;✍🏼 How I Take Notes As A Dev&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/lundjrl" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1078446%2F83831fd5-f4ec-4835-a768-407a94c2e2b5.png" alt="lundjrl profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/lundjrl" class="crayons-story__secondary fw-medium m:hidden"&gt;
              James Robert Lund III 
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                James Robert Lund III 
                
              
              &lt;div id="story-author-preview-content-2029367" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/lundjrl" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1078446%2F83831fd5-f4ec-4835-a768-407a94c2e2b5.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;James Robert Lund III &lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 13 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b" id="article-link-2029367"&gt;
          ✍🏼 How I Take Notes As A Dev
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/softwaredevelopment"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwaredevelopment&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/documentation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;documentation&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/excalidraw"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;excalidraw&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


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

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

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

&lt;/div&gt;


</description>
      <category>softwaredevelopment</category>
      <category>documentation</category>
      <category>webdev</category>
      <category>excalidraw</category>
    </item>
    <item>
      <title>✍🏼 How I Take Notes As A Dev</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Sun, 13 Apr 2025 15:50:01 +0000</pubDate>
      <link>https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b</link>
      <guid>https://dev.to/lundjrl/how-i-take-notes-as-a-dev-155b</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; I now use these things:&lt;br&gt;
&lt;a href="https://obsidian.md/download" rel="noopener noreferrer"&gt;Obsidian&lt;/a&gt;&lt;br&gt;
&lt;a href="https://obsidian.md/plugins?id=obsidian-excalidraw-plugin" rel="noopener noreferrer"&gt;Obsidian Excalidraw Plugin&lt;/a&gt;&lt;br&gt;
&lt;a href="https://obsidian.md/plugins?id=obsidian-git" rel="noopener noreferrer"&gt;Obsidian Git Plugin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My full config 👉🏼 &lt;a href="https://github.com/lundjrl/articles/tree/main/obsidian" rel="noopener noreferrer"&gt;Obsidian Config&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  How we got here
&lt;/h1&gt;

&lt;p&gt;&lt;br&gt;
I think every dev is on the lookout for a better way to organize notes and convey their ideas. Each dev has their own way of writing notes and staying organized which is totally fine. This article talks about what works for me and if it works for you, awesome! 🎉&lt;/p&gt;



&lt;p&gt;Let's get into the tools I've used and where I ended up. I was using Excalidraw on the daily.&lt;/p&gt;

&lt;p&gt;Excalidraw is a great tool for making diagrams. However, I wanted to save diagrams and access them on any machine I needed to. This was a problem because I needed to make sure these files were up to date and backed up on a cloud. &lt;/p&gt;

&lt;p&gt;So I needed a cloud... 🤔 why not use git and host these files on GitHub? It's free and I can access my stuff on any device that has Git. So off I went, saving notes to a folder on my computer and backing changes up to Git. The only issue is I had to manually back stuff up. &lt;/p&gt;

&lt;p&gt;Wouldn't it be good to backup when I saved a file?&lt;/p&gt;

&lt;p&gt;That got me looking into a smarter notes app, something that could automatically back up to a cloud, work on different operating systems, and something that allowed me to own my data. &lt;/p&gt;

&lt;h3&gt;
  
  
  Things I've Tried
&lt;/h3&gt;

&lt;p&gt;I tried using the notes app on MacOS but that's not compatible on other machines I use. Especially Ubuntu 🐧&lt;/p&gt;

&lt;p&gt;I've tried using evernote but it seemed like too much noise for what I needed.&lt;/p&gt;

&lt;p&gt;I tried using &lt;a href="https://www.any.do/" rel="noopener noreferrer"&gt;anydo&lt;/a&gt; which worked for awhile and has support for multiple platforms but I needed something richer than a TODO app. Something that let me create diagrams and have control over my data.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Current Solution 💡
&lt;/h2&gt;

&lt;p&gt;It's not for everyone, but over the past year I've really enjoyed using &lt;strong&gt;Obsidian&lt;/strong&gt;. I have it configured to backup my notes on save and push to a remote git repo. &lt;/p&gt;

&lt;p&gt;This perfectly satisfies my fulfillment criteria:&lt;br&gt;
    1. Cloud-based backups&lt;br&gt;
    2. Automatic backup on save&lt;br&gt;
    3. Excalidraw support&lt;br&gt;
    4. Community support&lt;br&gt;
    5. Owning my data&lt;br&gt;
    6. Accessing notes between machines&lt;/p&gt;

&lt;p&gt;I don't want to reinvent the wheel, so if you're interested, please checkout &lt;a href="https://forum.obsidian.md/t/the-easiest-way-to-setup-obsidian-git-to-backup-notes/51429" rel="noopener noreferrer"&gt;this video&lt;/a&gt;. It'll get you the majority of the way there.&lt;/p&gt;

&lt;p&gt;Outside of that, let's talk plugins.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔌 Bridging The Gap With Plugins
&lt;/h3&gt;

&lt;p&gt;In addition to the git plugin, I also installed Excalidraw, advanced canvas, CSV table, and emojis.&lt;/p&gt;

&lt;p&gt;This works for me since I'm used to Excalidraw, now I get to have my notes in 1 place! 🎉&lt;/p&gt;

&lt;p&gt;👇🏼 Example of a simple user form in excalidraw.&lt;/p&gt;

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

&lt;p&gt;I also get to read CSV outputs and leave comments on them (super useful for back-end work I do).&lt;/p&gt;

&lt;p&gt;The Canvas plugin lets me style my canvas'. This might be a bit redundant since I have the Excalidraw plugin too but it's good for linking to in-depth notes on an ERD (entity relationship diagram).&lt;/p&gt;

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

&lt;p&gt;I'll add more as time goes on but this works for me now 🙂&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Closing Out
&lt;/h2&gt;

&lt;p&gt;That's it! &lt;/p&gt;

&lt;p&gt;Would you try Obsidian? Are their any plugins you think I should try? Let me know in the comments below!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;




&lt;p&gt;&lt;a href="https://github.com/lundjrl/articles/tree/main/obsidian" rel="noopener noreferrer"&gt;Obsidian Config&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Photo by &lt;a href="https://unsplash.com/@jeztimms?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Jez Timms&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/building-interior-vTKLujPJecw?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>documentation</category>
      <category>webdev</category>
      <category>excalidraw</category>
    </item>
    <item>
      <title>Taking a short hiatus</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Mon, 13 May 2024 18:27:13 +0000</pubDate>
      <link>https://dev.to/lundjrl/taking-a-short-hiatus-5bkm</link>
      <guid>https://dev.to/lundjrl/taking-a-short-hiatus-5bkm</guid>
      <description>&lt;p&gt;Hey all!&lt;/p&gt;

&lt;p&gt;Thank you for the love and support over the past year. I wasn't expecting to get this much out of dev.to but certainly glad I started 😄&lt;/p&gt;

&lt;p&gt;I'm gonna take a break for a few months. There's a personal project I wanna focus on instead of writing articles. I'm sure I'll write some on the project once it's in a MVP stage. It'll be open source too! I really hope you try it out!&lt;/p&gt;

&lt;p&gt;Thanks again for the support over the past year, until we meet again ✌️&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;James&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Reflecting On My Programming Career</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Tue, 23 Apr 2024 13:48:20 +0000</pubDate>
      <link>https://dev.to/lundjrl/reflecting-on-my-programming-career-51b6</link>
      <guid>https://dev.to/lundjrl/reflecting-on-my-programming-career-51b6</guid>
      <description>&lt;p&gt;It's been a long 5 years.&lt;/p&gt;

&lt;p&gt;5 years of stand-ups, posture issues, fixing staging and production sites, and code, so much code. It's hard to imagine that it's been that long, it seems like ages ago. &lt;/p&gt;

&lt;p&gt;From starting my career as a back-end Python engineer working on healthcare websites to building full-stack applications with Typescript, I've seen a few things and led myself astray along the way. &lt;/p&gt;

&lt;p&gt;One of the ways I disadvantaged myself was to be a "yes man".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🚨 Spoiler Alert - don't do that.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I took any opportunity I could to prove myself and advance my career. Build my skills and keep my clients happy. I wanted to be known as a competent engineer. I wanted people to want me on their team. I wanted attention and to be recognized for my efforts, no matter what.&lt;/p&gt;

&lt;p&gt;I would work extra hours during the day or weekends to keep people happy. Anyone besides myself or my family. &lt;/p&gt;

&lt;p&gt;Stretching myself like this would only get me so far. I voluntarily did this to make my clients happy or to make up for a fumble I had during a meeting earlier in the week. I felt like I owed someone something.&lt;/p&gt;

&lt;p&gt;As long as my clients were happy, I was happy. Or at least that's what I told myself for years. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;😬 Yikes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I was becoming the person I set out &lt;strong&gt;NOT&lt;/strong&gt; to be, the workaholic programmer who only made time for work. Work work work. A cog in the machine that only stops to rest. &lt;/p&gt;

&lt;p&gt;I didn't stop and think about the negative impact my workaholic tendencies would have on my mental health and family. They craved more attention from me. Attention that I denied them so I could focus on developing the skills I thought I needed for the future.&lt;/p&gt;

&lt;p&gt;I was right on some of the skills and wrong on others. Let me explain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things I didn't need:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Google Cloud Certifications&lt;/li&gt;
&lt;li&gt;Saying yes to all demands&lt;/li&gt;
&lt;li&gt;Influencer trends (Rust, Flutter, AlpineJS, RedwoodJs, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Google Cloud Certifications
&lt;/h4&gt;

&lt;p&gt;Looking back, I feel like this wasn't the move. I was studying to earn a Google Developer certification to show to companies that I knew Google Cloud. What does that even mean? Knowing "Google Cloud" is a HUGE goal for anyone to learn (same goes for Azure, AWS, etc), I didn't set the right expectations for myself. &lt;/p&gt;

&lt;p&gt;A better use of my time would've been to better understand the exact features of GCC that would've benefited my projects. At the time, I was using Firebase on every project to speed up development. Learning more about GC Cloud Functions, App Engine, Storage, and IAM would've pushed me further in my career besides just knowing the basics. &lt;/p&gt;

&lt;p&gt;Couldn't the cert help me with those things? Yes, but it probably was overkill. &lt;/p&gt;

&lt;h4&gt;
  
  
  Saying Yes
&lt;/h4&gt;

&lt;p&gt;This was my biggest mistake.&lt;/p&gt;

&lt;p&gt;I was eager to prove myself and fearful of letting people down. I wouldn't turn someone down because it was an opportunity for me to learn and get more experience. &lt;/p&gt;

&lt;p&gt;It was easy for me to feel like this was progressing my career but it lead to sooner burnout. That sooner burnout hindered my performance and my drive to learn. &lt;/p&gt;

&lt;h4&gt;
  
  
  Influencer Trends
&lt;/h4&gt;

&lt;p&gt;There's new technologies coming out all the time and I felt like it was my responsibility to keep up with the trends. There's some truth to that but I was a bit starry-eyed thinking I should learn everything tech-bros were talking about.&lt;/p&gt;

&lt;p&gt;Is it okay to try new things? Absolutely. &lt;/p&gt;

&lt;p&gt;Is it okay to force yourself to try new things when you should be around those who care about you? For me, no.&lt;/p&gt;

&lt;p&gt;The reality was that I just needed to stick with the things that employers were looking for. For my specific line of work, this would mostly be React, React Native, JS/TS, Firebase, HTML, CSS, etc. A framework, a language, and the tools to build full stack apps. &lt;/p&gt;

&lt;p&gt;That's what helped me get the positions I was in, understanding tools and having the skills that employers were looking for.&lt;/p&gt;

&lt;p&gt;In my experience, employers weren't looking for a full-stack dev that had a Google Cloud certification or knowledge of Rust. They were looking for someone who knew one of the big three front-end frameworks (React, Angular, Vue) and could write nodejs code. Also someone who could adapt to older/different codebases than current standards.&lt;/p&gt;

&lt;p&gt;At the times I was applying for new opportunities, I never saw positions that were looking for Svelte, Rust, RedwoodJs, etc experience. Mainly full-stack positions that asked if you could provide value with knowing more common technologies.&lt;/p&gt;

&lt;p&gt;Rust is a neat language but it doesn't have much use for me in my area of webdev. I typically work on full-stack apps that use Typescript. Typically a CMS or CMS-like back-end and React front-end. Why should I learn Rust?&lt;/p&gt;

&lt;p&gt;It's not like I was building CLI tools or infrastructure to support my web apps, I just thought Rust was cool. I thought it would give me an edge.&lt;/p&gt;

&lt;p&gt;And let me stop for a moment, there is nothing wrong with learning new things. There is nothing wrong with learning Rust or anything on this list. My point is I was forcing myself to learn something that I didn't need to learn. I thought I was advancing my career but I was just holding myself back by not investing my time into the things that companies would want me to do (mostly front-end stuff at this time). &lt;/p&gt;

&lt;p&gt;What actually gave me energy to continue learning wasn't to force myself to learn, it was to spend more time with my family and recharge. After all, the point of me working so much was to have more family time by being better at my job, wasn't it?&lt;/p&gt;

&lt;p&gt;But that's enough of the negative, let's focus on the things that pushed me along my career. &lt;/p&gt;

&lt;h3&gt;
  
  
  Things that helped me:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Communication&lt;/li&gt;
&lt;li&gt;Typescript/Javascript&lt;/li&gt;
&lt;li&gt;CSS/HTML etc&lt;/li&gt;
&lt;li&gt;Saying no&lt;/li&gt;
&lt;li&gt;Establishing boundaries&lt;/li&gt;
&lt;li&gt;Learning to protect those boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Communication
&lt;/h4&gt;

&lt;p&gt;To most of you, this is a no-brainer, but I learned it the hard way. Instead of communicating my hiccups to my team, I'd silently iron all bugs in my way. "I can fix anything!" I'd say to myself, not considering that I could save time by pair programming with someone else. &lt;/p&gt;

&lt;p&gt;What happens when you can't fix something and your deadline is coming up? Panic. &lt;/p&gt;

&lt;p&gt;What happens when you can't fix something, your deadline is coming up, and you leverage your team? More often than not, the team will help you get out of your situation. Either by helping you get unstuck, developing the work with you, or communicating with the client that we should push back the deadline. &lt;/p&gt;

&lt;h4&gt;
  
  
  Typescript/Javascript
&lt;/h4&gt;

&lt;p&gt;Another no-brainer for those who work in webdev. Looking back, I wish I focused on Typescript a lot sooner. I'd have more experience and would have more job opportunities. Most places are asking for TS experience these days.&lt;/p&gt;

&lt;p&gt;I'd also grow faster. If I implemented TS sooner, more of my legacy projects would be more maintainable because my code would've been more intentional with its data flow. &lt;/p&gt;

&lt;h4&gt;
  
  
  CSS/HTML
&lt;/h4&gt;

&lt;p&gt;If you work front-end, you need to know these. I was &lt;em&gt;decent&lt;/em&gt; at it but for most of my career I'd use divs for everything. Who cares about SEO or accessibility anyway? Yeah, totally not my attitude these days. &lt;/p&gt;

&lt;h4&gt;
  
  
  Saying no
&lt;/h4&gt;

&lt;p&gt;If you're having a hard time, this might be your skeleton key. Learning to say no and protecting my boundaries was a &lt;strong&gt;game changer&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;When I learned how to protect my boundaries, I was able to properly set expectations with my team. Expectations that were manageable led me to get more sleep, keep work at work, generally feel less stressed, and not feel burnt out as quickly.&lt;/p&gt;

&lt;p&gt;You have to swallow your pride to do this. Accept that you can't do everything and you should leverage your team when you need them. They're there to help you, as you are to them.&lt;/p&gt;




&lt;p&gt;These things actually helped me progress in my career. The cool thing was they didn't take much time outside of work. They're mostly day-to-day things that made my life easier. And with my life easier, I was able to make more time for my family. &lt;/p&gt;

&lt;p&gt;What also helps motivate me is having a sense of community. Something outside of my job that connects me with others who feel the same way I do. For me, there's a non-profit organization called GRWebDev that hosts events in my local area. &lt;/p&gt;

&lt;p&gt;Maybe there's an org like that around you too ☺️&lt;/p&gt;




&lt;p&gt;Thanks for reading! If you liked this post please give it a heart or another emoji. Did this post help you manage learning and your mental health? Or do you have some tips from your personal journey? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>mentalhealth</category>
      <category>webdev</category>
      <category>development</category>
      <category>career</category>
    </item>
    <item>
      <title>🐺 REST APIs with Elysia.js 🌿</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Mon, 25 Mar 2024 12:56:53 +0000</pubDate>
      <link>https://dev.to/lundjrl/rest-apis-with-elysiajs-37pl</link>
      <guid>https://dev.to/lundjrl/rest-apis-with-elysiajs-37pl</guid>
      <description>&lt;p&gt;&lt;br&gt;
Hey API Dev, tired of building express apps that don't perform well under high loads? Want something that feels a bit cleaner and modern to build your next multi-million dollar project? &lt;/p&gt;

&lt;p&gt;You may have heard of &lt;a href="https://dev.to/lundjrl/bun-a-faster-javascript-runtime-jph"&gt;Bun&lt;/a&gt;, the newest JS runtime before, but have you heard of an ergonomic developer-friendly API framework that uses Bun?&lt;/p&gt;

&lt;p&gt;If not, this article is for you 🎉&lt;/p&gt;

&lt;p&gt;There's a few contenders out there but the one that really stood out to me is Elysia.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  What is Elysia?
&lt;/h2&gt;

&lt;p&gt;Elysia is a HTTP API framework written on Bun with developer experience being the main motivation of the framework. &lt;/p&gt;

&lt;p&gt;Essentially, a faster Express.js replacement.&lt;/p&gt;

&lt;p&gt;Elysia is set up for you to write functions and returns for your API. Need to send a response to the client? Just return your data in the callback function. No need to rely on req/res explicitly. &lt;/p&gt;

&lt;p&gt;A basic Elysia endpoint could look like this:&lt;/p&gt;

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

&lt;p&gt;Which will return a 200 and the string &lt;code&gt;Test&lt;/code&gt; inside the response body.&lt;/p&gt;

&lt;p&gt;The implementation syntax looks similar to express but cleaner, in my opinion.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Elysia Paths
&lt;/h3&gt;

&lt;p&gt;You can leverage all the regular HTTP Methods and also add your own:&lt;/p&gt;

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

&lt;p&gt;Or if you don't care about the method, you can use &lt;code&gt;.all&lt;/code&gt; instead of &lt;code&gt;.get .post&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;You can also handle 404 errors like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfgqkjbjwzq0sp3aefyz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfgqkjbjwzq0sp3aefyz.png" alt="Code snippet showing how to handle 404 errors in Elysia" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Need dynamic paths? No worries:&lt;/p&gt;

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

&lt;p&gt;Need multiple dynamic variables on an endpoint? They got you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3e98w2r4unucftpspk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3e98w2r4unucftpspk3.png" alt="Code snippet of how to use dynamic variables in an endpoint" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What about wildcards? Don't worry about it:&lt;/p&gt;

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

&lt;p&gt;As you can see, Elysia has a lot of power baked in. But what about returning data? &lt;/p&gt;

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

&lt;h3&gt;
  
  
  Elysia's Handler Function
&lt;/h3&gt;

&lt;p&gt;Those callbacks you saw in the code-snippets are the "handler". A handler is a callback function as the second argument in an endpoint. As you saw, we can extract params, path, and the request context by destructuring the request object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbm7kynsrd9je7nv2kxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbm7kynsrd9je7nv2kxs.png" alt="Code snippet on how to descructure the request object in HTTP requests" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The request object isn't lost to us tho. To alter request headers or redirects, we can leverage &lt;code&gt;set&lt;/code&gt; like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw6ck9c4rm7yfjelw9kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw6ck9c4rm7yfjelw9kn.png" alt="Code snippet showing how to use the request object in Elysia" width="800" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More info on request context &lt;a href="https://elysiajs.com/essential/context.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Elysia Responses
&lt;/h3&gt;

&lt;p&gt;Elysia will automatically create the response object for you from whatever you return in your handler function.&lt;/p&gt;

&lt;p&gt;If you want, you can also return a &lt;code&gt;new Response()&lt;/code&gt; object and Elysia will handle it.&lt;/p&gt;

&lt;p&gt;Want to move your routes to different files? Leverage Elysia's &lt;a href="https://elysiajs.com/essential/plugin.html" rel="noopener noreferrer"&gt;plugin system&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Need some additional functionality? Checkout the &lt;a href="https://elysiajs.com/plugins/overview.html" rel="noopener noreferrer"&gt;community&lt;/a&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Life Cycle Events
&lt;/h3&gt;

&lt;p&gt;I won't go into too much detail here but this is an illustration of what's going on under the hood.&lt;/p&gt;

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

&lt;p&gt;When a request is made and accepted, the system will transform the request to the object we receive in our handler function. &lt;/p&gt;

&lt;p&gt;If we have validation in place, that occurs next. The handler function is executed and returns data in form of a HTTP Response.&lt;/p&gt;

&lt;p&gt;If this all makes sense, let's move on to a demo!&lt;br&gt;
 &lt;/p&gt;

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

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

&lt;h2&gt;
  
  
  API Demo
&lt;/h2&gt;

&lt;p&gt;💻 &lt;strong&gt;Completed code &lt;a href="https://github.com/lundjrl/elysia-article" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's start by creating a new Elysia app!&lt;/p&gt;

&lt;p&gt;You can easily create a new Elysia app by running &lt;code&gt;bun create elysia app&lt;/code&gt; in your terminal where "app" is the name of your new application. If you don't have Bun installed, you can install it via curl &lt;code&gt;curl -fsSL https://bun.sh/install | bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, cd into the new directory and run the app with &lt;code&gt;bun run dev&lt;/code&gt;. A dev server should start up at &lt;code&gt;localhost:3000&lt;/code&gt;.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Building Our Endpoints
&lt;/h3&gt;

&lt;p&gt;For this demo, we're going to be connecting to the Trefle plant API. This API contains a very wide variety of plants and we'll be performing get requests for the purpose of this demo.&lt;/p&gt;

&lt;p&gt;We're going to make a few endpoints to get our plant data.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Get 30 plants
2. Search by query
3. Search by plant genus
4. Search by plant species
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;First off, we'll add those endpoints to &lt;code&gt;index.ts&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Don't worry about the handler function for now, we'll add those later after we complete the next step.&lt;/p&gt;

&lt;p&gt;Next, let's create the file that'll contain these functions in &lt;code&gt;src/api.ts&lt;/code&gt;. Add these functions below:&lt;/p&gt;

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

&lt;p&gt;But before we can attach these functions to the plant API, we need to get a token to authenticate. If you create an account &lt;a href="https://trefle.io/profile" rel="noopener noreferrer"&gt;here&lt;/a&gt;, you'll be granted with an API token to use their API.&lt;/p&gt;

&lt;p&gt;Once you get your token, add it to &lt;code&gt;.env&lt;/code&gt; inside our project as &lt;code&gt;API_TOKEN&lt;/code&gt;. We'll leverage Bun to securely access our secrets. No dotenv package needed! Env variables are available via Bun with &lt;code&gt;Bun.env.${YOUR_ENV}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After your token has been added, let's kill the current server and restart with &lt;code&gt;bun run dev&lt;/code&gt;. Now our value for the env variable should be accessible.&lt;/p&gt;

&lt;p&gt;Next we will connect our API to Trefle with a generate URL function. This function will construct a new URL object and dynamically append any query params to the string. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5ysew4fk0a3hnst00nm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5ysew4fk0a3hnst00nm.png" alt="Code snippet of generateUrl function to construct Trefle fetch url" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have a way to construct our url to the Trefle API, let's start getting some data. We'll need to complete those handler functions I mentioned earlier. &lt;/p&gt;

&lt;p&gt;For each handler, call the generateUrl function we created. For the specifics on getting plants, refer to the screenshot below. The purpose of this article isn't to use the Trefle API, just to demonstrate how to setup an Elysia instance. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwits2kpbx4e36h9rmz5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwits2kpbx4e36h9rmz5v.png" alt="Code snippet of finished code in src/api.ts file" width="800" height="768"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool, if your code looks similar to the snippet above, let's move on to wrapping up the endpoints in&lt;code&gt;index.ts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We just need to import the handler functions and assign them to the proper endpoints. &lt;/p&gt;

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

&lt;p&gt;After that's done, if we go to &lt;code&gt;localhost:3000/plants&lt;/code&gt; in our browser, we should see a JSON object returned with 30 plants 🎉 🌿&lt;/p&gt;

&lt;p&gt;Test out the other endpoints to get specific genus or species data! That about sums up the demo.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Additional Things About Elysia
&lt;/h3&gt;

&lt;p&gt;There's still a lot about the framework that we couldn't cover in this article. Here are some quick links if anything catches your eye.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://elysiajs.com/patterns/cookie.html" rel="noopener noreferrer"&gt;Cookies in Elysia&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/patterns/documentation.html" rel="noopener noreferrer"&gt;Swagger docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/patterns/websocket.html" rel="noopener noreferrer"&gt;Websockets&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/patterns/lazy-loading-module.html" rel="noopener noreferrer"&gt;Lazy loading&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/patterns/mvc.html" rel="noopener noreferrer"&gt;Dos and donts&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/eden/overview.html" rel="noopener noreferrer"&gt;E2E type safety&lt;/a&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Resources / Thank you
&lt;/h3&gt;

&lt;p&gt;Thanks for taking the time to read! What did you think? Are you going to be trying Elysia anytime soon? Let me know in the comments! &lt;/p&gt;

&lt;p&gt;If you want to know more about the API framework, checkout these links below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://elysiajs.com/" rel="noopener noreferrer"&gt;Elysia Docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/elysiajs/elysia" rel="noopener noreferrer"&gt;Elysia Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elysiajs.com/plugins/overview.html" rel="noopener noreferrer"&gt;Official Plugins&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/lundjrl/elysia-article" rel="noopener noreferrer"&gt;Demo Repo&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Image credits go to the Elysia repository image author. I did not create the banner image on this post&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>elysia</category>
      <category>bunjs</category>
      <category>api</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🍞 Bun, A Faster JavaScript Runtime</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Tue, 27 Feb 2024 21:41:03 +0000</pubDate>
      <link>https://dev.to/lundjrl/bun-a-faster-javascript-runtime-jph</link>
      <guid>https://dev.to/lundjrl/bun-a-faster-javascript-runtime-jph</guid>
      <description>&lt;p&gt;⚠️ &lt;strong&gt;Disclaimer: This article is for those who don't really know about Bun but want to understand it in a hurry&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A new challenger approaches in web development!&lt;/p&gt;

&lt;p&gt;Bun has received a lot of attention in the past year. But what is it?&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Bun?
&lt;/h2&gt;

&lt;p&gt;Bun is many things but to sum it up, Bun is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;package manager&lt;/li&gt;
&lt;li&gt;test runner&lt;/li&gt;
&lt;li&gt;fast javascript runtime&lt;/li&gt;
&lt;li&gt;bundler&lt;/li&gt;
&lt;li&gt;so many more things...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bun is basically, a smaller, faster Node.js replacement.&lt;/p&gt;

&lt;p&gt;Do note that not all features of Node.js are currently available in Bun. Though they will be built out eventually as the community is actively pushing out new and improved features. &lt;/p&gt;

&lt;p&gt;Thankfully, the Bun team provides a compatibility table to show what features are implemented and what still needs work. You can check that out &lt;a href="https://bun.sh/docs/runtime/nodejs-apis" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;One neat thing about Bun is it's written in &lt;a href="https://en.wikipedia.org/wiki/Zig_(programming_language)" rel="noopener noreferrer"&gt;Zig&lt;/a&gt;. A programming language that first appeared in 2016 that is intended to be a successor to the C programming language.&lt;/p&gt;

&lt;p&gt;Other languages on this level would be: &lt;a href="https://en.wikipedia.org/wiki/Go_(programming_language)" rel="noopener noreferrer"&gt;Go&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Rust_(programming_language)" rel="noopener noreferrer"&gt;Rust&lt;/a&gt;, and Google's new interoperability language for C++, &lt;a href="https://en.wikipedia.org/wiki/Carbon_(programming_language)" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While Zig is "new" in terms of languages, it seems to hold up to what the Bun team is trying to do with it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bun vs. Node
&lt;/h2&gt;

&lt;p&gt;As mentioned before, Bun isn't quite a 1:1 comparison to Node. So I'd avoid swapping out your back-end for it right now. However, if the features you use are fully implemented within Bun, I'd highly recommend trying it out.&lt;/p&gt;

&lt;p&gt;Why? Check out these metrics:&lt;/p&gt;

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

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

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

&lt;p&gt;&lt;br&gt;
As you can see, the results look pretty promising 👀&lt;/p&gt;

&lt;p&gt;Also, here's a thorough &lt;a href="https://medium.com/deno-the-complete-reference/is-bun-really-much-faster-than-node-js-e5b15942a8e8" rel="noopener noreferrer"&gt;breakdown article by Mayank Choubey&lt;/a&gt; going over some non-biased performance metrics. The results will shock you!&lt;/p&gt;

&lt;p&gt;If you want to test it out yourself, refer to &lt;a href="https://bun.sh/docs/project/benchmarking" rel="noopener noreferrer"&gt;this page&lt;/a&gt; of their documentation.&lt;/p&gt;

&lt;p&gt;And with that, there's also a bunch of applications we can construct with Bun. So many that there's a &lt;a href="https://bun.sh/guides/" rel="noopener noreferrer"&gt;guides section&lt;/a&gt; on the bun site. &lt;/p&gt;




&lt;h2&gt;
  
  
  Awesome Bun Projects
&lt;/h2&gt;

&lt;p&gt;With Bun reaching version 1.0, you bet that there's a ton of projects out there that use it. The makers of bun made a repository with a bunch of projects that use the tool, you can check that out &lt;a href="https://github.com/oven-sh/awesome-bun" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Most notable projects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/elysiajs/elysia" rel="noopener noreferrer"&gt;Express-like API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/honojs/hono" rel="noopener noreferrer"&gt;Express-like Edge API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://primatejs.com/" rel="noopener noreferrer"&gt;Web Framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dotansimha/graphql-yoga" rel="noopener noreferrer"&gt;GraphQL Yoga&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/RodrigoDornelles/npm-gamepadzilla/" rel="noopener noreferrer"&gt;Webdev Game Things&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thanks for reading!!&lt;/p&gt;

&lt;p&gt;This was a short one, next month should be a larger article with a demo. In the meantime, here's some links to other Bun-related resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/oven-sh/bun" rel="noopener noreferrer"&gt;Bun Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/oven-sh/awesome-bun" rel="noopener noreferrer"&gt;More Bun Projects&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bunjs</category>
      <category>node</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🚅 Building a Cypress Accessibility Pipeline with Next.js and Axe</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Mon, 18 Dec 2023 15:42:03 +0000</pubDate>
      <link>https://dev.to/lundjrl/building-a-cypress-accessibility-pipeline-with-nextjs-and-axe-5146</link>
      <guid>https://dev.to/lundjrl/building-a-cypress-accessibility-pipeline-with-nextjs-and-axe-5146</guid>
      <description>&lt;p&gt;In the web development world, there's a LOT of things we should remember. We should remember to build applications that are accessible, responsive, scalable, maintainable, cost-effective, secure, and the list goes on.&lt;/p&gt;

&lt;p&gt;But that first item, accessibility, gets overlooked way too often. Unfortunately, it's normal to see accessibility as an afterthought in a web application, much like those who need websites to be accessible. People are people and they have every right to use your website (assuming its public) as anyone else. &lt;/p&gt;

&lt;p&gt;If a user wants to consume your content, why shouldn't they be able to? &lt;/p&gt;

&lt;p&gt;If someone is taking time out of their day to use your product, why shouldn't they have the best experience possible?&lt;/p&gt;

&lt;p&gt;These are the questions we should be asking ourselves as we construct things that we care about. But as the developer, that's another thing you need to be mindful of. &lt;/p&gt;

&lt;p&gt;Is my application accessible? Am I meeting the needs of my users, ADA, and WCAG? Is my company or client at risk of being sued for not being above a certain accessibility score? &lt;/p&gt;

&lt;p&gt;It's hard to keep up with all of these things, but hopefully this tool will make it easier on you.&lt;/p&gt;

&lt;p&gt;Let's talk about Cypress and Axe.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Cypress? 🌲
&lt;/h2&gt;

&lt;p&gt;Cypress is a common name for some conifers in the Cupressaceae family (okay, I'm joking 😉, wrong cypress).&lt;/p&gt;

&lt;p&gt;Cypress is (primarily) an E2E testing framework.&lt;/p&gt;

&lt;p&gt;You can document user journeys, record where errors occur in your application, test components, and test E2E tests.&lt;/p&gt;

&lt;p&gt;Cypress has tons of support and is available in any project that can install NPM dependencies. &lt;/p&gt;

&lt;h2&gt;
  
  
  What's Axe? 🪓
&lt;/h2&gt;

&lt;p&gt;Axe is an accessibility testing framework that enables you to test your website against the standards of WCAG, A11y, ADA, and the like. &lt;/p&gt;

&lt;p&gt;You can use Axe as a browser extension, GitHub CI/CD, and so much more. We're gonna use it in an automated CI/CD pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Pipeline 🏗️
&lt;/h2&gt;

&lt;p&gt;Okay cool, we know what the tools are so let's clone &lt;a href="https://github.com/lundjrl/nextjs-accessibility-ci" rel="noopener noreferrer"&gt;the repo&lt;/a&gt; and play around.&lt;/p&gt;

&lt;p&gt;To start off, we'll install our dependencies with &lt;a href="https://bun.sh/docs/cli/install" rel="noopener noreferrer"&gt;bun install&lt;/a&gt; or if you want, &lt;code&gt;yarn install&lt;/code&gt; is supported too.&lt;/p&gt;

&lt;p&gt;Next, let's spin up the site with &lt;code&gt;bun run dev&lt;/code&gt; or &lt;code&gt;yarn dev&lt;/code&gt;. If you see the site at &lt;code&gt;localhost:3000&lt;/code&gt; then we're good to go. But before we get ahead of ourselves, let's look at the folders inside the project.&lt;/p&gt;

&lt;p&gt;The main takeaways here are the &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;.github&lt;/code&gt;, and &lt;code&gt;cypress&lt;/code&gt; directories.&lt;/p&gt;

&lt;p&gt;If you're new to Next.js or Next.js 13, the &lt;code&gt;app&lt;/code&gt; directory is a new way to implement SSR (server-side rendering) in your web application. Each folder is a route and will render content on the page as long as there is a &lt;code&gt;page.tsx&lt;/code&gt; file inside of it. &lt;/p&gt;

&lt;p&gt;To those of you who haven't worked with GitHub Actions, if you have a &lt;code&gt;.github/workflows&lt;/code&gt; folder in your project (and your repo is hosted on GitHub), upon pushing your code, GitHub will look in this folder for YAML files to run as CI/CD. &lt;/p&gt;

&lt;p&gt;This is a super easy way to implement CI/CD pipelines in your projects. The two files already in this repo are for e2e testing on push and verifying our Next.js site will build.&lt;/p&gt;

&lt;p&gt;And as you may have guessed, the &lt;code&gt;cypress&lt;/code&gt; directory will contain our tests and some configuration for Cypress. Let's take a peak at the resources there.&lt;/p&gt;



&lt;p&gt;If you look in the &lt;code&gt;cypress/support/e2e.ts&lt;/code&gt; file, you'll see that we're importing custom commands (if we had any) and the cypress-axe package. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96dyd6wdxw9qo5853gh4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96dyd6wdxw9qo5853gh4.jpg" alt="If I had any custom cypress commands meme" width="500" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That cypress-axe package import is crucial to using the functions that allow us to test our website against accessibility violations. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;cypress/e2e&lt;/code&gt; directory itself contains all of our tests for the UI of the application. The &lt;code&gt;cypress/e2e/log-to-terminal.cy.ts&lt;/code&gt; file is mainly here to provide cleaner logs to us for debugging accessibility issues. The main tests exist in the sibling file &lt;code&gt;check-accessibility.cy.ts&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are we testing?
&lt;/h3&gt;

&lt;p&gt;Each test should be self-describing. Some will target color accessibility for folks with color blindness, some will check for accessible HTML, and some others do custom things.&lt;/p&gt;

&lt;p&gt;These "custom things" can be anything between excluding HTML elements, targeting specific ones, specifying custom rules, and only failing a test if serious or critical accessibility issues are found. &lt;/p&gt;

&lt;p&gt;Here are some examples:&lt;/p&gt;

&lt;h4&gt;
  
  
  Checking All Potential Issues
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Critical Issues Only
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Custom Rules
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Ignoring Specific Elements
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Targeting Specific Elements
&lt;/h4&gt;

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

&lt;p&gt;As you can see, there's not a lot of code that goes into these tests which is ideal if we're double-checking for any violation we might have missed. &lt;/p&gt;

&lt;p&gt;Now, let's run these tests via &lt;code&gt;bun run cypress:open&lt;/code&gt; or &lt;code&gt;yarn cypress:open&lt;/code&gt; respectively.&lt;/p&gt;

&lt;p&gt;If all is well, you should see this:&lt;/p&gt;

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

&lt;p&gt;You can choose whichever browser suits your preference.&lt;br&gt;
Next, click the &lt;code&gt;E2E&lt;/code&gt; testing type:&lt;/p&gt;

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

&lt;p&gt;After that, you should see a list of our spec files. &lt;code&gt;check-accessibility.cy.ts&lt;/code&gt; is the only one we care about for the purpose of this tutorial. Click the spec and watch our tests run!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Reviewing the pipeline steps
&lt;/h2&gt;

&lt;p&gt;Awesome, so we can spin up the Next.js project and run our E2E tests locally. What about the YAML file for the pipeline?&lt;/p&gt;

&lt;p&gt;It's pretty simple but let's review the steps inside &lt;code&gt;.github/workflows/e2e.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At the top of the file, the &lt;code&gt;on&lt;/code&gt; statement specifies on push or pull request to the main branch. This filters the action to only run under those conditions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;On push to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;On a pull request to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After that, we specify our job and the container it runs in (ubuntu-22.04).&lt;/p&gt;

&lt;p&gt;Then as you can see, there's 6 steps the pipeline executes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Checkout our repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install Node (Bun isn't supported yet).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Restore the Next.js cache for faster build times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install dependencies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build the Next.js site&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run Cypress&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;That's it! After we push to our main branch or make a PR, Cypress scanned each page we defined and let us know where we should fix our code to comply with accessibility standards.&lt;/p&gt;

&lt;p&gt;Now could you imagine reading up all the WCAG and A11y rules yourself? Using a tool like this will save your team time, cost, and possibly a lawsuit.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article and learned something! Got a hot tip for implementing accessibility? Something cool about the tools discussed that I didn't mention? Let me know in the comments below!&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.accessibilitychecker.org/" rel="noopener noreferrer"&gt;Is your site accessible enough?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lundjrl/spark-accessibility-ci" rel="noopener noreferrer"&gt;Demo Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.cypress.io/guides/overview/why-cypress" rel="noopener noreferrer"&gt;Cypress Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/dequelabs/axe-core/blob/develop/doc/developer-guide.md" rel="noopener noreferrer"&gt;Axe Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imgflip.com/memegenerator" rel="noopener noreferrer"&gt;Meme creation tool&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cover Image created by &lt;a href="https://unsplash.com/photos/a-dirt-road-surrounded-by-trees-and-bushes-3VXDX6-cRPA" rel="noopener noreferrer"&gt;Tomáš Hirsch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>cypress</category>
    </item>
    <item>
      <title>The Beginners Breezy Intro to Tailwind</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Sun, 26 Nov 2023 15:12:09 +0000</pubDate>
      <link>https://dev.to/lundjrl/a-breezy-introduction-to-tailwind-3h7h</link>
      <guid>https://dev.to/lundjrl/a-breezy-introduction-to-tailwind-3h7h</guid>
      <description>&lt;p&gt;You've probably seen Tailwind somewhere around the internet. Whether it's recommended by your favorite web framework, criticized in another article for being "messy", or shouted on the rooftops by some web dev influencer, Tailwind has undoubtedly made its impact in the dev world.&lt;/p&gt;

&lt;p&gt;In this article, I'll explain Tailwind's main concepts through the assumption that you have little to no knowledge of it. This article is not to persuade you but rather to inform you of what Tailwind is and how you could add it to a Next.js project. If you don't want to use Next.js, you can view the list of guides 👉 &lt;a href="https://tailwindcss.com/docs/installation/framework-guides" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With all that out of the way, let's dive in! &lt;/p&gt;




&lt;h2&gt;
  
  
  What IS Tailwind?
&lt;/h2&gt;

&lt;p&gt;Tailwind, in short, is a CSS library made up of a bunch of utility classes that have been pre-selected for you with your interest in mind.&lt;/p&gt;

&lt;p&gt;Interesting, how so?&lt;/p&gt;

&lt;p&gt;I can only cover so much, but if you're interested, please please please read &lt;a href="https://www.refactoringui.com/" rel="noopener noreferrer"&gt;the book&lt;/a&gt;. Tailwind isn't just a bunch of RANDOM utility classes, they're specifically selected to help you build responsive and elegant design solutions. &lt;/p&gt;

&lt;h3&gt;
  
  
  What's a utility class?
&lt;/h3&gt;

&lt;p&gt;Utility classes are generally agreed upon as being simple, single-use classes. In the realm of CSS, a utility class could be &lt;code&gt;flex&lt;/code&gt; which could translate to &lt;code&gt;display: flex&lt;/code&gt; or &lt;code&gt;rotate-90&lt;/code&gt; which could translate to &lt;code&gt;transform: rotate(90deg)&lt;/code&gt; or even &lt;code&gt;shadow&lt;/code&gt; which could translate to &lt;code&gt;box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;☝️ These are all Tailwind utilities by the way.&lt;/p&gt;

&lt;p&gt;Hopefully, these examples shed some light as to why one would want to use utility classes.&lt;/p&gt;

&lt;p&gt;You may be wondering, if Tailwind is a bunch of these "utility classes", why couldn't I just make my own in a &lt;code&gt;*.css&lt;/code&gt; file?&lt;/p&gt;

&lt;p&gt;In truth, you totally can. You can take the time to define your utility classes and create your design system. But if you don't have the time or resources, Tailwind would be an excellent option.&lt;/p&gt;

&lt;p&gt;Tailwind has things like light/dark mode, theme support, hover and focus classes, CSS grouping, media queries, and a bunch of optional plugins that you can set up before your coffee maker finishes your morning brew. &lt;/p&gt;

&lt;p&gt;More CSS vs. Tailwind things 👉 &lt;a href="https://tailwindcss.com/docs/utility-first" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;Tailwind, like many tools, needs a configuration file so it knows what to do. This file is either called &lt;code&gt;tailwind.config.js&lt;/code&gt; or &lt;code&gt;tailwind.config.ts&lt;/code&gt; for you Typescript nerds. &lt;/p&gt;

&lt;p&gt;When you're editing your &lt;code&gt;tailwind.config.ts&lt;/code&gt; file, you're able to specify a "content" property. This property tells Tailwind where to look for its utility classes and which file extensions it should care about.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshnpm9eolpsnni1dv2ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshnpm9eolpsnni1dv2ak.png" alt="Example of a tailwind.config.js file, showcasing the content property" width="538" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screenshot, I'm telling Tailwind to look at my pages, components, and app directories for files that end in &lt;code&gt;*.js&lt;/code&gt;, &lt;code&gt;*.ts&lt;/code&gt;, &lt;code&gt;*.jsx&lt;/code&gt;, &lt;code&gt;*.tsx&lt;/code&gt;, and &lt;code&gt;*.mdx&lt;/code&gt;. If I had html files in these directories, I'd include &lt;code&gt;*.html&lt;/code&gt; too. &lt;/p&gt;

&lt;p&gt;When building your site, Tailwind will look at these files and see where and which utility classes are actually being used. &lt;/p&gt;

&lt;p&gt;It will only care about the ones being used and disregard the other utility classes it knows about. This is part of its tree-shaking process. &lt;/p&gt;




&lt;h2&gt;
  
  
  How can I install it?
&lt;/h2&gt;

&lt;p&gt;There's typically two routes you can take to add Tailwind to your project. Via the Tailwind CLI or as a PostCSS plugin.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://tailwindcss.com/docs/installation" rel="noopener noreferrer"&gt;the docs&lt;/a&gt; Tailwind CLI is "the simplest and fastest way to get up and running with Tailwind". Though this is true, I want to stick with a different approach. The one that you'd probably use to integrate it into your project by using Tailwind as a PostCSS plugin. This is the recommended way to integrate it into your project if you're using Webpack, Vite, Rollup or any other build tool.&lt;/p&gt;

&lt;p&gt;See how your framework should use Tailwind 👉 &lt;a href="https://tailwindcss.com/docs/installation/framework-guides" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before installing it though, we should probably understand two other tools that are needed for this. PostCSS and Autoprefixer.&lt;/p&gt;

&lt;p&gt;According to their Git repo, PostCSS is "a tool for transforming styles with JavaScript plugins". In short, it "takes a CSS file and provides an API to analyze and modify its rules by transforming them into an abstract syntax tree" using JavaScript. "This API can then be used by plugins". Plugins like TailwindCSS and Autoprefixer in our case. &lt;/p&gt;

&lt;p&gt;Autoprefixer, according to the NPM docs, is a PostCSS plugin to parse CSS and add vendor prefixes to CSS rules using values from &lt;a href="https://caniuse.com/" rel="noopener noreferrer"&gt;Can I Use&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Here's a list of some browser prefixes as of the time of this article:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-webkit- (Chrome, Safari, newer versions of Opera and Edge, almost all iOS browsers, basically any WebKit or Chromium-based browser)
-moz- (Firefox)
-o- (old pre-WebKit versions of Opera)
-ms- (Internet Explorer and Microsoft Edge, before Chromium)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay cool, now that we understand what these things are, let's get back to installing Tailwind in our app.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting it up in a Next.js app
&lt;/h2&gt;

&lt;p&gt;If you want to skip setting it up and just play around, you can install an already configured template and play around with it 👉 &lt;a href="https://github.com/lundjrl/Next-App-Template" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, if you like this template or have suggestions, please star it or create an issue. Thank you!&lt;/p&gt;

&lt;p&gt;Otherwise, let's follow the &lt;a href="https://tailwindcss.com/docs/guides/nextjs" rel="noopener noreferrer"&gt;Tailwind docs&lt;/a&gt; and set this up from a clean slate.&lt;/p&gt;

&lt;p&gt;To start off, let's install a VSCode extension to give us some IntelliSense: &lt;/p&gt;

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

&lt;p&gt;Then, let's setup a new Next.js project:&lt;/p&gt;

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

&lt;p&gt;Next, we'll install tailwind and our dependencies with npm:&lt;/p&gt;

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

&lt;p&gt;In order to use Tailwind, we'll need to tell it which files to look at in the "content" section of our Tailwind config:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitxljlmj6z7ftqtq3o3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fitxljlmj6z7ftqtq3o3t.png" alt="Example of a tailwind.config.js file, showcasing the content property" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, we'll need to add Tailwind's directives to Next.js' &lt;code&gt;globals.css&lt;/code&gt; file. This is needed to use it's utility classes. More info 👉 &lt;a href="https://tailwindcss.com/docs/functions-and-directives" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Now that everything is set up, you should be able to start styling your site! With every tool, there's a learning curve and it's impossible to remember everything. So that's why I use &lt;a href="https://nerdcave.com/tailwind-cheat-sheet" rel="noopener noreferrer"&gt;a cheatsheet&lt;/a&gt; to help me build things.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adding your own utility classes
&lt;/h2&gt;

&lt;p&gt;What if we wanted to add our custom branding colors? We can do that by creating custom utility classes in our config.&lt;/p&gt;

&lt;p&gt;There's a section in your &lt;code&gt;tailwind.config.js&lt;/code&gt; file that allows you to add additional utility classes by extending your theme. You can see from the image below, I include two new colors, &lt;code&gt;primary&lt;/code&gt; and &lt;code&gt;errorOnLight&lt;/code&gt;. After making your changes here, you can now use them in your html.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshnpm9eolpsnni1dv2ak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshnpm9eolpsnni1dv2ak.png" alt="Adding custom theme colors in Tailwind.config.js file" width="538" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like to define my brand colors in the config so I can use them in the project. You can choose to either keep all the Tailwind colors or only keep your custom ones, the choice is yours.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tree-shaking and production
&lt;/h2&gt;

&lt;p&gt;So we're able to setup Tailwind in a Next.js site, but what happens when we want to build for production?&lt;/p&gt;

&lt;p&gt;From the docs: &lt;br&gt;
"Tailwind CSS is incredibly performance focused and aims to produce the smallest CSS file possible by only generating the CSS you are actually using in your project.&lt;/p&gt;

&lt;p&gt;Combined with minification and network compression, this usually leads to CSS files that are less than 10kB, even for large projects. For example, Netflix uses Tailwind for Netflix Top 10 and the entire website delivers only 6.5kB of CSS over the network."&lt;/p&gt;

&lt;p&gt;If you installed Tailwind as a PostCSS plugin (we did in this article) you can also use &lt;code&gt;cssnano&lt;/code&gt; as a plugin to reduce the CSS bundle when we make a production build. More info on that 👉 &lt;a href="https://tailwindcss.com/docs/optimizing-for-production" rel="noopener noreferrer"&gt;here&lt;/a&gt;. However, I have not noticed this making a difference in a Next.js application. Probably due to Next.js minimizing things for us automatically. &lt;/p&gt;

&lt;p&gt;I hope this leaves you with a better understanding of what Tailwind is! Did I miss something? Do you know a cool Tailwind trick? Let me know in the comments below!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;Cover image created by &lt;a href="https://www.pexels.com/@124360385/" rel="noopener noreferrer"&gt;Булат Салихов&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>design</category>
    </item>
    <item>
      <title>🔮 VSCode Extensions To Magically Accelerate Your Productivity</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Mon, 23 Oct 2023 12:10:16 +0000</pubDate>
      <link>https://dev.to/lundjrl/vscode-extensions-to-magically-accelerate-your-productivity-2lad</link>
      <guid>https://dev.to/lundjrl/vscode-extensions-to-magically-accelerate-your-productivity-2lad</guid>
      <description>&lt;p&gt;Most of you reading this probably use VSCode extensions on a daily basis. Whether it's to lint code, show suggestions, type inference, or something to make you laugh, they impact your workflow and help you build products.&lt;/p&gt;

&lt;p&gt;Below is a list of extensions that I use daily. It's safe to say I would be totally lost without them and my estimates on tickets would inflate. &lt;/p&gt;

&lt;p&gt;I hope these help you as much as they've helped me!&lt;/p&gt;




&lt;h2&gt;
  
  
  Auto Rename Tag
&lt;/h2&gt;

&lt;p&gt;Starting off this list is the Auto Rename Tag extension. This extension is super useful if you work with a lot of HTML. The general gist of it is it'll format the closing tag of the tag you're editing to be the same name so you don't have to. This saves me a lot of time when I'm working on legacy sites that have &lt;code&gt;*.html&lt;/code&gt; files with tags that wrap 100+ other tags. &lt;/p&gt;

&lt;p&gt;Id: formulahendry.auto-rename-tag&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Code Spell Checker
&lt;/h2&gt;

&lt;p&gt;This one is really helpful if you work with international teams or you want to document words or abbreviations within a project. &lt;/p&gt;

&lt;p&gt;Code Spell Checker allows you to fix misspelled words or save them to the project's &lt;code&gt;settings.json&lt;/code&gt; file. This shows intention which is huge for onboarding new developers who might not be familiar with the business phrases of the application. &lt;/p&gt;

&lt;p&gt;Id: streetsidesoftware.code-spell-checker&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  EditorConfig
&lt;/h2&gt;

&lt;p&gt;EditorConfig is ESSENTIAL for my team and me. It helps us keep our code editors in sync and reduce diff logs when making pull requests by establishing a formatting standard.&lt;/p&gt;

&lt;p&gt;Id: EditorConfig.EditorConfig&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Eslint &amp;amp; Prettier
&lt;/h2&gt;

&lt;p&gt;If you've been in the webdev world for a short period of time, you've probably came across these two. I won't go into too much detail here but in short, Eslint is a linter, Prettier is a formatter. You can use them together to enforce a code standard in your projects.&lt;/p&gt;

&lt;p&gt;Id: dbaeumer.vscode-eslint&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Id: esbenp.prettier-vscode&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Git-Rename
&lt;/h2&gt;

&lt;p&gt;Git-Rename is very useful if you want to rename a file or change the casing in a filename. Instead of deleting a file to remove it from your Git history so you can change its casing, Git-Rename lets you rename your file and helps you track those changes in Git.&lt;/p&gt;

&lt;p&gt;What?&lt;/p&gt;

&lt;p&gt;Say you have a file called "myfile" in your project and it's already tracked by version control. If you change the name to "myFile" that's just a casing change and Git won't care about it by default. You can change your git settings to fix this but if you're working in a team, you'll need to convince your fellow devs to do the same. An easier option would be to include this extension in your &lt;code&gt;extensions.json&lt;/code&gt; file in your project so they get prompted every time they open the project that they should download the extension. &lt;/p&gt;

&lt;p&gt;Id: ambooth.git-rename&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=ambooth.git-rename" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=ambooth.git-rename&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Import Cost
&lt;/h2&gt;

&lt;p&gt;Import cost lets you know how many bytes each of your imported packages are. It's super useful for mobile apps where your bundle size means a lot to your end users.&lt;/p&gt;

&lt;p&gt;Id: wix.vscode-import-cost&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  IntelliCode
&lt;/h2&gt;

&lt;p&gt;Another great extension for TypeScript and JavaScript. IntelliCode works as that annoying friend who tries to finish your sentences. It provides method/object completion for the TS version it finds in your project and infers types for you, letting you know which properties on an object you can use.&lt;/p&gt;

&lt;p&gt;For you Django fans, it works for Python too!&lt;/p&gt;

&lt;p&gt;Id: VisualStudioExptTeam.vscodeintellicode&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Pretty Typescript Errors
&lt;/h2&gt;

&lt;p&gt;This one isn't for everyone but I write a lot of TypeScript and it helps me parse out TS errors. Basically, instead of TypeScript giving you a long and semi-convoluted message, this extension will display a more human-friendly message to help you narrow down what you're doing wrong in your code. &lt;/p&gt;

&lt;p&gt;Id: yoavbls.pretty-ts-errors&lt;br&gt;
VS Marketplace Link: &lt;a href="https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Do you use any of these extensions? Do you have a suggestion for extensions that work better than these? Let me know in the comments below!&lt;/p&gt;

&lt;p&gt;Cover image created by &lt;a href="https://pixabay.com/photos/fantasy-woman-viking-magic-6141885/" rel="noopener noreferrer"&gt;GioeleFazzeri&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>extensions</category>
    </item>
    <item>
      <title>Get Validated With Zod</title>
      <dc:creator>James Robert Lund III </dc:creator>
      <pubDate>Wed, 10 May 2023 21:11:27 +0000</pubDate>
      <link>https://dev.to/lundjrl/get-validated-with-zod-2klo</link>
      <guid>https://dev.to/lundjrl/get-validated-with-zod-2klo</guid>
      <description>&lt;p&gt;How many times has this happened to you? &lt;/p&gt;

&lt;p&gt;You're writing a super sweet api that consumes some data from a database and tosses that data to some front-end where it can be consumed by users. &lt;/p&gt;

&lt;p&gt;Maybe your api has a POST endpoint where users can upload data that's being consumed and viewed by other users. That's all fine and dandy until you start to get some bad data into your database. Maybe some data that doesn't fit a model and will blow up your application if not formatted properly.&lt;/p&gt;

&lt;p&gt;See, Typescript is awesome in all, but it lacks data security. It might tell you (the developer) that a type is missing a property but it wouldn't actually stop data from going through that part of your application.  &lt;/p&gt;

&lt;p&gt;This is where Zod comes in.&lt;/p&gt;

&lt;p&gt;Zod is an amazing library. You can use it to define schema's, create types, and most importantly... validate data. This data validation library was created to fill in the gaps that Typescript leaves behind. &lt;/p&gt;

&lt;p&gt;That sounds great in all... but how about some examples?&lt;/p&gt;

&lt;p&gt;Defining a schema:&lt;/p&gt;

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

&lt;p&gt;Here we create a schema called "POST_SCHEMA", it expects some data to have an id with a length of 16, a postNumber that's a number, and a few more fields. You get the idea.&lt;/p&gt;

&lt;p&gt;Inferring a Type:&lt;/p&gt;

&lt;p&gt;We can now create a type from our schema to use anywhere else in our app.&lt;/p&gt;

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

&lt;p&gt;This looks and will act the same as:&lt;/p&gt;

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

&lt;p&gt;But the benefit is we also have a schema to validate our data. &lt;/p&gt;

&lt;p&gt;Parsing data:&lt;/p&gt;

&lt;p&gt;Now that we have a schema, we can validate or "parse" our data to make sure it fits our defined model.&lt;/p&gt;

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

&lt;p&gt;Zod will throw an error if the data isn't matching the schema we created.&lt;/p&gt;

&lt;p&gt;But what if I don't want to throw an error?&lt;/p&gt;

&lt;p&gt;That's easy, we can just use the &lt;code&gt;safeParse&lt;/code&gt; function instead!&lt;/p&gt;

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

&lt;p&gt;If you're curious about this library, you can view the full documentation &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. It's helped me a lot on production projects and hopefully it helps you too.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
