<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Bridget Amana</title>
    <description>The latest articles on Forem by Bridget Amana (@bridget_amana).</description>
    <link>https://forem.com/bridget_amana</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%2F1693394%2Fc6a753fe-84d8-43e2-a37d-cc4746818e59.png</url>
      <title>Forem: Bridget Amana</title>
      <link>https://forem.com/bridget_amana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bridget_amana"/>
    <language>en</language>
    <item>
      <title>The Challenges Threatening Open Source</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Wed, 25 Feb 2026 20:33:12 +0000</pubDate>
      <link>https://forem.com/bridget_amana/the-challenges-threatening-open-source-160g</link>
      <guid>https://forem.com/bridget_amana/the-challenges-threatening-open-source-160g</guid>
      <description>&lt;p&gt;Open source software (OSS) serves as the digital backbone of modern society, providing the foundation for the applications and services we rely on daily. However, the same openness that drives innovation also introduces significant risks. As our dependence on shared code grows, the obstacles facing the ecosystem become more complex. Understanding these challenges is the first step toward building a more resilient future for software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security vulnerabilities
&lt;/h2&gt;

&lt;p&gt;Many open source initiatives are maintained by small groups of volunteers or even a single individual. While this grassroots approach is a testament to the community's spirit, it creates a "single point of failure." Inactive or abandoned repositories can harbor known vulnerabilities that remain unpatched for years, leaving any system that uses them exposed.&lt;/p&gt;

&lt;p&gt;It gets messier when you factor in dependency chains. Most open source software relies on other open source software, and those chains can get long and hard to track. One weak link in that chain and suddenly you've got a security problem that ripples outward. The transparency that makes open source so powerful is also what makes it vulnerable here. Attackers can see the same code that the community uses to fix things, and sometimes they get there first. That's why regular auditing and automated scanning have become so critical, not just a nice-to-have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sustainability
&lt;/h2&gt;

&lt;p&gt;Every open source project has people behind it, and keeping those people around is one of the trickiest parts of the whole thing. These projects need funding, they need resources, and most of all they need contributors who stick around. When a project becomes essential to global industry but lacks a support structure, the burden often falls on a few individuals.&lt;/p&gt;

&lt;p&gt;This leads to maintainer burnout—a state where the pressure of fixing bugs and managing requests outweighs the joy of contributing. Sustainability is not just a financial issue; it is about creating a culture where contributors feel supported. If the software that millions of companies depend on is treated as a "free" resource without reinvestment, the very people who build it may eventually stop showing up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining code quality
&lt;/h2&gt;

&lt;p&gt;Open source invites anyone to contribute, and that's one of its greatest strengths. You get people with all kinds of backgrounds, skill levels, and ideas jumping in, and that kind of diversity makes projects genuinely better. But it also makes keeping the code tight and consistent a real challenge.&lt;/p&gt;

&lt;p&gt;When contributions are coming in from all over the place, without solid review processes or clear guidelines, things can start to slip. Small issues add up, and before long you've got a codebase that's harder to maintain and trust. It's one of those problems that doesn't announce itself loudly. It just quietly builds up until someone notices something is off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking ahead
&lt;/h2&gt;

&lt;p&gt;Open source has never been just about code. It's about curiosity, generosity, and the belief that collaboration makes better things and better people. The next few years will test that belief like never before. But if we do what we've always done best, show up, share the work, and care for each other, we won't just sustain open source. We'll sustain the spirit that started it and ensure the success we've built continues for the good of the modern world.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>learning</category>
    </item>
    <item>
      <title>Getting Your First Open Source Contributors</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 16 Feb 2026 10:49:12 +0000</pubDate>
      <link>https://forem.com/bridget_amana/getting-your-first-open-source-contributors-5j</link>
      <guid>https://forem.com/bridget_amana/getting-your-first-open-source-contributors-5j</guid>
      <description>&lt;p&gt;I have built a number of open source projects, including &lt;a href="https://marketplace.visualstudio.com/items?itemName=Bridget.snippetshot" rel="noopener noreferrer"&gt;snippet shot&lt;/a&gt;, &lt;a href="https://marketplace.visualstudio.com/items?itemName=Bridget.tailwind-migrator" rel="noopener noreferrer"&gt;tailwindcss migrator&lt;/a&gt;, and &lt;a href="https://pixlated.bridgetamana.me/" rel="noopener noreferrer"&gt;pixlated&lt;/a&gt;. After building, I shared it on forums and communities, made it clear in the readme that 'contributions are welcome,' but still got zero contributions. It made me wonder what exactly I was doing wrong. I looked at these repos from outsider's perspective. I noticed that, aside from the big “contributors are welcome” message, nothing else was inviting me to contribute. From there, I discovered a few more issues as to why my project wasn’t receiving contributors. &lt;/p&gt;

