<?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: Pete Benoit</title>
    <description>The latest articles on DEV Community by Pete Benoit (@peterbenoit).</description>
    <link>https://dev.to/peterbenoit</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%2F304189%2F9f727bae-c59c-4ab2-980a-c19e6fbf83fb.jpg</url>
      <title>DEV Community: Pete Benoit</title>
      <link>https://dev.to/peterbenoit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peterbenoit"/>
    <language>en</language>
    <item>
      <title>The First Thing I Do When I Open a Project</title>
      <dc:creator>Pete Benoit</dc:creator>
      <pubDate>Fri, 10 Apr 2026 13:40:14 +0000</pubDate>
      <link>https://dev.to/peterbenoit/the-first-thing-i-do-when-i-open-a-project-2ejo</link>
      <guid>https://dev.to/peterbenoit/the-first-thing-i-do-when-i-open-a-project-2ejo</guid>
      <description>&lt;p&gt;There's a specific kind of blank-stare moment many developers know. You open a project, something you cloned, something you built yourself last spring, and you just stare. The code is right there. The context is completely gone.&lt;/p&gt;

&lt;p&gt;I built a VS Code extension called Explain This Project to solve this.&lt;/p&gt;

&lt;p&gt;One command gives you structure analysis, dependency mapping, git diagnostics showing which files break the most, and a plain-text summary via Copilot. All in one file at your project root.&lt;/p&gt;

&lt;p&gt;I recently added git diagnostics after reading a great post by Ally Piechowski on the git commands she runs before reading any code. I thought it was an amazing idea, and added it to my extension.&lt;/p&gt;

&lt;p&gt;You can read more about it here.&lt;/p&gt;

&lt;p&gt;peterbenoit.com/blog/first-thing-open-project&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>extensions</category>
      <category>git</category>
      <category>development</category>
    </item>
    <item>
      <title>CSS @starting-style: Animating Elements Into Existence</title>
      <dc:creator>Pete Benoit</dc:creator>
      <pubDate>Wed, 25 Mar 2026 15:00:43 +0000</pubDate>
      <link>https://dev.to/peterbenoit/css-starting-style-animating-elements-into-existence-15ad</link>
      <guid>https://dev.to/peterbenoit/css-starting-style-animating-elements-into-existence-15ad</guid>
      <description>&lt;p&gt;The enter animation problem has been with us since CSS transitions were invented. &lt;code&gt;@starting-style&lt;/code&gt; finally gives us a clean, declarative solution.&lt;/p&gt;

&lt;p&gt;There's a class of bug that every CSS developer encounters eventually, usually while trying to animate a toast notification or a dialog. You add the element to the DOM, apply the transition, and… nothing. The element snaps in instantly, ignoring the transition entirely.&lt;/p&gt;

&lt;p&gt;The reason is simple once you understand it: CSS transitions animate between two computed states. When an element is first inserted, there is no previous state. The browser has nothing to interpolate from, so the transition is skipped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The old workarounds&lt;/strong&gt;&lt;br&gt;
Most of us reached for the same duct-tape solutions. Force a reflow, then set the target state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Option 1: setTimeout (fragile, tied to frame timing)&lt;/span&gt;
&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Option 2: requestAnimationFrame (better, still manual)&lt;/span&gt;
&lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Option 3: force reflow by reading layout property&lt;/span&gt;
&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of these work, in the sense that they produce the animation. None of them feel right. They're coupling timing to the rendering pipeline in ways that are hard to test, hard to reason about, and easy to break with a browser update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter &lt;code&gt;@starting-style&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
The @starting-style rule, now in Baseline 2024, lets you declare what an element's computed style should be treated as on its very first render. It gives the browser a "from" state to animate from, without any JavaScript.&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="c"&gt;/* The element's normal state */&lt;/span&gt;
&lt;span class="nc"&gt;.toast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;opacity&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="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;opacity&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* How the browser treats this element on its first render */&lt;/span&gt;
&lt;span class="k"&gt;@starting-style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.toast&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-0.75rem&lt;/span&gt;&lt;span class="p"&gt;);&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;That's it. Add the element to the DOM, give it the class .toast, and the browser automatically transitions from the &lt;code&gt;@starting-style&lt;/code&gt; declarations to the element's computed style. No JavaScript timing tricks required.&lt;/p&gt;

