<?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: Mía Salazar</title>
    <description>The latest articles on DEV Community by Mía Salazar (@miasalazar).</description>
    <link>https://dev.to/miasalazar</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%2F708072%2Fe084321a-e4bb-48d7-a464-5a3b114e1973.jpg</url>
      <title>DEV Community: Mía Salazar</title>
      <link>https://dev.to/miasalazar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/miasalazar"/>
    <language>en</language>
    <item>
      <title>How to Improve Performance in React Applications</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Fri, 27 Mar 2026 12:22:38 +0000</pubDate>
      <link>https://dev.to/miasalazar/how-to-improve-performance-in-react-applications-4f40</link>
      <guid>https://dev.to/miasalazar/how-to-improve-performance-in-react-applications-4f40</guid>
      <description>&lt;p&gt;Optimizing performance in React applications is essential to create smooth, fast, and responsive user experiences. React’s flexibility and component-based architecture allow developers to implement various strategies to enhance performance.&lt;/p&gt;

&lt;p&gt;In this article, we’ll explore key techniques such as dynamic imports, list virtualization, and others to help you boost your app’s speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Imports: Code Splitting for Faster Load Times
&lt;/h2&gt;

&lt;p&gt;One of the most effective performance optimizations in React is code splitting, which allows you to load JavaScript files only when needed. This can drastically reduce the initial load time, especially for large applications. React’s dynamic imports enable you to load components and modules on demand, which means users only download the code they need.&lt;/p&gt;

&lt;p&gt;With dynamic imports, you can split your application into smaller chunks and only load parts of the app when required. For example, you might load a component for a specific route only when the user navigates to it, rather than including it in the initial bundle.&lt;/p&gt;

&lt;p&gt;By implementing dynamic imports, you improve your app’s initial loading time and reduce the amount of unnecessary code loaded upfront.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Suspense } from 'react';

const LazyLoadedComponent = React.lazy(() =&amp;gt; import('./LazyLoadedComponent'));

function App() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;}&amp;gt;
        &amp;lt;LazyLoadedComponent /&amp;gt;
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  List Virtualization: Rendering Only What’s Visible
&lt;/h2&gt;

&lt;p&gt;In applications that display large lists of data, rendering every single item at once can be a performance bottleneck. List virtualization solves this problem by only rendering the items visible on the screen at any given time, drastically reducing the number of DOM elements.&lt;/p&gt;

&lt;p&gt;Libraries like &lt;a href="https://www.npmjs.com/package/react-window" rel="noopener noreferrer"&gt;react-window&lt;/a&gt; help implement list virtualization by rendering a small subset of items based on the visible area, improving rendering speed and reducing memory usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memoize Expensive Calculations with useMemo
&lt;/h2&gt;

&lt;p&gt;If you perform heavy calculations or transformations (like sorting, filtering, or mapping large arrays), memoize the result with useMemo so it's only recalculated when the inputs change.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const sortedList = useMemo(() =&amp;gt; {
  return items.sort((a, b) =&amp;gt; a.name.localeCompare(b.name));
}, [items]);

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids unnecessary recalculations on every render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preload Critical Resources
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; or tools like &lt;code&gt;React Helmet&lt;/code&gt; to preload fonts, critical images, or even API data you know the user will need immediately. This can significantly reduce LCP and improve perceived performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart Data Fetching with React Query
&lt;/h2&gt;

&lt;p&gt;Managing server state efficiently is key to performance. Instead of manually fetching and storing data in state variables, libraries like React Query handle caching, background refetching, and request deduplication out of the box.&lt;/p&gt;

&lt;p&gt;React Query can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache requests and avoid redundant fetches.&lt;/li&gt;
&lt;li&gt;Refetch data in the background without blocking the UI.&lt;/li&gt;
&lt;li&gt;Handle loading, error, and success states automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Optimize Images and Assets
&lt;/h2&gt;

&lt;p&gt;Large or unoptimized images are one of the most common causes of slow-loading apps. To avoid this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use modern formats like WebP or AVIF&lt;/li&gt;
&lt;li&gt;Compress images before loading&lt;/li&gt;
&lt;li&gt;Use lazy loading (&lt;code&gt;&amp;lt;img loading="lazy" /&amp;gt;&lt;/code&gt;) for below-the-fold images&lt;/li&gt;
&lt;li&gt;Leverage responsive images with srcSet for different screen sizes
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;picture&amp;gt;
  &amp;lt;source media="(min-width:768px)" srcset="flowers-tablet.jpg"&amp;gt;
  &amp;lt;img src="ppizza.jpg" alt="Pozza" style="width:auto;"&amp;gt;
&amp;lt;/picture&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keep Components Small and Focused
&lt;/h2&gt;

&lt;p&gt;Smaller components are easier to optimize, understand, and reuse. If a component does too many things, it’s more likely to re-render often. Split logic-heavy components into smaller children where only relevant parts update.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analyze and Monitor with Performance Tools
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lighthouse (via Chrome DevTools or CI)&lt;/li&gt;
&lt;li&gt;Web Vitals extension&lt;/li&gt;
&lt;li&gt;React Profiler&lt;/li&gt;
&lt;li&gt;Sentry/Datadog for performance monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Measure, benchmark, and monitor performance to track regressions over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use useEffect and useCallback Wisely
&lt;/h2&gt;

&lt;p&gt;React’s &lt;code&gt;useEffect&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt; hooks are powerful, but they can easily become sources of performance issues if not used thoughtfully. &lt;/p&gt;

&lt;p&gt;With useEffect, it's important to limit side effects to what’s necessary and avoid including unstable dependencies (like inline functions or objects) unless absolutely required. This reduces the risk of unnecessary re-renders or even infinite loops. Also, always clean up subscriptions or event listeners inside effects to prevent memory leaks.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;code&gt;useCallback&lt;/code&gt; helps memoize functions so they retain a stable reference between renders, useful when passing callbacks to memoized child components or when including functions as dependencies in useEffect. However, overusing &lt;code&gt;useCallback&lt;/code&gt; can clutter your code and offer little benefit if the function isn’t passed as a prop or used in dependency arrays.&lt;/p&gt;

&lt;p&gt;In short, use &lt;code&gt;useEffect&lt;/code&gt; to manage external interactions and side effects with minimal, clear logic, and reserve &lt;code&gt;useCallback&lt;/code&gt; for stabilizing functions that really need it. Used wisely, these hooks help you keep your components performant and predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Performance optimization in React is not just about writing faster code. It's about making thoughtful architectural choices, leveraging the right tools, and reducing unnecessary work for the browser.&lt;/p&gt;

&lt;p&gt;Focus on rendering only what’s needed, when it’s needed, and keep an eye on the network, re-renders, and the structure of your components. With these strategies in place, you’ll create React apps that are not only functional but delightfully fast.&lt;/p&gt;

</description>
      <category>react</category>
      <category>frontend</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Writing Scalable and Maintainable CSS: BEM, SMACSS and OOCSS</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Thu, 12 Mar 2026 10:27:09 +0000</pubDate>
      <link>https://dev.to/miasalazar/writing-scalable-and-maintainable-css-bem-smacss-and-oocss-omj</link>
      <guid>https://dev.to/miasalazar/writing-scalable-and-maintainable-css-bem-smacss-and-oocss-omj</guid>
      <description>&lt;p&gt;Managing CSS at scale is one of the hardest challenges in front-end development. As projects grow, CSS can easily become brittle, hard to maintain, and prone to unintended side effects due to excessive inheritance and uncontrolled specificity. &lt;/p&gt;

&lt;p&gt;This article introduces some popular methodologies: BEM, SMACSS, and OOCSS, and explains how they help create scalable, modular CSS architectures with clear naming conventions, low specificity, and better separation of concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Cascading and Specificity
&lt;/h2&gt;

&lt;p&gt;CSS was designed to cascade, but uncontrolled cascading often leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep selector chains (.header .menu ul li a span { ... })&lt;/li&gt;
&lt;li&gt;Overuse of !important&lt;/li&gt;
&lt;li&gt;Inheritance leaks causing unintended style changes&lt;/li&gt;
&lt;li&gt;Difficulty overriding styles without breaking existing layouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When stylesheets become difficult to predict or extend, developers start fearing changes. The key is to avoid deeply nested selectors and manage specificity explicitly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Modular CSS Architecture
&lt;/h2&gt;

&lt;p&gt;A modular CSS approach aims to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create independent, reusable components&lt;/li&gt;
&lt;li&gt;Minimise selector specificity&lt;/li&gt;
&lt;li&gt;Clearly separate structure (layout, positioning) from skin (visual appearance)&lt;/li&gt;
&lt;li&gt;Use consistent naming conventions&lt;/li&gt;
&lt;li&gt;Avoid over-reliance on inheritance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s explore some well-known methodologies that encourage this.&lt;/p&gt;

&lt;h2&gt;
  
  
  BEM
&lt;/h2&gt;