&lt;h2&gt;
  
  
  Show how to use and setup your project
&lt;/h2&gt;

&lt;p&gt;When I first shared the repo, there was nothing guiding users on how to set up the project. I had a README but it was missing installation instructions. Without this, potential contributors face unnecessary friction. If you can't get a project running, how can you contribute to it? Good installation instructions aren't just 'npm install.' They should walk through the complete setup: prerequisites, installation steps, how to run locally, and what success looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep your project active
&lt;/h2&gt;

&lt;p&gt;I have scrolled past repos countless times simply because the last activity was months ago. It subtly signals that this project isn’t active so why waste my time contributing. When I looked at my projects from that perspective, I realized I wouldn't even contribute to them if they weren't mine. You don't need daily commits, but aim for visible activity at least once a month. This could be merging a PR, updating a dependency, adding an example to your docs, or even just triaging issues. The goal isn't busywork, it's showing the project has a pulse. On Pixlated, I set a reminder to review and update something small monthly, even during quiet periods. That consistent timestamp matters more than you'd think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open up a few issues first.
&lt;/h2&gt;

&lt;p&gt;Sometimes, people don't know how they can contribute. Be their guide. Opening a few issues paves the way for more contributors. I looked at the project and it seemed dry—maybe people didn't know where to start. Contributions on pPxlated started coming in when I opened up a few good first issues. The first issue I opened was to 'convert all project images to .webp format'. This was after running the site on page speed insights and it pointed out that performance issue. I could have done this instantly by myself but I thought, this is a good simple first issue for someone just getting started with open source contributions. Within a couple of hours, someone commented asking to be assigned. After that, I used the same strategy. I opened simple issues that wouldn't take more than 5 minutes to do. With this constant interaction, other people started opening issues. A few issues were ignored till they were further broken down in the issue description.&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%2F98pyjam80xaefjkkwmtf.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%2F98pyjam80xaefjkkwmtf.png" alt="first assigned issue" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It shows that people want to contribute but are confused about what they can do.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show appreciation to your previous contributors.
&lt;/h2&gt;

&lt;p&gt;Contributors aren't paid for their work, so recognition matters. Seeing your GitHub profile on a project gives contributors that dopamine hit that makes them want to return. Give people reasons to be excited: thank contributors after a successful merge or add a contributors section to your README. This appreciates past contributors and signals to new ones that their efforts will be valued.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publicize your work
&lt;/h2&gt;

&lt;p&gt;You can't contribute to what you don't know about. Contributions aren't coming in because your project is still very much hidden. Share your project on communities and social media. Announce what you're building, that it's open for contributions, and when you open new issues. I posted on Reddit and created an article on Dev.to to share the project. Neither got much traction. What actually kickstarted contributions was a Twitter post announcing good first issues. Don't constrain yourself to one platform. Twitter worked for me because I was already consistent and had followers there. It might not work for you if you're just starting out. So, go where your audience is. I didn't just stop at one post but continued giving updates regularly.&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%2Fyn9u9vor2lgkw9p2gxr5.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%2Fyn9u9vor2lgkw9p2gxr5.png" alt="Twitter post of Pixlated" width="602" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get your project up and running first
&lt;/h2&gt;

&lt;p&gt;People won't contribute to what isn't working. Project owners might think building together is part of the open source spirit, but contributors want to improve something functional, not debug a broken foundation. Get the project started on your own and show that crucial features are working. Don't build halfway with nothing visibly working and expect people to join. This doesn't mean your project needs to be feature-complete, but there should be a working core that people can clone, run, and see in action. For Pixlated, I made sure the basic image pixelation worked and the site was deployed before asking for contributions. Contributors could visit the live site, understand what it does, then look at the code to improve it. Starting with a half-built project where nothing runs yet means contributors spend their time figuring out your vision instead of improving it. &lt;/p&gt;

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

&lt;p&gt;If your project hasn't had contributions, the first step is to audit your readme. Make sure someone can understand what it does and how to run it within 30 seconds. Then work on sharing your project to get eyes on it. The more eyes you get on it, the greater your chances of getting a contributor. The contributors are out there, you just need to make it easy for them to find and join you&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Exploring The Career Of A Technical Writer</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 16 Feb 2026 10:45:29 +0000</pubDate>
      <link>https://forem.com/bridget_amana/exploring-the-career-of-a-technical-writer-2gm1</link>
      <guid>https://forem.com/bridget_amana/exploring-the-career-of-a-technical-writer-2gm1</guid>
      <description>&lt;h2&gt;
  
  
  Who a Technical writer is
&lt;/h2&gt;