&lt;p&gt;Keep Reading about @starting-style on: &lt;a href="https://www.peterbenoit.com/blog/css-starting-style" rel="noopener noreferrer"&gt;peterbenoit.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>nocode</category>
      <category>learning</category>
    </item>
    <item>
      <title>Liquid Glass UI in CSS Only</title>
      <dc:creator>Pete Benoit</dc:creator>
      <pubDate>Mon, 16 Jun 2025 10:31:58 +0000</pubDate>
      <link>https://dev.to/peterbenoit/liquid-glass-ui-in-css-only-jo4</link>
      <guid>https://dev.to/peterbenoit/liquid-glass-ui-in-css-only-jo4</guid>
      <description>&lt;p&gt;Apple recently introduced “Liquid Glass” as part of its new UI design language. It’s a translucent visual style that reflects and refracts its surroundings and adapts to light and content behind it. Since it’s been all over my feed, I wanted to see how close I could get to the effect using just CSS.&lt;/p&gt;

&lt;p&gt;No images, no JavaScript frameworks, no canvas tricks. Just a clean CSS-based implementation using two core properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mix-blend-mode: difference for automatic contrast&lt;/li&gt;
&lt;li&gt;backdrop-filter: blur for that frosted-glass depth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they let text and UI elements stay legible on any background without explicitly setting color logic. I also added a draggable button with a subtle jiggle to hint that it’s interactive.&lt;/p&gt;

&lt;p&gt;This isn’t a one-to-one recreation, but it captures the spirit of what Apple’s going for in a way that’s simple and performance friendly for the web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://codepen.io/peterbenoit/live/qEdYxyL" rel="noopener noreferrer"&gt;https://codepen.io/peterbenoit/live/qEdYxyL&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>liquidglass</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Manage duplicates in your Bitwarden Vault with Python</title>
      <dc:creator>Pete Benoit</dc:creator>
      <pubDate>Sat, 04 Jan 2025 00:50:13 +0000</pubDate>
      <link>https://dev.to/peterbenoit/manage-duplicates-in-your-bitwarden-vault-with-python-5f00</link>
      <guid>https://dev.to/peterbenoit/manage-duplicates-in-your-bitwarden-vault-with-python-5f00</guid>
      <description>&lt;p&gt;Bitwarden doesn't have a built-in method for managing duplicates in your vault. I wasn't happy with the other user-made libraries I found, so I went and created a Python-based tool to help automate the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Filter entries by type: Login, Secure Note, Card, or Identity.&lt;/li&gt;
&lt;li&gt;Identify and export duplicates for review.&lt;/li&gt;
&lt;li&gt;Save unique entries in a cleaned JSON file.&lt;/li&gt;
&lt;li&gt;Interactive or CLI-based configuration for flexibility.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Export your Bitwarden vault into JSON and run the tool, you can categorize entries based on customizable criteria using an interactive shell script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use This Tool?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Simplifies vault management.&lt;/li&gt;
&lt;li&gt;Works directly with Bitwarden JSON exports.&lt;/li&gt;
&lt;li&gt;Fully customizable and extensible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;To get started, clone the repository and run the shell script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/peterbenoit/Bitwarden-Deduplicator
&lt;span class="nb"&gt;cd &lt;/span&gt;Bitwarden-Deduplicator
./run_python.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script sets up a virtual environment, installs dependencies, and guides you through the configuration process.&lt;/p&gt;

</description>
      <category>bitwarden</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Demo: The Doggo Image Slider</title>
      <dc:creator>Pete Benoit</dc:creator>
      <pubDate>Sun, 06 Oct 2024 18:00:06 +0000</pubDate>
      <link>https://dev.to/peterbenoit/demo-the-doggo-image-slider-kd6</link>
      <guid>https://dev.to/peterbenoit/demo-the-doggo-image-slider-kd6</guid>
      <description>&lt;p&gt;This project is built using React for managing the component state and rendering, Axios for fetching data from the Dog API, and Tailwind CSS for styling, including a glassmorphic effect on the UI. The slider is fully configurable, allowing dynamic control over the slide speed and looping behavior. React's useState and useEffect hooks manage state updates and side effects like fetching images and handling the auto-slide feature. The useRef hook is used to handle and reset the slide timer efficiently. The design leverages Tailwind’s utility classes for smooth transitions, hover effects, and responsive design, creating a modern, flexible, and highly interactive UI.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/peterbenoit/embed/dyxXyYy?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
    </item>
  </channel>
</rss>