&lt;p&gt;BEM stands for Block Element Modifier, and it works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Block: the standalone entity (e.g. &lt;code&gt;card&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Element: a part of the block (e.g. &lt;code&gt;card__header&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Modifier: a variant or state (e.g. &lt;code&gt;card--highlighted&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BEM creates predictable class names with low specificity and no dependence on DOM structure or nesting. Besides, the low specificity makes these class names easy to override and compose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="card card--highlighted"&amp;gt;
  &amp;lt;div class="card__header"&amp;gt;Title&amp;lt;/div&amp;gt;
  &amp;lt;div class="card__content"&amp;gt;Content here&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  SMACSS
&lt;/h2&gt;

&lt;p&gt;Scalable and Modular Architecture for CSS (SMACSS) categorises CSS rules into five types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base: default browser styles (typography, resets).&lt;/li&gt;
&lt;li&gt;Layout: large structural areas (grid, header, footer).&lt;/li&gt;
&lt;li&gt;Module: reusable components (cards, buttons, forms).&lt;/li&gt;
&lt;li&gt;State: UI states (.is-active, .is-hidden).&lt;/li&gt;
&lt;li&gt;Theme: visual skins.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SMACSS encourages separation of concerns, promoting reusability and scalability, and it helps organise large codebases logically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* layout/_header.scss */
.header { ... }

/* module/_card.scss */
.card { ... }

/* state/_visibility.scss */
.is-hidden { display: none; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  OOCSS
&lt;/h2&gt;

&lt;p&gt;Object-Oriented CSS (OOCSS) promotes splitting styles into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure (object): layout and positioning.&lt;/li&gt;
&lt;li&gt;Skin: colours, fonts, shadows, borders.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OOCSS encourages thinking of UI as reusable "objects" that can be extended visually through skins. It creates highly reusable elements, separating layout and appearance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* structure */
.box { display: block; padding: 1rem; }

/* skin */
.box--primary { background-color: blue; color: white; }
.box--secondary { background-color: grey; color: black; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Managing Specificity and Avoiding Excessive Inheritance
&lt;/h2&gt;

&lt;p&gt;All these methodologies share common goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit specificity: Prefer simple class selectors over IDs or long chains.&lt;/li&gt;
&lt;li&gt;Avoid deep nesting: Don’t rely on parent-child structures (.nav .list .item .link), flat selectors are easier to override.&lt;/li&gt;
&lt;li&gt;Use consistent naming: BEM-style or SMACSS naming conventions make styles easy to locate and modify.&lt;/li&gt;
&lt;li&gt;Separate structure and skin: Keep layout and visual design decoupled.&lt;/li&gt;
&lt;li&gt;Use utility classes for global states: e.g. &lt;code&gt;.is-disabled&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;BEM, SMACSS, and OOCSS are not mutually exclusive: they share complementary principles that help you write predictable, maintainable, and scalable CSS. By embracing flat class-based selectors, separating concerns, and managing specificity, your front-end code will remain robust even as your project grows.&lt;/p&gt;

&lt;p&gt;A clear modular architecture with naming conventions not only improves maintainability but also fosters team collaboration and confidence in styling changes.&lt;/p&gt;

</description>
      <category>css</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>html</category>
    </item>
    <item>
      <title>Multiple header, footer, and h1 Elements: What Is Actually Accessible?</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Fri, 20 Feb 2026 15:18:07 +0000</pubDate>
      <link>https://dev.to/miasalazar/multiple-header-footer-and-h1-elements-what-is-actually-accessible-5c2e</link>
      <guid>https://dev.to/miasalazar/multiple-header-footer-and-h1-elements-what-is-actually-accessible-5c2e</guid>
      <description>&lt;p&gt;Questions about how many &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;, or &lt;code&gt;h1&lt;/code&gt; elements are allowed in a page are extremely common in web development, and they are often framed as strict accessibility rules. In reality, accessibility is less about counting elements and more about &lt;strong&gt;meaning, structure, and relationships&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article clarifies what is valid, what is accessible, and what actually matters when using &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;, and &lt;code&gt;h1&lt;/code&gt; elements in a single document.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Principle: Semantics Over Superstition
&lt;/h2&gt;

&lt;p&gt;HTML is not a set of fragile rules that break accessibility when slightly bent. It is a semantic language designed to describe the structure of a document.&lt;/p&gt;

&lt;p&gt;The key question is not "how many of these elements am I allowed to use?",  but rather "Do these elements accurately describe the structure of the content?".&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple &lt;code&gt;header&lt;/code&gt; Elements
&lt;/h2&gt;

&lt;p&gt;Is it allowed? Yes. You can have &lt;strong&gt;multiple &lt;code&gt;header&lt;/code&gt; elements&lt;/strong&gt; in a single document. A &lt;code&gt;header&lt;/code&gt; represents introductory content for its nearest sectioning ancestor, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;body&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;main&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;article&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;section&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nav&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&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;header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Site name&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;article&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;h2&amp;gt;&lt;/span&gt;Article title&lt;span class="nt"&gt;&amp;lt;/h2&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;p&amp;gt;&lt;/span&gt;Article content…&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This structure is both valid HTML and accessible. Each &lt;code&gt;header&lt;/code&gt; introduces its own section. Screen readers expose headers as structural landmarks tied to their sections. Multiple headers are not confusing when the hierarchy is clear.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple &lt;code&gt;footer&lt;/code&gt; Elements
&lt;/h2&gt;

&lt;p&gt;Is it allowed? Also yes. Like &lt;code&gt;header&lt;/code&gt;, the &lt;code&gt;footer&lt;/code&gt; element is &lt;strong&gt;section-scoped&lt;/strong&gt;. A &lt;code&gt;footer&lt;/code&gt; contains information related to its nearest ancestor section, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Author information&lt;/li&gt;
&lt;li&gt;Related links&lt;/li&gt;
&lt;li&gt;Metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&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;article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Post content…&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;p&amp;gt;&lt;/span&gt;Written by Alex&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;/article&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;© 2026 Example site&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Screen readers announce footers as landmarks only when they are top-level. Nested footers are treated as part of their section, which is expected behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple &lt;code&gt;h1&lt;/code&gt; Elements
&lt;/h2&gt;

&lt;p&gt;Is it allowed? A really strong yes. HTML5 explicitly allows &lt;strong&gt;multiple &lt;code&gt;h1&lt;/code&gt; elements&lt;/strong&gt;. Each &lt;code&gt;h1&lt;/code&gt; represents the top heading of its &lt;strong&gt;sectioning context&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&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;main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Article title&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Introduction&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Another article&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Overview&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Real Accessibility Question About Headings
&lt;/h2&gt;

&lt;p&gt;The real issue is not the number of &lt;code&gt;h1&lt;/code&gt;s, but whether the &lt;strong&gt;heading hierarchy makes sense&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A good heading structure involves headings that reflect the content structure, that levels are not skipped arbitrarily, and sections are clearly defined&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Poor Heading Structure

&amp;lt;h1&amp;gt;Main title&amp;lt;/h1&amp;gt;
&amp;lt;h4&amp;gt;Subsection&amp;lt;/h4&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skipping levels creates confusion for screen reader users who navigate by headings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Screen Readers and Navigation
&lt;/h2&gt;

&lt;p&gt;Many assistive technology users navigate pages by headings, landmarks or regions. Proper use of &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;, and heading levels enables faster navigation, clear mental models of the page and predictable reading order&lt;/p&gt;

&lt;p&gt;The problem is not multiplicity: it is &lt;strong&gt;misrepresentation&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Guidelines
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;header&lt;/code&gt; and &lt;code&gt;footer&lt;/code&gt; elements should be used to introduce or conclude meaningful sections of content, not as generic wrappers. Headings should reflect the real structure of the page rather than visual styling choices, helping users understand how content is organised. &lt;/p&gt;

&lt;p&gt;Clarity should always be prioritised over rigid or outdated rules, and heading navigation should be tested with a screen reader to ensure the structure works in practice.&lt;/p&gt;

&lt;p&gt;If the structure makes sense to a human, it usually makes sense to assistive technology.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Using multiple &lt;code&gt;header&lt;/code&gt; and &lt;code&gt;footer&lt;/code&gt; elements in a document is both valid and accessible when they correctly describe their respective sections. Multiple &lt;code&gt;h1&lt;/code&gt; elements are also allowed and often appropriate, particularly in documents composed of distinct articles or regions.&lt;/p&gt;

&lt;p&gt;Accessibility does not depend on counting elements, but on providing a clear and logical hierarchy that accurately represents the content.&lt;/p&gt;

&lt;p&gt;HTML accessibility is ultimately about expressing meaning rather than following myths or arbitrary conventions.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>When Does a Component Re-render in React?</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Sun, 01 Feb 2026 19:53:25 +0000</pubDate>
      <link>https://dev.to/miasalazar/when-does-a-component-re-render-in-react-lnb</link>
      <guid>https://dev.to/miasalazar/when-does-a-component-re-render-in-react-lnb</guid>
      <description>&lt;p&gt;React's declarative nature and virtual DOM abstraction make it deceptively easy to build complex UIs. However, understanding when and why a component re-renders is essential for performance, especially in larger applications. Re-renders can be cheap, but unnecessary ones add up.&lt;/p&gt;

&lt;p&gt;This article explains the most common triggers of component re-renders and offers strategies for controlling them effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Triggers a Re-render?
&lt;/h2&gt;

&lt;p&gt;When a component’s state changes using useState, React schedules a re-render of that component.&lt;/p&gt;

&lt;p&gt;Every call to setCount with a different value will cause the component to re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [count, setCount] = useState(0);

const increment = () =&amp;gt; setCount(count + 1);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prop Changes
&lt;/h3&gt;

&lt;p&gt;If a component receives new props (i.e., if the parent re-renders and passes new values), the child will also re-render by default.&lt;/p&gt;

&lt;p&gt;If someValue changes (even if it’s deeply equal but a new reference), MyComponent will re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;MyComponent data={someValue} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Context Changes
&lt;/h3&gt;

&lt;p&gt;React Contexts provide a way to share values across the component tree. Any update to a context value will re-render all consuming components.&lt;/p&gt;

&lt;p&gt;When theme changes, ChildComponent and all others using useContext(MyContext) re-render.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;MyContext.Provider value={theme}&amp;gt;
  &amp;lt;ChildComponent /&amp;gt;
&amp;lt;/MyContext.Provider&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parent Re-renders
&lt;/h3&gt;

&lt;p&gt;Even if a child’s props didn’t change, it can re-render if its parent re-renders unless it’s memoised with React.memo.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Reconciliation: How React Decides to Re-render
&lt;/h2&gt;

&lt;p&gt;React uses referential equality (===) to compare props and state. If something changes, a new object, array, or primitive, it assumes the UI might need to update.&lt;/p&gt;

&lt;p&gt;This is why using immutable patterns is crucial. Mutating objects without changing their reference can lead to bugs or skipped renders.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Prevent Unnecessary Re-renders
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use React.memo for Pure Functional Components
&lt;/h3&gt;

&lt;p&gt;Only re-renders if name changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const MyComponent = React.memo(({ name }) =&amp;gt; {
  console.log("Rendered!");
  return &amp;lt;div&amp;gt;{name}&amp;lt;/div&amp;gt;;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use useCallback and useMemo to Stabilise Functions and Values
&lt;/h3&gt;

&lt;p&gt;Without useCallback, the function is recreated on every render and may cause children to re-render unnecessarily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleClick = useCallback(() =&amp;gt; {
  // Do something
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Avoid Inline Objects and Arrays in Props
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Causes re-render
&amp;lt;Component data={{ a: 1 }} /&amp;gt;

// Use useMemo
const data = useMemo(() =&amp;gt; ({ a: 1 }), []);
&amp;lt;Component data={data} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keep State Local Where Possible
&lt;/h3&gt;

&lt;p&gt;Lifting state up or storing too much in global context can lead to unnecessary tree-wide re-renders. Keep state close to where it’s used.&lt;/p&gt;

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

&lt;p&gt;Understanding when React re-renders a component is vital to building performant and predictable interfaces. State, props, context, and parent updates are the primary causes. By embracing immutable patterns and using tools like React.memo, useCallback, and useMemo, you can significantly reduce unnecessary rendering and boost the responsiveness of your application.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>performance</category>
    </item>
    <item>
      <title>Regular Functions vs Arrow Functions in JavaScript</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Mon, 26 Jan 2026 08:34:50 +0000</pubDate>
      <link>https://dev.to/miasalazar/regular-functions-vs-arrow-functions-in-javascript-528n</link>
      <guid>https://dev.to/miasalazar/regular-functions-vs-arrow-functions-in-javascript-528n</guid>
      <description>&lt;p&gt;JavaScript offers two main ways to declare functions: regular functions and arrow functions. While both can perform the same tasks, they behave differently in key areas, especially regarding this, arguments, and how they’re used in front-end development.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;this&lt;/code&gt; Binding
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Regular functions get their own &lt;code&gt;this&lt;/code&gt; depending on how they’re called. &lt;code&gt;this&lt;/code&gt; changes based on who calls the function.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const button = document.querySelector('#myButton');

button.addEventListener('click', function () {
  console.log(this); // 'this' = the button
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, this refers to the button that was clicked&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrow functions don’t have their own this; they inherit it from their surrounding scope. &lt;code&gt;this&lt;/code&gt; comes from where the function is written.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes arrow functions ideal in situations where you want to keep the context&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const button = document.querySelector('#myButton');

button.addEventListener('click', () =&amp;gt; {
  console.log(this); // 'this' = window or outer scope
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, this does not refer to the button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arguments Object
&lt;/h2&gt;

&lt;p&gt;The arguments object is a built-in feature in regular functions in JavaScript. It contains an array-like list of all the values passed to that function, even if they weren’t defined as parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular functions have access to the arguments object, an array-like list of arguments passed to the function.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function showArguments() {
  console.log(arguments);
}

showArguments('Hello', 42, true);
// Output: ['Hello', 42, true] (in modern browsers)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Arrow functions do not have their own arguments. You need to use rest parameters instead (...args).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try to use arguments inside an arrow function, it won’t work the way you might expect. If you need to collect arguments in an arrow function, use the rest parameter syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const showArguments = (...args) =&amp;gt; {
  console.log(args);
};

showArguments('Hello', 42, true);
// Output: ['Hello', 42, true]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Constructors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Regular functions can be used as constructors with new.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Person(name) {
  this.name = name;
  this.sayHello = function () {
    console.log(`Hello, I'm ${this.name}`);
  };
}

const user = new Person('Alice');
user.sayHello(); // Hello, I'm Alice

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Arrow functions cannot be used that way. They’re not constructors.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Person = (name) =&amp;gt; {
  this.name = name;
  this.sayHello = () =&amp;gt; {
    console.log(`Hello, I'm ${this.name}`);
  };
};

const user = new Person('Alice'); // ❌ TypeError: Person is not a constructor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Syntax
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Arrow functions are more concise, especially for one-liners or callbacks.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Arrow functions and regular functions both allow you to define reusable blocks of code. However, they serve slightly different purposes in modern JavaScript.&lt;/p&gt;

&lt;p&gt;Arrow functions are shorter, cleaner, and automatically bind this and arguments from their surrounding context. This makes them ideal for callbacks, array methods, and React components, where you want predictable scope and no surprises with this.&lt;/p&gt;

&lt;p&gt;On the other hand, regular functions are more flexible when you need your function to have its own this, use the built-in arguments object, or act as a constructor with new. They are better suited for event handlers on the DOM, older codebases, or where full control over the function context is required.&lt;/p&gt;

&lt;p&gt;Understanding when to use each helps keep your code readable, efficient, and bug-free, especially in front-end development where scope confusion is a common issue.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Human‑Driven vs AI‑Driven IDEs</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Fri, 09 Jan 2026 09:29:09 +0000</pubDate>
      <link>https://dev.to/miasalazar/human-driven-vs-ai-driven-ides-52ha</link>
      <guid>https://dev.to/miasalazar/human-driven-vs-ai-driven-ides-52ha</guid>
      <description>&lt;p&gt;AI‑powered IDEs such as Cursor, VS Code with Copilot, and WebStorm AI Assistant are rapidly becoming part of everyday development. They can autocomplete code, refactor components, generate tests, and explain unfamiliar APIs.&lt;/p&gt;

&lt;p&gt;There is, however, a crucial distinction in how these tools are used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI‑driven development: the IDE leads, the human reacts.&lt;/li&gt;
&lt;li&gt;Human‑driven development: the human leads, the AI assists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article explains that distinction, why human‑driven workflows matter for teams, and how to configure AI‑enabled IDEs (with Cursor as a concrete example) to support that approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Do We Mean by AI‑Driven?
&lt;/h2&gt;

&lt;p&gt;An AI-driven workflow is one in which the developer accepts large AI-generated blocks of code with little or no critical review, allows the AI to make decisions about architecture, naming, and patterns, and increasingly relies on the tool to “solve” problems instead of reasoning through them. In this model, the AI effectively leads the development process, while the human mainly reacts to its output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Prompt: "Create a responsive navbar in React"

export default function Navbar() {
 return (
  &amp;lt;nav&amp;gt;
   &amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;Home&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;About&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;Contact&amp;lt;/li&amp;gt;
   &amp;lt;/ul&amp;gt;
  &amp;lt;/nav&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code works, but the AI has implicitly made design decisions on behalf of the team, without considering accessibility, responsiveness, design‑system conventions, or state management. These omissions are subtle, but they accumulate quickly in real codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Human‑Driven Development?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Human‑driven development&lt;/strong&gt; keeps intent, judgement, and responsibility firmly with the developer.&lt;/p&gt;

&lt;p&gt;In a human-driven approach, the AI is treated as a fast typist, a refactoring assistant, and a source of suggestions rather than a decision-maker. The human developer defines what needs to be built and why, while the AI helps with how to implement it, and all generated code is carefully reviewed, understood, and adapted to fit the wider system and context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface NavItem {
 label: string;
 href: string;
}

const navItems: NavItem[] = [
 { label: 'Home', href: '/' },
 { label: 'About', href: '/about' },
 { label: 'Contact', href: '/contact' },
];

export function Navbar() {
 return (
  &amp;lt;nav aria-label="Main navigation"&amp;gt;
   &amp;lt;ul className="nav-list"&amp;gt;
    {navItems.map(item =&amp;gt; (
     &amp;lt;li key={item.href}&amp;gt;
      &amp;lt;a href={item.href}&amp;gt;{item.label}&amp;lt;/a&amp;gt;
     &amp;lt;/li&amp;gt;
    ))}
   &amp;lt;/ul&amp;gt;
  &amp;lt;/nav&amp;gt;
 );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the AI may have helped with typing or mapping logic, but the structure is intentional, accessibility is explicit, and data is separated from presentation&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Cursor as a Human‑Driven IDE
&lt;/h2&gt;

&lt;p&gt;Using Cursor effectively requires deliberate constraints. Its deep AI integration can easily shift control away from the developer if left unchecked.&lt;/p&gt;

&lt;p&gt;A human‑driven setup starts by making intent explicit before invoking AI, through comments, partial implementations, type definitions, or clearly stated constraints. This anchors suggestions in the developer’s reasoning and ensures that the tool responds to existing context rather than introducing unsolicited structure or assumptions.&lt;/p&gt;

&lt;p&gt;In practice, Cursor works best when used incrementally. Inline completions and small, reviewable changes encourage understanding and ownership. Conservative configuration helps prevent large, unexamined rewrites. Treated this way, Cursor becomes an accelerator for well‑defined ideas rather than a substitute for architectural thinking or judgement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Files for a Human‑Driven Cursor Setup
&lt;/h2&gt;

&lt;p&gt;A key part of keeping Cursor &lt;em&gt;human‑driven&lt;/em&gt; is making your preferences explicit in configuration files. This reduces accidental AI overreach and aligns the tool with team standards.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Project‑Level Rules (&lt;code&gt;.cursor/rules.md&lt;/code&gt; or similar)
&lt;/h3&gt;

&lt;p&gt;Use a project‑local rules file to describe &lt;em&gt;how the AI should behave&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# AI Usage Rules

- Do not introduce new libraries without asking
- Prefer existing project patterns over generic best practices
- Optimise for readability over cleverness
- Always respect accessibility (WCAG) concerns
- Never change public APIs unless explicitly requested
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works especially well in teams, as it makes expectations explicit and repeatable.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Editor Settings (&lt;code&gt;settings.json&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Cursor builds on VS Code, so editor configuration still matters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "editor.inlineSuggest.enabled": true,
  "editor.suggest.preview": true,
  "editor.acceptSuggestionOnEnter": "off",
  "cursor.ai.autoGenerate": false,
  "cursor.ai.inlineSuggestions": true,
  "cursor.ai.confirmLargeChanges": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These settings bias toward small, intentional interactions rather than wholesale generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Repository Documentation (&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Document &lt;em&gt;how AI is expected to be used&lt;/em&gt; in the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## AI‑Assisted Development&lt;/span&gt;

AI tools may be used for:
&lt;span class="p"&gt;-&lt;/span&gt; Refactoring
&lt;span class="p"&gt;-&lt;/span&gt; Test generation
&lt;span class="p"&gt;-&lt;/span&gt; Documentation improvements

AI tools should not be used for:
&lt;span class="p"&gt;-&lt;/span&gt; Designing core architecture
&lt;span class="p"&gt;-&lt;/span&gt; Introducing new patterns without review
&lt;span class="p"&gt;-&lt;/span&gt; Replacing code reviews
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes AI usage part of the team’s social contract, not an implicit or ad‑hoc practice&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Optional: Prompt Templates
&lt;/h3&gt;

&lt;p&gt;Some teams keep prompt snippets in the repo for consistency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Refactoring Prompt

Refactor the selected code:
- Keep the public API unchanged
- Do not introduce new dependencies
- Prefer clarity over abstraction
- Explain the changes briefly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reduces vague prompts and improves output quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human‑Driven Prompting Patterns
&lt;/h2&gt;

&lt;p&gt;Instead of vague prompts like "Build this component", use constrained prompts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Refactor this function to be more readable, keep the API unchanged"&lt;/li&gt;
&lt;li&gt;"Suggest accessibility improvements only, no visual changes"&lt;/li&gt;
&lt;li&gt;"Explain this code rather than rewriting it"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One effective pattern is using AI for &lt;em&gt;review&lt;/em&gt;, not creation. The AI becomes a second pair of eyes, not the primary author.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Ask the AI:&lt;/span&gt;
&lt;span class="c1"&gt;// "What edge cases am I missing here?"&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`£&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&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;h2&gt;
  
  
  Why Human‑Driven Matters in Front‑End
&lt;/h2&gt;

&lt;p&gt;Front‑end code is not just about logic; it directly shapes user experience, accessibility, performance, and visual consistency. Every component encodes product decisions and design intent.&lt;/p&gt;

&lt;p&gt;AI models have no real understanding of your users, business goals, regulatory constraints, or design system nuances. When they lead, those concerns are flattened or ignored.&lt;/p&gt;

&lt;p&gt;Human‑driven workflows help teams:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid fragmented UI patterns&lt;/li&gt;
&lt;li&gt;Preserve long‑term code quality&lt;/li&gt;
&lt;li&gt;Reduce hidden technical debt&lt;/li&gt;
&lt;li&gt;Improve readability and onboarding&lt;/li&gt;
&lt;li&gt;Maintain shared understanding across the codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By keeping intent and judgement with developers, teams gain speed without sacrificing coherence.&lt;/p&gt;

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

&lt;p&gt;AI‑enabled IDEs are not inherently good or bad; the real risk lies in ceding intent.&lt;/p&gt;

&lt;p&gt;By defining goals clearly, configuring tools conservatively, and treating AI as an assistant rather than an architect, developers can benefit from increased velocity without losing understanding or ownership.&lt;/p&gt;

&lt;p&gt;Human‑driven development is not slower: it is deliberate. And in UI‑centric codebases, that deliberation is a feature, not a bug.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Replacing Toasts with Accessible User Feedback Patterns</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Tue, 18 Nov 2025 18:43:49 +0000</pubDate>
      <link>https://dev.to/miasalazar/replacing-toasts-with-accessible-user-feedback-patterns-1p8l</link>
      <guid>https://dev.to/miasalazar/replacing-toasts-with-accessible-user-feedback-patterns-1p8l</guid>
      <description>&lt;p&gt;Providing users with timely and meaningful feedback is essential for a usable digital experience. However, one of the most common UI patterns, toast notifications, often introduces serious accessibility barriers. Toasts tend to appear unpredictably, disappear too quickly, lack keyboard accessibility, and are rarely announced properly by assistive technologies.&lt;/p&gt;

&lt;p&gt;This article explores why toast notifications often fail to meet WCAG guidelines, and proposes accessible alternatives, complete with example code snippets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Toasts Are Problematic
&lt;/h2&gt;

&lt;p&gt;Toasts typically violate several WCAG 2.2 success criteria &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-interruptive timing issues: Toasts frequently appear for only a few seconds, preventing some users from perceiving them.&lt;/li&gt;
&lt;li&gt;Lack of screen reader announcement: Many toasts are not implemented as live regions, meaning assistive technology users may never know they were there.&lt;/li&gt;
&lt;li&gt;Keyboard inaccessibility: If the toast contains actionable elements (e.g., an “Undo” button), users often cannot tab into it before it vanishes.&lt;/li&gt;
&lt;li&gt;Unexpected appearance on screen: Toasts that slide into view can cause layout shifts or distract users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Accessible Alternatives to Toast Notifications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use Persistent Status Message Regions
&lt;/h3&gt;

&lt;p&gt;Avoid transient pop-ups and instead display status messages in a consistent, easily discoverable location, typically above the main content or directly beside the component that has changed.&lt;/p&gt;

&lt;p&gt;This ensures the message:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is always in a predictable location (WCAG 3.2.3 Consistent Navigation)&lt;/li&gt;
&lt;li&gt;Can remain visible until dismissed (WCAG 2.2.1 Timing Adjustable)&lt;/li&gt;
&lt;li&gt;Can be announced with aria-live (WCAG 4.1.3 Status Messages)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div 
  aria-live="polite"
  aria-atomic="true"
  id="status-message"&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use Inline Feedback Near the Trigger
&lt;/h3&gt;

&lt;p&gt;For actions such as form submissions or toggles, providing feedback next to the interactive element can help users immediately associate the message with the action they performed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;button id="save-btn"&amp;gt;
  Save
&amp;lt;/button&amp;gt;
&amp;lt;span 
  id="save-feedback"
  class="visually-hidden"
  aria-live="assertive"
&amp;gt;&amp;lt;/span&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use a Non-modal, Dismissible Alert Component
&lt;/h3&gt;

&lt;p&gt;If a notification must stand out, consider an alert component fixed to the top of the page or container. Ensure it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stays visible until user dismissal (WCAG 2.2.1 Timing Adjustable)&lt;/li&gt;
&lt;li&gt;Is reachable via keyboard (WCAG 2.1.1 Keyboard)&lt;/li&gt;
&lt;li&gt;Is properly announced (WCAG 4.1.3 Status Messages)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div
  id="alert"
  class="alert"
  role="alert"
  tabindex="-1"
  hidden
&amp;gt;
  &amp;lt;p id="alert-text"&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;button aria-label="Dismiss alert" id="alert-dismiss"&amp;gt;×&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keep Animations Minimal and Optional
&lt;/h3&gt;

&lt;p&gt;Some users may experience distraction or discomfort from motion. It is recommended to avoid unnecessary motion unless essential to functionality (WCAG 2.3.3 – Animation from Interactions) and respect the user’s “prefers-reduced-motion”.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@media (prefers-reduced-motion: reduce) {
  .alert {
    transition: none;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Toasts may be familiar and visually appealing, but they often create accessibility barriers. By using persistent status areas, inline messages, or properly implemented alert components, designers and developers can ensure all users, including those with assistive technologies, can perceive, understand, and respond to important feedback.&lt;/p&gt;

&lt;p&gt;Replacing toasts with more accessible patterns not only improves compliance with WCAG but also leads to clearer, more reliable communication across your interface.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Why Skipping Frontend Tests Always Backfires</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Wed, 22 Oct 2025 07:05:38 +0000</pubDate>
      <link>https://dev.to/miasalazar/why-skipping-frontend-tests-always-backfires-2527</link>
      <guid>https://dev.to/miasalazar/why-skipping-frontend-tests-always-backfires-2527</guid>
      <description>&lt;p&gt;Every team has that one person, or two, who insists that “frontend tests are a waste of time.”&lt;/p&gt;

&lt;p&gt;They might say E2E tests are flaky, or that QA already does the job. But deep down, skipping tests isn’t a bold time-saving move; it’s a long-term productivity trap.&lt;/p&gt;

&lt;p&gt;Here’s how to win the argument (and save your project from endless regressions).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Testing Matters, even on the Frontend
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.Tests catch regressions before your users do
&lt;/h3&gt;

&lt;p&gt;Frontend changes are deceptively simple. You tweak a component or update an API call, and suddenly the login form stops working.&lt;/p&gt;

&lt;p&gt;Having automated tests for critical flows (login, checkout...) ensures that your app’s core functionality never silently breaks. Without tests, the real testers are your users, and they’re the worst kind of testers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.They actually save time
&lt;/h3&gt;

&lt;p&gt;Fixing a bug found in production takes exponentially more time than catching it during development. Manual QA can’t rerun every scenario on every release, but a test suite can, in seconds.&lt;/p&gt;

&lt;p&gt;So while writing tests feels slow upfront, it pays off every sprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.They make refactoring safe
&lt;/h3&gt;

&lt;p&gt;When your codebase grows, refactors are inevitable. Without tests, developers fear touching anything. With tests, you can confidently restructure, optimize, or modernize your code, knowing that your safety net will catch regressions instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.They force better code design
&lt;/h3&gt;

&lt;p&gt;Writing testable code means separating responsibilities and avoiding hidden side effects. Tests naturally lead to cleaner, more modular, and easier-to-understand components.&lt;/p&gt;

&lt;p&gt;In the long run, this reduces onboarding time for new developers and increases overall code health.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.You don’t need 100% coverage
&lt;/h3&gt;

&lt;p&gt;Nobody’s asking for full-blown test coverage. Start small: Cover only the key integration flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Objections, and How to Defeat Them
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;"Tests are too fragile": Badly written tests can be unstable, but using modern tools, and using them well, makes them reliable and maintainable.&lt;/li&gt;
&lt;li&gt;"We don’t have time": Skipping tests saves time only in the short term. Bugs found later cost far more to fix and slow development over time.&lt;/li&gt;
&lt;li&gt;"QA already checks that": QA should focus on exploratory and edge-case testing, not on repeating the same core flows every release.&lt;/li&gt;
&lt;li&gt;"Our app changes too often": Frequent changes increase the risk of regressions. Well-structured tests provide confidence and prevent hidden breakages.&lt;/li&gt;
&lt;li&gt;"Tests slow us down": Full E2E coverage can be slow, but a balanced strategy, focusing E2E on key user flows and using faster integration or unit tests elsewhere, keeps feedback loops quick and efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why End-to-End tests alone aren’t enough
&lt;/h2&gt;

&lt;p&gt;E2E tests are fantastic, they simulate real user behavior and verify that everything works together. But relying only on E2E tests is like checking if your car drives without ever opening the hood.&lt;/p&gt;

&lt;p&gt;Here’s why that’s risky:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E2E tests are heavy and slow: They take longer to run and are more brittle because they depend on the full stack being up and stable.&lt;/li&gt;
&lt;li&gt;When they fail, it’s hard to know why: A single failing E2E might mean a backend bug, a frontend change... Debugging takes longer than if you had smaller, faster integration or unit tests.&lt;/li&gt;
&lt;li&gt;You lose granularity: Without lower-level tests, you can’t easily isolate where a bug originates.&lt;/li&gt;
&lt;li&gt;They don’t scale well: Large teams need fast feedback loops. Having only E2E tests means waiting minutes (or hours) for CI runs instead of seconds for unit tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclussions
&lt;/h2&gt;

&lt;p&gt;Convincing someone to write tests isn’t about dogma: it’s about pragmatism. It’s insurance against chaos. Start small, show quick wins, and let the results speak for themselves. Before long, your once-skeptical teammate will be willing to create more tests.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Modals and accessibility</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Tue, 14 Oct 2025 07:18:48 +0000</pubDate>
      <link>https://dev.to/miasalazar/modals-and-accessibility-111e</link>
      <guid>https://dev.to/miasalazar/modals-and-accessibility-111e</guid>
      <description>&lt;p&gt;Modals are a frequently used element on web pages. These components appear as overlays on the current page, preventing full view and interaction with the underlying content. They are often used for confirmation or cancellation screens, or to request additional details on a subject.&lt;/p&gt;

&lt;p&gt;While common in design, modals can be a real challenge for keyboard or screen reader users if not properly implemented. &lt;/p&gt;

&lt;h2&gt;
  
  
  Opening the Modal
&lt;/h2&gt;

&lt;p&gt;An essential aspect is how the modal opens. When a modal is triggered, the focus should shift to the first interactive element within it. Interactive elements include links, buttons, and form elements like &lt;code&gt;input&lt;/code&gt; or &lt;code&gt;select&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Screen readers
&lt;/h3&gt;

&lt;p&gt;To ensure compatibility with screen readers, the modal should be properly identified using &lt;code&gt;role="dialog"&lt;/code&gt; (or &lt;code&gt;role="alertdialog"&lt;/code&gt;) and &lt;code&gt;aria-modal="true"&lt;/code&gt;. This informs assistive technologies that the rest of the page is inactive while the modal is open.&lt;/p&gt;

&lt;p&gt;In older implementations, developers often used &lt;code&gt;aria-hidden="true"&lt;/code&gt; to hide background content from screen readers. However, this approach is more error-prone and harder to maintain, especially in complex applications, so &lt;code&gt;aria-modal="true"&lt;/code&gt; is now the preferred solution.&lt;/p&gt;

&lt;p&gt;Regardless of the approach, it's still necessary to manage focus and prevent interaction with background content through proper focus trapping and scripting.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARIA roles and relationships
&lt;/h2&gt;

&lt;p&gt;To make modals fully accessible to assistive technologies, it is important to correctly define their structure and semantics using ARIA attributes.&lt;/p&gt;

&lt;p&gt;First, every modal should have a clear accessible name. If the modal includes a visible title, the container element with &lt;code&gt;role="dialog"&lt;/code&gt; should reference it using &lt;code&gt;aria-labelledby&lt;/code&gt;. This ensures screen readers announce the modal with its proper title.&lt;/p&gt;

&lt;p&gt;Additionally, if the modal contains descriptive text that explains its purpose or provides context, this should be associated using &lt;code&gt;aria-describedby&lt;/code&gt;. This allows screen readers to read both the title and the supporting description when the modal is opened.&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;role=&lt;/span&gt;&lt;span class="s"&gt;"dialog"&lt;/span&gt; &lt;span class="na"&gt;aria-labelledby=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt; &lt;span class="na"&gt;aria-describedby=&lt;/span&gt;&lt;span class="s"&gt;"modal-description"&lt;/span&gt; &lt;span class="na"&gt;aria-modal=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"modal-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete account&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"modal-description"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;This action cannot be undone.&lt;span class="nt"&gt;&amp;lt;/p&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;p&gt;Another important attribute is aria-modal="true". This indicates to assistive technologies that content outside the modal is inert (non-interactive) while the modal is open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Difference between role="dialog" and aria-modal="true"
&lt;/h2&gt;

&lt;p&gt;Although often used together, these attributes serve different purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;role="dialog" defines the element as a dialog (a modal window) and provides semantic meaning to assistive technologies.&lt;/li&gt;
&lt;li&gt;aria-modal="true" indicates that the dialog is modal, meaning interaction is limited to the dialog and background content should be ignored.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, role="dialog" tells what the element is, while aria-modal="true" tells how it behaves.&lt;/p&gt;

&lt;p&gt;Both should be used together for proper accessibility support, especially since not all assistive technologies fully infer modality from the role alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Focus trapping
&lt;/h2&gt;

&lt;p&gt;Keyboard users can accidentally navigate out of an open modal, which can lead to confusing interactions with elements behind the modal. To prevent this, implement focus trapping.&lt;/p&gt;

&lt;p&gt;Focus trapping is a technique that ensures the focus remains within the modal while it is open. This way, a keyboard user cannot leave the modal until it is closed or the necessary action to close it is performed.&lt;/p&gt;

&lt;p&gt;This technique is crucial for accessibility, as it prevents interactions with elements behind the modal and creates a circular navigation among the elements within the modal.&lt;/p&gt;

&lt;p&gt;There are numerous articles on how to implement focus trapping in React&lt;br&gt;
or Vanilla JavaScript, among other frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escaping the Modal
&lt;/h2&gt;

&lt;p&gt;Users often expect pressing the Escape key to close the modal. Therefore, it's important to implement this functionality. Additionally, when the modal closes, the focus should return to the element that triggered the modal.&lt;/p&gt;

&lt;h2&gt;
  
  
  General tips
&lt;/h2&gt;

&lt;p&gt;To conclude, here are some general tips for improving the accessibility of your modals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On mobile or small devices, modals should occupy the entire screen to enhance readability. On larger screens, use an opaque or semi-opaque layer beneath the modal to improve visibility.&lt;/li&gt;
&lt;li&gt;Each modal should have a title explaining its functionality to make its purpose clear.
The close button should be visible and large enough to be easily clicked, at least 44px by 44px.&lt;/li&gt;
&lt;li&gt;Use semantic HTML for all elements within the modal. The more information we provide to assistive technologies, the better.&lt;/li&gt;
&lt;li&gt;Prevent background scrolling when the modal is open to avoid confusion.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Building accessible modals requires more than just visual design: it involves careful consideration of semantics, focus management, and user interaction. Using &lt;code&gt;role="dialog"&lt;/code&gt; together with &lt;code&gt;aria-modal="true"&lt;/code&gt; provides the necessary context for assistive technologies, while &lt;code&gt;aria-labelledby&lt;/code&gt; and &lt;code&gt;aria-describedby&lt;/code&gt; ensure the modal is properly announced with meaningful information.&lt;/p&gt;

&lt;p&gt;However, ARIA alone is not enough. Proper focus management (including focus trapping and restoring focus on close) and preventing interaction with background content are essential to create a predictable and usable experience for all users. An accessible modal should behave consistently across input methods, keyboard, screen reader, and pointer, ensuring that all users can interact with it effectively and without confusion.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>frontend</category>
      <category>html</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Find a Job in Tech: Practical Advice for Navigating a Tough Market</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Sat, 30 Aug 2025 12:18:15 +0000</pubDate>
      <link>https://dev.to/miasalazar/how-to-find-a-job-in-tech-practical-advice-for-navigating-a-tough-market-219h</link>
      <guid>https://dev.to/miasalazar/how-to-find-a-job-in-tech-practical-advice-for-navigating-a-tough-market-219h</guid>
      <description>&lt;p&gt;In recent years, finding a job in tech, especially in software development, has become increasingly challenging. The market is more saturated, competition is stronger, and fully remote opportunities are no longer as abundant or well-paid as they once were. As someone who's been through this process, I want to share some practical tips that have helped me and might help you too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 1: Define Your Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Choose Your Focus (But Stay Flexible)
&lt;/h3&gt;

&lt;p&gt;Before you start applying, think carefully about what you want to do. The more specific your goal, the harder it might be to land interviews. For instance, if you only look for React roles, you may be missing out on opportunities that require other frameworks. I recommend checking out which technologies are in demand. Then, decide what you want to prioritize, both for now and your long-term career.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Decide on the Work Model (Remote, On-site, Hybrid)
&lt;/h3&gt;

&lt;p&gt;Remote work is much harder to get nowadays, especially fully remote roles. These positions are often more competitive and sometimes come with lower salaries. Choosing on-site or hybrid may increase your chances of getting hired faster, depending on your location and flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Define a Salary Range (and Make Sure It’s Realistic)
&lt;/h3&gt;

&lt;p&gt;Have a clear salary expectation, but verify that it's in line with market standards. Remember: fully remote jobs tend to pay less, especially if you're based in countries with lower cost of living.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Open Up to International Markets
&lt;/h3&gt;

&lt;p&gt;If you speak other languages, consider applying internationally. English is the key to most global opportunities, but you'll need to be comfortable enough to handle technical interviews. Confidence in both communication and coding is essential.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Add a Timeframe to Your Plan
&lt;/h3&gt;

&lt;p&gt;Set time-based checkpoints to reassess your strategy. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“If I haven’t found a job in 3 months, I’ll start considering hybrid roles.”&lt;/li&gt;
&lt;li&gt;“If after 2 months there are no responses, I’ll expand my search to include more tech stacks.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These personal deadlines help you stay grounded and prevent frustration from growing aimlessly. Adapting doesn't mean giving up, it means staying strategic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2: Search Effectively
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. Be Systematic
&lt;/h3&gt;

&lt;p&gt;Choose a few job platforms that work well for you, don’t try to monitor 300 websites or you might end up losing your mind. Search daily using a variety of keywords. For example, if you're a frontend developer, search terms like “frontend developer,” “front-end engineer,” “React,” etc. Keep track of where you’ve applied and what keywords work best.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Track Your Progress with a Spreadsheet
&lt;/h3&gt;

&lt;p&gt;Create an Excel or Google Sheets file with key information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Company name&lt;/li&gt;
&lt;li&gt;Work model (on-site/remote/hybrid)&lt;/li&gt;
&lt;li&gt;Work hours and flexibility&lt;/li&gt;
&lt;li&gt;Salary range offered&lt;/li&gt;
&lt;li&gt;Link to the job post&lt;/li&gt;
&lt;li&gt;Contact person&lt;/li&gt;
&lt;li&gt;Application status (e.g., applied, phone screen, rejected)&lt;/li&gt;
&lt;li&gt;Phase at which you were rejected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this data to identify patterns. If you’re consistently dropped at the same stage (e.g., technical interview), that’s a signal to improve in that area.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Stay Responsive: Check Your Phone &amp;amp; Email Regularly
&lt;/h3&gt;

&lt;p&gt;Recruitment processes can move fast. Stay reachable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep your phone on sound&lt;/li&gt;
&lt;li&gt;Check your email and LinkedIn messages frequently&lt;/li&gt;
&lt;li&gt;Save the phone numbers of recruiters with the company name, so you recognize who’s calling&lt;/li&gt;
&lt;li&gt;Update your Excel tracker with any contact details to stay organized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being responsive helps you avoid missing important calls or time-sensitive opportunities.&lt;/p&gt;

&lt;h3&gt;
  
  
  9.Pace Yourself: Don’t Burn Out
&lt;/h3&gt;

&lt;p&gt;If you're in a rush to find a job, you might feel the need to apply to everything and enter multiple processes at once. That’s okay, but you must prioritize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Focus on the roles that look most promising&lt;/li&gt;
&lt;li&gt;Sometimes you’ll need to choose between two take-home assignments. Decide which company is more aligned with you&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try not to schedule more than 2–3 interviews per day, and leave breaks between them to avoid mental exhaustion. If you’re not in a rush, take it slower:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Space out interviews and assignments&lt;/li&gt;
&lt;li&gt;Be selective with where you apply&lt;/li&gt;
&lt;li&gt;Choose when and how to give your best energy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even if time is tight, structure your week so that you stay sane. Good organization beats frantic multitasking.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Know Your Strengths (and Gaps)
&lt;/h3&gt;

&lt;p&gt;If you’re applying to jobs using technologies you haven't worked with in a while (e.g., Angular or Vue when you've only used React recently), be prepared. Consider building a small project (a “pet project”) with those technologies so you’re not caught off guard during technical interviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 3: Prepare Your Materials
&lt;/h2&gt;

&lt;h3&gt;
  
  
  11. Build a Strong CV (in All Relevant Languages)
&lt;/h3&gt;

&lt;p&gt;Your CV should be detailed and tailored to the roles you’re applying for. Include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exact dates of employment (month/year)&lt;/li&gt;
&lt;li&gt;Technologies used&lt;/li&gt;
&lt;li&gt;Projects and responsibilities&lt;/li&gt;
&lt;li&gt;Architecture, methodologies, and principles followed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Forget the “1-page CV” myth. More pages are fine if the content is valuable. Have it available in multiple formats (PDF, DOC) and in all the languages relevant to your job search.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Write Custom Cover Letters
&lt;/h3&gt;

&lt;p&gt;Always include a cover letter tailored to each company. Read the job description carefully, and align your message with what the company is looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 4: Interview Preparation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  13. Know Your Rights: Watch Out for Illegal Questions
&lt;/h3&gt;

&lt;p&gt;Before your interviews, take a moment to review local labor laws regarding job interviews. For example, in Spain it’s illegal for interviewers to ask about your age, marital status, sexual orientation, or family plans. They cannot legally discriminate based on any of those factors&lt;/p&gt;

&lt;p&gt;If you're asked inappropriate or illegal questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Politely deflect or refuse to answer&lt;/li&gt;
&lt;li&gt;Take it as a red flag. If they disregard the law during recruitment, it might reflect deeper problems within the company culture&lt;/li&gt;
&lt;li&gt;Don’t hesitate to walk away from companies that cross these boundaries. Your well-being and rights matter more than any offer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Being aware of these laws helps you protect yourself and recognize trustworthy employers.&lt;/p&gt;

&lt;h3&gt;
  
  
  14. Be Consistent in Your Narrative
&lt;/h3&gt;

&lt;p&gt;Make sure your answers align with your stated long-term goals.&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you say your goal is to move into management, reinforce this by mentioning leadership experiences, mentoring juniors, taking responsibility, etc.&lt;/li&gt;
&lt;li&gt;Avoid giving conflicting answers that make your story seem incoherent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A coherent, consistent narrative shows you’re clear about your goals and reliable in your planning.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Prepare a Solid Answer for: "Why Are You Leaving Your Current Job?"
&lt;/h3&gt;

&lt;p&gt;This is one of the most common and delicate questions.&lt;br&gt;
Avoid answers that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Criticize your colleagues ("my coworkers were unbearable")&lt;/li&gt;
&lt;li&gt;Make you sound unstable ("I get bored quickly")&lt;/li&gt;
&lt;li&gt;Raise concerns about your teamwork or long-term commitment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, focus on positive, professional reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seeking new challenges&lt;/li&gt;
&lt;li&gt;Wanting to grow technically&lt;/li&gt;
&lt;li&gt;Looking for better alignment with your career path&lt;/li&gt;
&lt;li&gt;Company restructuring (if applicable)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  16. Maintain a Stable Career Timeline (If Possible)
&lt;/h3&gt;

&lt;p&gt;Frequent job changes or unexplained employment gaps can make HR suspicious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They may wonder if you fail probation periods&lt;/li&gt;
&lt;li&gt;They may worry that you’ll leave quickly again&lt;/li&gt;
&lt;li&gt;They may question your ability to integrate into teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, sometimes short stays or breaks are legitimate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You tried a company and it wasn’t the right fit&lt;/li&gt;
&lt;li&gt;You needed personal time off&lt;/li&gt;
&lt;li&gt;There were economic layoffs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this happens, learn how to explain these gaps calmly and professionally.&lt;/p&gt;

&lt;h3&gt;
  
  
  17. Don’t Speak Badly About Former Employers or Coworkers
&lt;/h3&gt;

&lt;p&gt;Even if you had very negative experiences, avoid badmouthing previous companies or colleagues. Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can raise red flags about your teamwork skills&lt;/li&gt;
&lt;li&gt;It can make interviewers wonder if you’ll speak the same way about them later&lt;/li&gt;
&lt;li&gt;It shows a lack of professionalism&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Focus on what you learned, what you’re looking for now, and how you want to grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  18. Research the Interviewers &amp;amp; Use AI to Simulate Interviews
&lt;/h3&gt;

&lt;p&gt;Before your interview, try to identify who will be interviewing you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look them up on LinkedIn or the company website&lt;/li&gt;
&lt;li&gt;Check their roles, backgrounds, technical focus, and seniority&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can give you hints on the likely topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are they more focused on culture?&lt;/li&gt;
&lt;li&gt;Are they technical experts in certain stacks?&lt;/li&gt;
&lt;li&gt;Are they product-oriented?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you know who you’ll be talking to, you can use AI tools like ChatGPT to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate possible behavioral or culture-fit questions based on the company’s mission and values&lt;/li&gt;
&lt;li&gt;Simulate technical interview questions for the specific tech stack&lt;/li&gt;
&lt;li&gt;Generate product-oriented questions if the role is customer-facing or domain-specific&lt;/li&gt;
&lt;li&gt;Practice your answers to feel more confident&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also search online for "Technology interview questions" to review common technical challenges for your target role.&lt;/p&gt;

&lt;h3&gt;
  
  
  19. First Interview: Know the Company &amp;amp; Sell Yourself
&lt;/h3&gt;

&lt;p&gt;Before your first interview:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Review the job description&lt;/li&gt;
&lt;li&gt;Identify which of your strengths align with the role&lt;/li&gt;
&lt;li&gt;Research the company to understand its mission and product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the interview, confidently (but humbly) talk about what you’re proud of. Show enthusiasm and provide context for your skills and experience.&lt;/p&gt;

&lt;p&gt;Adapt your tone and focus depending on the company: If they emphasize culture fit, show how your values align. If they stress technical depth, highlight your hard skills and project experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  20. Look Professional (Even on Camera)
&lt;/h3&gt;

&lt;p&gt;Appearances matter, especially in remote interviews. Make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have good lighting and your face is clearly visible&lt;/li&gt;
&lt;li&gt;Your camera angle is at eye level&lt;/li&gt;
&lt;li&gt;You wear clean, professional-looking clothes (even if it’s just the top half!)&lt;/li&gt;
&lt;li&gt;You use a neutral or blurred background if your real one isn’t suitable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These small touches help you appear prepared and confident.&lt;/p&gt;

&lt;h3&gt;
  
  
  21. Technical Interview: Review the Stack
&lt;/h3&gt;

&lt;p&gt;If a technical interview is part of the process, go over the technologies listed in the job ad. Prepare for common interview questions and brush up on both basic and advanced concepts depending on the level of the role.&lt;/p&gt;

&lt;p&gt;If you consistently fail technical interviews on certain technologies or topics, identify them and study them intentionally. Practice with exercises, tutorials, and small projects to build confidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  22. Ask Questions &amp;amp; Seek Feedback
&lt;/h3&gt;

&lt;p&gt;At every interview stage, ask questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In HR interviews, ask about working conditions, team structure, and expectations.&lt;/li&gt;
&lt;li&gt;In technical interviews, ask thoughtful questions about their stack, architecture, or dev culture. It shows interest and depth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Always request feedback after interviews. Whether you pass or not, it can help you improve. After technical challenges or live coding, thank the interviewers for their time and note what you learned. &lt;/p&gt;

&lt;p&gt;It leaves a good impression and helps build relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  23. Watch Your Words Until the Very End
&lt;/h3&gt;

&lt;p&gt;Often, we think the interview is going either really well or terribly, and we relax, or panic, and say things we shouldn't. Don’t make that mistake.&lt;br&gt;
Never assume you’ve passed or failed. The interview is still happening until you hang up the call. Stay professional throughout.&lt;/p&gt;

&lt;p&gt;You might feel like your technical interview was a disaster, only to find out later you passed. Or you might think everything went great and slip up in the last minute with an off-hand comment. Control your nerves and your words from start to finish. Always leave the best possible impression.&lt;/p&gt;

&lt;h3&gt;
  
  
  24. Live Coding: Explain Your Thought Process
&lt;/h3&gt;

&lt;p&gt;If you’re doing live coding with someone watching, always:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read the prompt carefully&lt;/li&gt;
&lt;li&gt;Explain your approach as you go&lt;/li&gt;
&lt;li&gt;Ask questions if something’s unclear&lt;/li&gt;
&lt;li&gt;Make the solution work first and then improve it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before these sessions, practice with coding katas or timed exercises in the relevant language/framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  25. Understand the Types of Live Coding
&lt;/h3&gt;

&lt;p&gt;Not all live coding challenges are the same. Ask in advance what type you'll face so you can prepare properly. Common formats include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code review of a broken or badly written snippet. Your task is to suggest improvements or spot bugs&lt;/li&gt;
&lt;li&gt;Fixing broken code, where you're asked to debug and correct functionality&lt;/li&gt;
&lt;li&gt;Katas, which may include algorithmic challenges or small component builds under time pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Be aware of restrictions. Some interviews may:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prohibit ChatGPT or other AIs&lt;/li&gt;
&lt;li&gt;Disallow Stack Overflow or Google searches&lt;/li&gt;
&lt;li&gt;Only allow access to official documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure you clarify the rules and, if needed, train your memory and problem-solving without relying on external tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  26. Take-Home Assignments: Impress Them
&lt;/h3&gt;

&lt;p&gt;If you’re given a take-home challenge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use technologies you’re strongest with&lt;/li&gt;
&lt;li&gt;Stick closely to the requirements&lt;/li&gt;
&lt;li&gt;Go above and beyond. Add documentation, tests, or even a polished README explaining your architecture and decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind: even if they say it takes “2 hours,” it usually takes more. Make the extra effort to stand out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 5: Final Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  27. Network Smartly
&lt;/h3&gt;

&lt;p&gt;Don't rely only on job portals. Talk to people. Reach out to connections or professionals in your field and ask if they know of any openings. Check company websites directly and when applying, craft thoughtful answers to open-ended questions.&lt;/p&gt;

&lt;p&gt;You can use ChatGPT to help you draft responses and improve your applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  28. Manage Expectations
&lt;/h3&gt;

&lt;p&gt;If you’ve been searching for a long time and keep hearing that your salary expectations are too high or that the market is tough, consider adjusting. Either adapt to the current market or be patient and wait for the right opportunity.&lt;/p&gt;

&lt;h3&gt;
  
  
  29. Be Patient (Really Patient)
&lt;/h3&gt;

&lt;p&gt;Job hunting, especially when you’ve set ambitious criteria, takes time. If you’re only applying to very specific roles (e.g., fully remote, niche tech stack, high salary), be ready to wait longer.&lt;/p&gt;

&lt;p&gt;That said, it’s okay to reevaluate if your conditions are too strict and you realize you don’t have unlimited time, savings, or patience. You can always ease some of your filters.&lt;/p&gt;

&lt;p&gt;Also, remember: many recruitment processes are slow, sometimes disorganized, and can take weeks (or months). Take breaks when needed, but trust the process and keep going.&lt;/p&gt;

&lt;h3&gt;
  
  
  30. Don’t Take It Personally
&lt;/h3&gt;

&lt;p&gt;Rejection is hard, but it doesn’t always mean you’re not good enough. Sometimes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re simply not the profile they were looking for at that moment&lt;/li&gt;
&lt;li&gt;Another candidate had just a bit more experience with the exact tool they needed&lt;/li&gt;
&lt;li&gt;Or your strengths lie in areas that weren’t evaluated deeply enough&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other cases, you may need to improve in specific areas, and that’s okay too. Use feedback to identify those gaps and work on them. But always keep in mind: one rejection (or ten) does not define your worth or potential.&lt;/p&gt;

&lt;h3&gt;
  
  
  31. Keep Going. It Gets Easier
&lt;/h3&gt;

&lt;p&gt;The first few interviews can be intimidating. You may feel caught off guard, especially in technical interviews or live coding sessions. But the more interviews you do, the more familiar the patterns become:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many questions will repeat across companies&lt;/li&gt;
&lt;li&gt;You’ll get better at explaining yourself&lt;/li&gt;
&lt;li&gt;You’ll become more comfortable under pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat each interview as practice for the next one. Confidence grows with repetition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 6: After the Offer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  32. Don’t Accept Immediately: Take Your Time
&lt;/h3&gt;

&lt;p&gt;When you receive an offer, don’t feel obligated to say yes on the spot.&lt;br&gt;
It’s perfectly acceptable, and even expected, to ask for a few days to evaluate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You may receive another offer shortly after&lt;/li&gt;
&lt;li&gt;You need to analyze salary, conditions, work model, growth potential, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid making emotional decisions in the heat of the moment. Take your time to compare offers calmly and make a decision that aligns with your long-term goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  33. Ask for a Pre-Contract (Offer Letter) Before Resigning
&lt;/h3&gt;

&lt;p&gt;Before resigning from your current job, request a pre-contract or offer letter that clearly states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Salary&lt;/li&gt;
&lt;li&gt;Start date&lt;/li&gt;
&lt;li&gt;Work model&lt;/li&gt;
&lt;li&gt;Benefits&lt;/li&gt;
&lt;li&gt;Any special agreements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides legal and psychological security, especially if you’re leaving a stable job.&lt;/p&gt;

&lt;p&gt;Having something signed avoids last-minute surprises and allows you to transition with confidence.&lt;/p&gt;

&lt;h3&gt;
  
  
  34. Rest and Prepare Before Starting the New Job
&lt;/h3&gt;

&lt;p&gt;Sometimes after signing the offer, the company may share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Technologies to review&lt;/li&gt;
&lt;li&gt;Tools or frameworks to familiarize yourself with&lt;/li&gt;
&lt;li&gt;Onboarding materials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s good to prepare, but don’t burn yourself out before even starting.&lt;br&gt;
If possible, negotiate a gap of a few days or weeks between jobs to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rest and recharge&lt;/li&gt;
&lt;li&gt;Reset your mind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start your new role with energy and clarity&lt;/p&gt;

&lt;p&gt;You’ll perform better if you start fresh, not exhausted.&lt;/p&gt;

&lt;h3&gt;
  
  
  35. Close the Loop: Inform Other Companies
&lt;/h3&gt;

&lt;p&gt;Once you’ve accepted an offer, inform other companies where you’re still in process that you’re no longer continuing:&lt;/p&gt;

&lt;p&gt;Respect the time and effort of recruiters and interviewers. It’s professional and leaves the door open for future opportunities. A short polite message is enough.&lt;/p&gt;

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

&lt;p&gt;Job hunting in tech can be a marathon, not a sprint. By defining your strategy, tracking your progress, preparing thoroughly, and staying proactive, you can significantly improve your chances, even in a tough market. Treat it like a project, stay consistent, and don’t be afraid to ask for help or adjust your approach as you go.&lt;/p&gt;

</description>
      <category>jobhunting</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Best Practices</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Fri, 08 Aug 2025 09:10:10 +0000</pubDate>
      <link>https://dev.to/miasalazar/react-best-practices-2acj</link>
      <guid>https://dev.to/miasalazar/react-best-practices-2acj</guid>
      <description>&lt;p&gt;React is powerful, but with great flexibility comes great responsibility. As your application grows, so does the complexity, and that’s when best practices become essential.&lt;/p&gt;

&lt;p&gt;In this article, we’ll walk through practical techniques and habits that help you write clean, maintainable, and scalable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Components Small and Focused
&lt;/h2&gt;

&lt;p&gt;A component should do one thing, and do it well. Split large components into smaller ones for better reusability and readability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Functional Components and Hooks
&lt;/h2&gt;

&lt;p&gt;Avoid using class components unless you have a specific reason (like legacy codebases). Functional components with hooks are simpler, cleaner, and the current standard in modern React development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Functional component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Counter() {
  const [count, setCount] = useState(0);
  return &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;{count}&amp;lt;/button&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Class component
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  handleClick = () =&amp;gt; {
    this.setState((prevState) =&amp;gt; ({
      count: prevState.count + 1
    }));
  };

  render() {
    return (
      &amp;lt;button onClick={this.handleClick}&amp;gt;
        {this.state.count}
      &amp;lt;/button&amp;gt;
    );
  }
}

export default Counter;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use a Clear Folder Structure
&lt;/h2&gt;

&lt;p&gt;There’s no single "perfect" folder structure in React. What matters most is that it’s clear, consistent, and aligned with your team’s chosen architecture.&lt;/p&gt;

&lt;p&gt;Whether you follow a feature-based, domain-driven, or atomic design approach, pick one that fits your app’s complexity and stick to it. Constantly mixing styles leads to confusion and tech debt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example of a feature-based structure:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  /features
    /auth
      AuthForm.tsx
      useAuth.ts
      authService.ts
    /dashboard
      Dashboard.tsx
      useDashboardData.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example of a clean architecture structure:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
  /domain
    user.ts
  /application
    useLogin.ts
  /infrastructure
    api.ts
  /presentation
    LoginForm.tsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Custom Hooks for Reusable Logic
&lt;/h2&gt;

&lt;p&gt;Whenever you find repeated logic across components, consider extracting it into a custom hook. Custom Hooks allow us to separate concerns, create cleaner and more testable components, and have better composition.&lt;/p&gt;

&lt;p&gt;Custom hooks are not just about reuse. They're about clarity.&lt;br&gt;
They help enforce clean architecture, reduce repetition, and improve the developer experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use TypeScript (if possible)
&lt;/h2&gt;

&lt;p&gt;Adding TypeScript helps catch bugs early, improves autocomplete, and makes code more robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid Prop Drilling with Context
&lt;/h2&gt;

&lt;p&gt;Prop drilling happens when you pass props through multiple layers of components just to get data to a deeply nested child. This makes your code harder to maintain and clutters component APIs.&lt;/p&gt;

&lt;p&gt;React Context allows you to share values like state, theme, language, or user data across your entire component tree without passing props manually at every level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Meaningful Names
&lt;/h2&gt;

&lt;p&gt;Good naming improves readability for everyone, including your future self.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write Tests for Critical Logic
&lt;/h2&gt;

&lt;p&gt;Writing tests for critical logic ensures that key functionality works as expected. Tests catch bugs early, reducing the risk of introducing errors in production and improving overall code stability. &lt;/p&gt;

&lt;p&gt;By testing the core behavior of your app, you ensure that essential features are always functional, even as new features are added or the codebase evolves.&lt;/p&gt;

&lt;p&gt;Additionally, tests act as living documentation. As your project grows, automated tests help new developers quickly understand how certain features should behave. They ensure that everyone on the team is aligned on expectations, improving collaboration and reducing the chance of miscommunication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;React is just a tool. The way you structure, write, and organize your code makes all the difference in long-term quality.&lt;/p&gt;

&lt;p&gt;Adopting these best practices doesn't mean rewriting everything overnight, but gradually improving your codebase will pay off in the long run. Your future self (and your teammates) will thank you.&lt;/p&gt;

</description>
      <category>react</category>
      <category>frontend</category>
      <category>cleancode</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>Clean Architecture in Front-End Development</title>
      <dc:creator>Mía Salazar</dc:creator>
      <pubDate>Sun, 01 Jun 2025 08:44:57 +0000</pubDate>
      <link>https://dev.to/miasalazar/clean-architecture-in-front-end-development-523n</link>
      <guid>https://dev.to/miasalazar/clean-architecture-in-front-end-development-523n</guid>
      <description>&lt;p&gt;Clean Architecture, introduced by Robert C. Martin, is a software design philosophy that emphasizes the separation of concerns and independence from frameworks or tools. &lt;/p&gt;

&lt;p&gt;While it originally gained traction in back-end development, it's increasingly being adapted to front-end projects, especially as these applications grow more complex.&lt;/p&gt;

&lt;p&gt;In this article, we'll break down what Clean Architecture means for front-end developers, explain its core layers, and show you how to apply it in real-world UI codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Clean Architecture?
&lt;/h2&gt;

&lt;p&gt;Clean Architecture organizes code into layers, forming concentric circles. Each layer depends only on the one inside it. This approach allows you to write code that is independent of frameworks, easy to test, and resilient to change.&lt;/p&gt;

&lt;p&gt;The main idea:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Your business logic should not depend on frameworks, databases, or UI code. These are implementation details that can change.&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Layers
&lt;/h2&gt;

&lt;p&gt;The traditional Clean Architecture model maps layers this way:&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%2Fwkmtz54dzbki4f98nc6c.webp" 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%2Fwkmtz54dzbki4f98nc6c.webp" alt="Layer diagram: the domain is in the center, the application layer around it, and the adapters layer on the outside" width="772" height="567"&gt;&lt;/a&gt; Image from &lt;a href="https://bespoyasov.me/blog/clean-architecture-on-frontend/" rel="noopener noreferrer"&gt;Clean Architecture on Frontend, Alex Bespoyasov&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities (Domain Layer): This layer is Framework-agnostic. It is for core business logic and domain models and it contains rules that rarely change
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type User = {
  email: string;
  password: string;
};

export const isValidEmail = (email: string): boolean =&amp;gt; {
  return email.includes('@');
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Use Cases (Application Layer): The use cases layer orchestrates how data flows between the domain and UI and it encapsulates application-specific rules
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const loginUser = async (
  email: string,
  password: string
): Promise&amp;lt;boolean&amp;gt; =&amp;gt; {
  if (!isValidEmail(email)) {
    throw new Error('Invalid email');
  }

  const user: User = { email, password };
  return await loginApi(user);
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Interface Adapters (Presentation Layer): Includes components, view models, presenters...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const LoginForm = () =&amp;gt; {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = async () =&amp;gt; {
    try {
      const success = await loginUser(email, password);
      alert(success ? 'Logged in!' : 'Login failed');
    } catch (error) {
      alert((error as Error).message);
    }
  };

  return (
    &amp;lt;form onSubmit={(e) =&amp;gt; e.preventDefault()}&amp;gt;
      &amp;lt;input
        type="text"
        placeholder="Email"
        value={email}
        onChange={(e) =&amp;gt; setEmail(e.target.value)}
      /&amp;gt;
      &amp;lt;input
        type="password"
        placeholder="Password"
        value={password}
        onChange={(e) =&amp;gt; setPassword(e.target.value)}
      /&amp;gt;
      &amp;lt;button onClick={handleLogin}&amp;gt;Login&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Frameworks &amp;amp; Drivers (Infrastructure Layer): These should only interact with your app through interfaces or adapters such as axios, fetch, local Storage...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const loginApi = async (user: User): Promise&amp;lt;boolean&amp;gt; =&amp;gt; {
  const response = await fetch('/api/login', {
    method: 'POST',
    body: JSON.stringify(user),
    headers: {
      'Content-Type': 'application/json',
    },
  });

  return response.ok;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Testability: You can test business logic without a browser or DOM.&lt;/li&gt;
&lt;li&gt;Maintainability: You can swap frameworks or APIs with minimal impact.&lt;/li&gt;
&lt;li&gt;Scalability: You can grow the codebase easily.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Clean Architecture isn't just a pattern: it's a mindset. In front-end development, it helps keep your application modular, testable, and framework-agnostic, which is especially valuable in a fast-evolving JavaScript ecosystem.&lt;/p&gt;

&lt;p&gt;Even if you don’t adopt all its principles at once, gradually introducing its ideas can lead to cleaner, more resilient code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interesting links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://bespoyasov.me/blog/clean-architecture-on-frontend/" rel="noopener noreferrer"&gt;https://bespoyasov.me/blog/clean-architecture-on-frontend/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/tagada216/clean-architecture-for-the-front-end-3ni4"&gt;https://dev.to/tagada216/clean-architecture-for-the-front-end-3ni4&lt;/a&gt;&lt;br&gt;
&lt;a href="https://eduardo-ottaviani.medium.com/a-definitive-guide-to-front-end-clean-architecture-3a62418becb4" rel="noopener noreferrer"&gt;https://eduardo-ottaviani.medium.com/a-definitive-guide-to-front-end-clean-architecture-3a62418becb4&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>cleanarquitecture</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