&lt;p&gt;A technical writer (sometimes called a tech writer) is someone who takes complicated technical concepts and makes it easy for people to understand. They translate jargons to easy-to-understand documentation. While many people think technical writers just write "guides", their role is more expansive than that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Information Design: They determine how to structure information so users can find what they need quickly.&lt;/li&gt;
&lt;li&gt;User Advocacy: They represent the end-user, often testing products to identify points of confusion before the documentation is even written.&lt;/li&gt;
&lt;li&gt;User Advocacy: They speak up for you, the end-user. They'll test products and spot confusing parts before the documentation is even written.&lt;/li&gt;
&lt;li&gt;Content Creation: They create all sorts of materials, including:

&lt;ul&gt;
&lt;li&gt;API Documentation: Instructions that help developers use software tools.&lt;/li&gt;
&lt;li&gt;Help Systems: Those searchable knowledge bases you use when you're stuck.&lt;/li&gt;
&lt;li&gt;Standard Operating Procedures (SOPs): Internal guides that show employees how to do their jobs.&lt;/li&gt;
&lt;li&gt;White Papers: Deep-dive reports that explain specific technologies or solutions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Skills Needed to Be a Technical Writer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Technical Proficiency
&lt;/h3&gt;

&lt;p&gt;You don't need to be a programmer, but you'll need some basic technical knowledge. If you're documenting a Python tool, for example, understanding basic Python concepts helps you ask better questions and catch mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Research
&lt;/h3&gt;

&lt;p&gt;Research is at the core of what a technical writer do. Writers dig into unfamiliar topics, interview subject matter experts, and test products themselves to truly understand what they're explaining. Good research means you can explain something clearly even if you weren't the one who built it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication and Collaboration
&lt;/h3&gt;

&lt;p&gt;Technical writers work with developers, product managers, designers, and customer support teams. You need to ask the right questions and build good relationships with stakeholders.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing and Editing
&lt;/h3&gt;

&lt;p&gt;This might seem obvious, but it's about more than just grammar. You need to write clearly, cut unnecessary jargon, and know when to use a diagram instead of a paragraph. You're always thinking: "What's the simplest way to say this?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Role of A Technical Writer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create Documentation&lt;/li&gt;
&lt;li&gt;Translate Technical Information&lt;/li&gt;
&lt;li&gt;Research &amp;amp; Understand Products&lt;/li&gt;
&lt;li&gt;Organize Information&lt;/li&gt;
&lt;li&gt;Maintain and Update Content&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Your guide to getting started
&lt;/h3&gt;

&lt;p&gt;If you're interested in becoming a technical writer, here's the good news: you don't need a specific degree. Many technical writers come from writing backgrounds, while others transition from technical roles like software development or IT support. The key is being curious, willing to learn, and able to explain things clearly.&lt;/p&gt;

</description>
      <category>writing</category>
    </item>
    <item>
      <title>Improve Site Performance by Auditing Unused Code</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 08 Dec 2025 16:47:52 +0000</pubDate>
      <link>https://forem.com/bridget_amana/improve-site-performance-by-auditing-unused-code-20ag</link>
      <guid>https://forem.com/bridget_amana/improve-site-performance-by-auditing-unused-code-20ag</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Shipping unused CSS and JavaScript does more than clutter your codebase. It directly affects your site's performance. Every unused rule or function is extra data the browser has to download and parse before the page becomes interactive. While you could manually compare your styles against your HTML, modern browsers provide a more easier solution: the Coverage tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Coverage tool does
&lt;/h2&gt;

&lt;p&gt;The Coverage panel in developer tools analyzes every CSS and JavaScript resource loaded on a page. It calculates which parts of each file are actually used during rendering and highlights the unused sections. This gives you a clear view of what can be safely removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open DevTools (&lt;code&gt;Cmd+Option+I&lt;/code&gt; on Mac or &lt;code&gt;Ctrl+Shift+I&lt;/code&gt; on Windows).&lt;/li&gt;
&lt;li&gt;Open the Command Menu (&lt;code&gt;Cmd+Shift+P&lt;/code&gt; or &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Type &lt;strong&gt;Coverage&lt;/strong&gt; and select &lt;strong&gt;Show Coverage&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the Coverage tab, click the reload icon to start recording.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The panel lists all CSS and JavaScript files, along with the percentage of code executed. Red highlights indicate unused sections. You can also filter the results to show all resources or only CSS or only JavaScript.&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%2Fl7kb75e42w3k8d8pvumr.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%2Fl7kb75e42w3k8d8pvumr.png" alt="Coverage tool screenshot" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Analyzing Results 
&lt;/h3&gt;

&lt;p&gt;Once the page reloads, the Coverage tab displays the used and unused portions of each file. These results are helpful but require proper interpretation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pseudo classes such as hover or active appear unused when they are not triggered.
&lt;/li&gt;
&lt;li&gt;Media query rules appear unused if your current viewport does not match the query.
&lt;/li&gt;
&lt;li&gt;Interaction based styles and animations will not register unless activated during recording.
&lt;/li&gt;
&lt;li&gt;JavaScript that runs only after specific actions will appear unused until those actions occur.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Performance improvements do not always require complex changes. Identifying and removing unused CSS and JavaScript is a simple and effective way to reduce page weight. The Coverage tool helps you find what is no longer used on the page, and removing that results in a faster site.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Understanding why 100vh behaves differently on mobile</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 08 Dec 2025 16:38:09 +0000</pubDate>
      <link>https://forem.com/bridget_amana/understanding-why-100vh-behaves-differently-on-mobile-140k</link>
      <guid>https://forem.com/bridget_amana/understanding-why-100vh-behaves-differently-on-mobile-140k</guid>
      <description>&lt;p&gt;The expected behavior of 100vh is simple. When you apply it to an element, it should take up the full visible height of the screen so no scrolling is required. This works perfectly on desktop. On mobile browsers, especially Chrome and Safari, the behavior is different. The bottom part of the page sits behind the browser interface, so the content appears cut off unless you scroll. This article focuses on understanding why this happens and how to fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;100vh has always been the quick way to create a full height layout. The issue is that mobile browsers do not calculate 100vh using the actual visible space. The browser address bar and tab bar are not included in that calculation. When those bars expand or collapse, the visual viewport changes, but 100vh does not adjust.&lt;/p&gt;

&lt;p&gt;Here is a simple example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"app-shell"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This is the main content area.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;footer&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Footer content here.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/footer&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.app-shell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;  

&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;     
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On mobile, part of the layout will sit behind the browser bar. When you scroll, the bar collapses and the layout suddenly fits. This is the inconsistency developers run into.&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%2Fb5gziknx13eg1rn20ihf.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%2Fb5gziknx13eg1rn20ihf.png" alt="A demo of 100vh issue" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many older articles suggest using webkit-fill-available. This used to work in certain contexts but is unreliable today and does not solve the root issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  100dvh as the fix
&lt;/h2&gt;

&lt;p&gt;A more accurate way to handle full height layouts on mobile is to use the new dynamic viewport unit: &lt;strong&gt;dvh&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dvh stands for dynamic viewport height. It is one of three new viewport units (svh, lvh, dvh). The dynamic version adjusts based on the current visible viewport. If the browser address bar collapses or expands, dvh updates in real time.&lt;/p&gt;

&lt;p&gt;Using our earlier example, the fix looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.app-shell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;     
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="n"&gt;dvh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&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%2Fw6jwsq8nbef3mmqrm3qr.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%2Fw6jwsq8nbef3mmqrm3qr.png" alt="100dvh Fix" width="724" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting the height to 100dvh tells the browser to size the element using the actual visible viewport height. This prevents the layout from slipping behind the browser UI on mobile. &lt;/p&gt;

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

&lt;p&gt;Dvh provides a practical and reliable fix for the long standing 100vh issue on mobile browsers. It responds to changes in the viewport and keeps your layout visible without relying on outdated workarounds. While browser behavior may continue to evolve, dvh is currently the most accurate way to create full height layouts on mobile.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>frontend</category>
    </item>
    <item>
      <title>A Practical Guide to Color Contrast for Web Developers</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 08 Dec 2025 12:09:58 +0000</pubDate>
      <link>https://forem.com/bridget_amana/a-practical-guide-to-color-contrast-for-web-developers-53oi</link>
      <guid>https://forem.com/bridget_amana/a-practical-guide-to-color-contrast-for-web-developers-53oi</guid>
      <description>&lt;p&gt;Color contrast determines the readability of your interface in real-world conditions, affecting everything from quick button taps to long-form reading. You notice this impact most when you are outside with low screen brightness or using a device with a weaker display. &lt;/p&gt;

&lt;p&gt;This is why contrast is not just a design concern; it is a core part of front-end engineering. You already invest time in performance, layout, and stable interactions. Contrast belongs in that same category because it dictates how reliably your UI performs across different environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Contrast Actually Measures
&lt;/h3&gt;

&lt;p&gt;The Web Content Accessibility Guidelines (WCAG) use a formula comparing the relative luminance of two colors to determine visibility. While you do not need to calculate this manually, you must know the targets.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Normal text&lt;/strong&gt; requires a ratio of at least 4.5:1.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Large text&lt;/strong&gt; requires a ratio of at least 3:1.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These values sit on a scale from 1 to 21, where higher numbers represent stronger contrast. Black text on a white background is 21:1, while white on white is 1:1. Most readable color pairs in modern web projects land between 5 and 14.&lt;/p&gt;

&lt;p&gt;These ratios are not arbitrary numbers chosen at random. They are based on how people with different visual acuities perceive brightness. Even users with typical vision lose clarity in low light or outdoor glare, so a pair that passes at 4.5:1 will survive more environmental factors than a pair hovering at 3:1. This is why aiming for the bare minimum works for headlines but often causes readability issues for smaller body text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Contrast While You Work
&lt;/h3&gt;

&lt;p&gt;For immediate feedback, your browser is the fastest tool. By opening DevTools and inspecting a text element, you can view the contrast ratio directly within the accessibility or styles panel. This allows you to catch accessibility bugs early in the process, particularly when you are blocking out layouts or experimenting with new theme colors.&lt;/p&gt;

&lt;p&gt;However, browser DevTools are most accurate for text on flat, solid backgrounds. If your text sits on top of a gradient or a complex image, the browser cannot always calculate the background color reliably, so you will need a dedicated tool.&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%2Ftvqk2q2zzsl0i7xk4v8v.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%2Ftvqk2q2zzsl0i7xk4v8v.png" alt="Chrome DevTools showing low color contrast ratio" width="800" height="460"&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%2Fhzy07xoxpiqf1zf2tjrz.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%2Fhzy07xoxpiqf1zf2tjrz.png" alt="Chrome DevTools showing high color contrast ratio" width="739" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Dedicated Contrast Checkers
&lt;/h3&gt;

&lt;p&gt;Small color swatches can be misleading because some combinations technically meet the math requirements but still look weak in a real interface. Tools like &lt;a href="https://colourcontrast.cc/" rel="noopener noreferrer"&gt;colourcontrast.cc&lt;/a&gt; are valuable here because they update the entire page preview based on your selection.&lt;/p&gt;

&lt;p&gt;This approach lets you see titles, paragraphs, and UI components using the color pair at different scales. It gives you a realistic sense of stability that a simple calculator cannot provide. Sometimes a ratio of 4.7:1 looks fine in isolation but feels too thin once placed inside a dense layout, and seeing it in context helps you make the right judgment call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automating the Workflow
&lt;/h3&gt;

&lt;p&gt;To reduce guesswork across your team, you should integrate automated checks. While linting plugins like &lt;a href="https://www.npmjs.com/package/eslint-plugin-jsx-a11y" rel="noopener noreferrer"&gt;eslint-plugin-jsx-a11y&lt;/a&gt; help catch missing labels, they sometimes struggle to calculate color contrast since they cannot always see your CSS files.&lt;/p&gt;

&lt;p&gt;People often treat accessibility as a separate compliance requirement, but in practice, contrast improves basic usability for everyone. It makes text easier to scan, reduces eye strain, and keeps interfaces clear on older hardware. By treating contrast as a technical constraint rather than just an aesthetic choice, you help make the web a better place.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Finding Open Source Projects to Contribute To</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Mon, 08 Dec 2025 11:46:02 +0000</pubDate>
      <link>https://forem.com/bridget_amana/finding-open-source-projects-to-contribute-to-3aco</link>
      <guid>https://forem.com/bridget_amana/finding-open-source-projects-to-contribute-to-3aco</guid>
      <description>&lt;p&gt;Finding open source projects to contribute to is usually harder than people make it sound. Most articles give the same standard advice which tells you to search for “good first issues” and filter by labels. In reality, this does not always work because maintainers often forget to label issues. Many of the “good first issues” you find belong to old or inactive projects, so you end up wasting time trying to contribute to something no one maintains anymore.&lt;/p&gt;

&lt;p&gt;From my experience, there are much more effective ways to find active work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow Active Contributors
&lt;/h3&gt;

&lt;p&gt;A better approach is to follow active open source people rather than just staring at repositories. When you follow contributors and maintainers you trust, your GitHub feed becomes a powerful tool. You start seeing the pull requests they open, the issues they interact with, and the new projects they star.&lt;/p&gt;

&lt;p&gt;This gives you visibility into living projects instead of abandoned ones. It is much easier to join projects this way because you are walking into a space that already has activity around 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%2Fszsktrse41pjxycjll1n.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%2Fszsktrse41pjxycjll1n.png" alt="GitHub home feed of Bridget Amana" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Contribute by Testing, Not Just Coding
&lt;/h3&gt;

&lt;p&gt;Most people overlook the fact that contributing is not limited to opening pull requests. For my first year in open source, I mostly contributed by testing projects. I would run the project locally, use the features, and actively look for problems.&lt;/p&gt;

&lt;p&gt;These problems could be anything from an accessibility issue or a broken UI on mobile screens to small performance lags or grammar errors in the documentation. All of these details matter. When you find them, open an issue. You can take on a few of them yourself or leave them for other beginners to tackle. This helps maintainers more than you think, and it gets you familiar with the codebase at the same time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Curated Discovery Channels
&lt;/h3&gt;

&lt;p&gt;Another reliable way to find active projects is through trusted Twitter accounts that share open source opportunities. These are the verified accounts I follow:&lt;/p&gt;

&lt;p&gt;-&lt;a href="https://x.com/githubprojects" rel="noopener noreferrer"&gt;GitHub Projects&lt;/a&gt;&lt;br&gt;
-&lt;a href="https://x.com/the_osps" rel="noopener noreferrer"&gt;Open Source Projects&lt;/a&gt;&lt;br&gt;
-&lt;a href="https://x.com/metaopensource" rel="noopener noreferrer"&gt;Meta Open Source&lt;/a&gt;&lt;br&gt;
-&lt;a href="https://x.com/tom_doerr" rel="noopener noreferrer"&gt;Tom Doerr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They post a wide range of projects with different tech stacks, so you can choose something that matches your current skill level or interests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Ignore Small Projects
&lt;/h3&gt;

&lt;p&gt;I always tell beginners not to ignore small projects. Many people only want to contribute to popular repositories with thousands of stars, but those projects started small too.&lt;/p&gt;

&lt;p&gt;Smaller projects are usually more open to beginners and have maintainers who respond faster. You often learn the most in places where you are not competing with hundreds of other contributors. Start small to build your experience, and then move into larger communities when you feel ready.&lt;/p&gt;

&lt;p&gt;Finding projects is not always straightforward, but there are better ways than relying on labels. Follow active contributors, test real projects, open issues, and do not overlook the smaller repos. This approach keeps you in the flow of active work and leads to more meaningful contributions.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Soft skills can be learned too</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Sun, 07 Dec 2025 02:01:53 +0000</pubDate>
      <link>https://forem.com/bridget_amana/soft-skills-can-be-learned-too-3n26</link>
      <guid>https://forem.com/bridget_amana/soft-skills-can-be-learned-too-3n26</guid>
      <description>&lt;p&gt;There is nothing more frustrating than watching someone who seems naturally good with people. You see them enter a room and everything shifts a little. They connect easily, they say the right things without forcing it. It feels almost like they have access to a script the rest of us never got.&lt;/p&gt;

&lt;p&gt;When we see this, it feels unfair. It feels like something they were born with. So we tell ourselves a story. We say, &lt;em&gt;"That’s just who they are"&lt;/em&gt; or &lt;em&gt;"I’m not wired like that."&lt;/em&gt; We act as if personality is fixed, like a gift only a few people have.&lt;/p&gt;

&lt;p&gt;But the more I pay attention, the more that idea stops making sense.&lt;/p&gt;

&lt;p&gt;Most of the things we are good at today were once things we knew nothing about. We learned them slowly, by trying, failing, and adjusting. We accept this in almost every part of our life, yet when it comes to social skills, confidence, or communication, we convince ourselves it is different.&lt;/p&gt;

&lt;p&gt;The people who look "natural" have just been practicing longer, even if they didn’t realize it. They paid attention to how others responded to them, they corrected themselves, they tried again. Over time, those efforts blended into habits that look effortless from the outside.&lt;/p&gt;

&lt;p&gt;What we call charisma or confidence is usually a collection of small behaviors. Making eye contact, listening fully, speaking with intention instead of rushing, showing genuine curiosity. These are not personality traits. They are skills, and skills can be learned.&lt;/p&gt;

&lt;p&gt;Once you stop treating your personality like something you were handed at birth, you gain control. You can notice the parts of yourself you want to strengthen and work on them piece by piece. You can model people you admire. You can improve without trying to become someone else.&lt;/p&gt;

&lt;p&gt;If you treat growth as something you participate in, not something that happens to you, things change. The gap between you and the people you think are miles ahead becomes smaller and far less intimidating.&lt;/p&gt;

&lt;p&gt;I still catch myself comparing and thinking others are just "born that way." But then I remember the small habits I’ve quietly developed and I see that the gap isn’t unbridgeable.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Exploring native Browser/Web APIs</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Tue, 02 Dec 2025 19:44:44 +0000</pubDate>
      <link>https://forem.com/bridget_amana/exploring-native-browserweb-apis-2mj8</link>
      <guid>https://forem.com/bridget_amana/exploring-native-browserweb-apis-2mj8</guid>
      <description>&lt;p&gt;Most frontend projects rely heavily on REST APIs. We fetch data, handle the loading state, and display lists. While this is an essential skill, it ignores a large part of what the browser can do.&lt;/p&gt;

&lt;p&gt;I recently saw a tweet about using native Browser APIs to build more interesting projects. I wanted to try this myself, but I found it difficult to find good project ideas. Most documentation provides syntax examples but rarely explains what you can actually build with them.&lt;/p&gt;

&lt;p&gt;I created a site to solve this. It serves as a collection of browser APIs, resources, and specific project ideas for each one.&lt;/p&gt;

&lt;p&gt;&lt;a href="//bridgetamana.github.io/web-api-project-ideas/"&gt;You can view it 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%2F8eouxuyrq0d04k6nsgvm.jpeg" 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%2F8eouxuyrq0d04k6nsgvm.jpeg" alt="web api site" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is inside
&lt;/h2&gt;

&lt;p&gt;For each API, I included the MDN documentation, a couple of resources and a few project ideas. This will be updated as I find more project ideas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Browser APIs
&lt;/h2&gt;

&lt;p&gt;Focusing on these APIs requires a different approach than standard data fetching. You have to manage permissions, handle real-time events, and interact with device hardware. Asides from it being fun, it is a practical way to understand the web better.&lt;/p&gt;

&lt;p&gt;I am using this list to guide my own learning. I plan to update it as I discover more APIs and use cases.&lt;/p&gt;

&lt;p&gt;If you are looking for a new project to build, you can check out the full list here.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>api</category>
    </item>
    <item>
      <title>Introducing SnippetShot – A VS Code Extension for Clean Code Screenshots</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Thu, 11 Sep 2025 23:25:39 +0000</pubDate>
      <link>https://forem.com/bridget_amana/introducing-snippetshot-a-vs-code-extension-for-clean-code-screenshots-8dm</link>
      <guid>https://forem.com/bridget_amana/introducing-snippetshot-a-vs-code-extension-for-clean-code-screenshots-8dm</guid>
      <description>&lt;p&gt;As someone who tweets often and builds in public, I regularly need to show a part or snippet of my code. I’ve always done this by copying the code and using tools like ray.so or Polacode.&lt;/p&gt;

&lt;p&gt;For those who don’t know, Polacode is a Visual Studio Code extension for creating code screenshots. I love the tool, but it’s a bit buggy, and since the maintainer is no longer active, those bugs remain. So I decided to build my own.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Bridget.snippetshot" rel="noopener noreferrer"&gt;SnippetShot&lt;/a&gt; is a free VS Code extension that lets you turn code into clean, shareable images in seconds. Copy your code, open SnippetShot, and export a styled PNG without leaving your editor. That’s how easy it is.&lt;/p&gt;

&lt;p&gt;SnippetShot is an updated version of Polacode, so if you were a fan of Polacode, this is the tool for 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%2F3d77rwdmstcpqmwwa8oy.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%2F3d77rwdmstcpqmwwa8oy.png" alt="code screenshot taken with snippetshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customizable background. Pick any color to match your style or branding.&lt;/li&gt;
&lt;li&gt;Line numbers toggle. Show or hide line numbers as you please.&lt;/li&gt;
&lt;li&gt;Add custom credits or text to your screenshot.&lt;/li&gt;
&lt;li&gt;Twitter/X sharing. Instantly copy your image and share it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;To install the extension, click the Extensions icon on the left sidebar of your editor to open the marketplace, then search for &lt;em&gt;SnippetShot&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;After installing, open the command palette. On Windows, use &lt;code&gt;Ctrl+P&lt;/code&gt;. On Mac, use &lt;code&gt;Cmd+Shift+P&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open any file with code. Select the code, and it will appear in the editor’s right panel where SnippetShot is open.&lt;/li&gt;
&lt;li&gt;From there, you can change the background color, toggle line numbers, and add your name.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt; or &lt;strong&gt;Share to Twitter&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/6EhfJ6yKfPA"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;SnippetShot also supports gradient backgrounds for more flexibility in styling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: There’s another tool out there with a similar name, but mine is a pure VS Code extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Download the extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=Bridget.snippetshot" rel="noopener noreferrer"&gt;here&lt;/a&gt;. I also just launched on &lt;a href="https://www.producthunt.com/products/snippetshot" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt;. If you find it useful, please give it an upvote there and a star on &lt;a href="https://github.com/Bridgetamana/SnippetShot-" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vscode</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Fri, 05 Sep 2025 11:46:26 +0000</pubDate>
      <link>https://forem.com/bridget_amana/-2bm6</link>
      <guid>https://forem.com/bridget_amana/-2bm6</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b" class="crayons-story__hidden-navigation-link"&gt;AI Agent for Google Play Review Monitoring&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;n8n and Bright Challenge: Unstoppable Workflow&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/bridget_amana" 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%2F1693394%2Fc6a753fe-84d8-43e2-a37d-cc4746818e59.png" alt="bridget_amana profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/bridget_amana" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Bridget Amana
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Bridget Amana
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-2810497" 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="/bridget_amana" 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%2F1693394%2Fc6a753fe-84d8-43e2-a37d-cc4746818e59.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Bridget Amana&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/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 31 '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/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b" id="article-link-2810497"&gt;
          AI Agent for Google Play Review Monitoring
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/n8nbrightdatachallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;n8nbrightdatachallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&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;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;28&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b#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>devchallenge</category>
      <category>n8nbrightdatachallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>AI Agent for Google Play Review Monitoring</title>
      <dc:creator>Bridget Amana</dc:creator>
      <pubDate>Sun, 31 Aug 2025 08:24:10 +0000</pubDate>
      <link>https://forem.com/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b</link>
      <guid>https://forem.com/bridget_amana/ai-agent-for-google-play-review-monitoring-2p9b</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/brightdata-n8n-2025-08-13"&gt;AI Agents Challenge powered by n8n and Bright Data&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a workflow that takes reviews of an app from Google Play, runs sentiment analysis on them, and routes them based on the results. Positive reviews get logged for tracking, while negative ones are flagged so they can be acted on. The whole point was to create an automated system that helps teams quickly understand how users feel about their app without going through hundreds of reviews manually. To make it practical, I used Temu as the app for testing&lt;/p&gt;

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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/7pn68kyieAQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  n8n Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/Bridgetamana/5dca5f1376803f44424a963d95c6173f" rel="noopener noreferrer"&gt;Github Gist&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Implementation
&lt;/h2&gt;

&lt;p&gt;I started by connecting Bright Data’s Web Scraper node in n8n to Google Play. My first challenge was figuring out the correct URL setup to fetch reviews. I realized I needed to scrape by the app’s URL and then create a dataset node to structure the review data.&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%2Fbyfro7ehhwpv8a0skzfn.jpeg" 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%2Fbyfro7ehhwpv8a0skzfn.jpeg" alt="N8n workflow with bright data "&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%2Fjvfygf7f84zeci58eagb.jpeg" 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%2Fjvfygf7f84zeci58eagb.jpeg" alt="n8n workflow with bright data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the reviews came in, I needed a way to handle them individually. I used n8n’s &lt;strong&gt;Split Out Items&lt;/strong&gt; node to break the dataset into separate review objects. At first, I struggled with which fields to split, but including only the review text solved the problem. Later on, I discovered a feature inside Bright Data’s actions: &lt;em&gt;Split snapshots data to parts by snapshot id&lt;/em&gt;, which would have done exactly what I did with split out.&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%2F9688ex0yxj4sh17rla2q.jpeg" 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%2F9688ex0yxj4sh17rla2q.jpeg" alt="n8n screenshot showing bright data action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For sentiment analysis, I connected n8n’s AI Agent node with &lt;strong&gt;OpenAI GPT-4.1-MINI&lt;/strong&gt;. The prompt I used was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given the following review {{ $json.review }}, return a JSON with: {sentiment: ..., summary: ..., key_issue: ...}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked, but I had to tweak the output handling to make sure it returned proper JSON that n8n could actually parse.&lt;/p&gt;

&lt;p&gt;Next came the routing logic. I wanted negative reviews to go to the team for action and positive ones to just be logged. Using an IF node, I set the condition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{{ $json["message"]["content"]["sentiment"] }} == "Negative"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fpdm6s2m07zhb7m3dvn0f.jpeg" 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%2Fpdm6s2m07zhb7m3dvn0f.jpeg" alt="n8n workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first I ran into false branches because I wasn’t using expressions correctly, but once I switched to using proper expressions, it started working as expected.&lt;/p&gt;

&lt;p&gt;Finally, I logged everything into Google Sheets. Each row had the Sentiment, Summary, and Key Issue fields.&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%2Froicw03n4jhc132z2o61.jpeg" 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%2Froicw03n4jhc132z2o61.jpeg" alt="Google sheet displaying the parsed app reviews"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Bright Data Verified Node
&lt;/h3&gt;

&lt;p&gt;Bright Data’s verified node is what made this workflow possible. At first, I wasn’t fully clear on what Bright Data was or how to really use it. I joined the live demo session and got a few pointers, but I was still confused until I stumbled on a video that broke it all down. That video is what unlocked things for me, so if you’re new to Bright Data, I recommend watching it first.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/vKjokuht2n0?start=1"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Once I had the node running, it was straightforward to fetch reviews directly from the Google Play page. The dataset it produced was clean enough to connect with other parts of n8n, which made the later steps; splitting, analysis, and routing, much easier to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;This was my first real attempt at using Bright Data with n8n, and it didn’t go perfectly at first. I spent time figuring out URL structures, how datasets worked, and how to properly handle outputs from AI. There were moments where I thought I had broken the workflow entirely, but each roadblock helped me learn how n8n’s nodes actually work in practice.&lt;/p&gt;

&lt;p&gt;The biggest lightbulb moment was discovering Bright Data’s snapshot split feature, which made structuring data far simpler. Another one was realizing how much expressions matter inside n8n. Without setting them correctly, conditions and mappings just don’t behave the way you expect.&lt;/p&gt;

&lt;p&gt;If I were to redo this, I’d start by setting up a proper schema for how I wanted the data to flow before building the workflow itself. That would have saved me a lot of time. Still, the process taught me how powerful Bright Data and n8n can be together when you use them right.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>n8nbrightdatachallenge</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
