<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged frontenddevelopment</title>
<link>https://coderlegion.com/tag/frontenddevelopment</link>
<description>Powered by Question2Answer</description>
<item>
<title>🔥 30 Days of Frontend — Day 5: React DevTools Profiler</title>
<link>https://coderlegion.com/31532/30-days-of-frontend-day-5-react-devtools-profiler</link>
<description>&lt;p&gt;When a React application starts feeling slow, one of the first things developers often do is reach for &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, or &lt;code&gt;React.memo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We've all seen this pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A component renders more often than expected.&lt;/li&gt;
&lt;li&gt;The UI feels sluggish when interacting with a page.&lt;/li&gt;
&lt;li&gt;A large list becomes noticeably slower as more items are added.&lt;/li&gt;
&lt;li&gt;Updating one piece of state seems to trigger work across an entire component tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The natural reaction is to start memoizing components and functions.&lt;/p&gt;
&lt;p&gt;But here's the problem: &lt;strong&gt;you might be optimizing code that isn't responsible for the slowdown in the first place.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;React performance optimization should start with understanding what is happening, not guessing what might be happening.&lt;/p&gt;
&lt;p&gt;That's where the &lt;strong&gt;React DevTools Profiler&lt;/strong&gt; becomes useful.&lt;/p&gt;
&lt;h3 id=&quot;1-what-is-the-react-devtools-profiler-&quot;&gt;1. What Is the React DevTools Profiler?&lt;/h3&gt;
&lt;p&gt;React DevTools is a browser extension that helps developers inspect React component trees, props, state, and other component-related information.&lt;/p&gt;
&lt;p&gt;It includes two particularly useful panels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Components:&lt;/strong&gt; Inspect the component hierarchy, props, state, and component details.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profiler:&lt;/strong&gt; Record rendering activity and investigate how React updated the component tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Profiler helps you understand the rendering work associated with a particular interaction.&lt;/p&gt;
&lt;p&gt;For example, imagine you're working on an e-commerce application with a product grid containing hundreds of products.&lt;/p&gt;
&lt;p&gt;When a user changes a filter, several things might happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The parent component updates.&lt;/li&gt;
&lt;li&gt;The product list renders again.&lt;/li&gt;
&lt;li&gt;Individual product cards render.&lt;/li&gt;
&lt;li&gt;Sorting or filtering calculations run.&lt;/li&gt;
&lt;li&gt;Some components render even though their visible data hasn't changed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some of this work might be necessary. Some might be avoidable.&lt;/p&gt;
&lt;p&gt;Instead of assuming which component is responsible, you can record the interaction and inspect the results.&lt;/p&gt;
&lt;p&gt;The goal isn't to eliminate every render. It's to understand whether the work is necessary and whether it affects the user experience.&lt;/p&gt;
&lt;h3 id=&quot;2-understanding-how-react-rendering-relates-to-profiling&quot;&gt;2. Understanding How React Rendering Relates to Profiling&lt;/h3&gt;
&lt;p&gt;Before opening the Profiler, it's worth understanding what it actually measures.&lt;/p&gt;
&lt;p&gt;A React update generally involves two important phases.&lt;/p&gt;
&lt;h4 id=&quot;the-render-phase&quot;&gt;The render phase&lt;/h4&gt;
&lt;p&gt;During the render phase, React calls components as needed to determine what the next UI should look like.&lt;/p&gt;
&lt;p&gt;This phase includes calculating the next React element tree and determining the changes required.&lt;/p&gt;
&lt;p&gt;A component rendering doesn't automatically mean that the browser DOM will change.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;function Counter({ count }) {
  console.log(&quot;Counter rendered&quot;);

  return &amp;lt;p&amp;gt;Count: {count}&amp;lt;/p&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whenever React calls &lt;code&gt;Counter&lt;/code&gt;, the component function executes and returns a React element describing the UI.&lt;/p&gt;
&lt;p&gt;React may then determine that the resulting output doesn't require a DOM mutation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A render is not the same thing as a DOM update.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This distinction is important because developers sometimes interpret every component render as expensive browser work.&lt;/p&gt;
&lt;h4 id=&quot;the-commit-phase&quot;&gt;The commit phase&lt;/h4&gt;
&lt;p&gt;After React finishes the necessary render work, it can commit the changes to the host environment, such as updating the DOM in a browser.&lt;/p&gt;
&lt;p&gt;The Profiler helps you investigate rendering activity, but its measurements shouldn't be interpreted as a complete measurement of every part of browser performance.&lt;/p&gt;
&lt;p&gt;For example, a page can have relatively inexpensive React rendering but still feel slow because of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expensive JavaScript outside React.&lt;/li&gt;
&lt;li&gt;Large amounts of DOM layout or painting.&lt;/li&gt;
&lt;li&gt;Long-running event handlers.&lt;/li&gt;
&lt;li&gt;Network delays.&lt;/li&gt;
&lt;li&gt;Large images or other resources.&lt;/li&gt;
&lt;li&gt;Main-thread work that blocks user interactions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why the React Profiler is one tool in a broader performance investigation, not a replacement for the browser's Performance panel.&lt;/p&gt;
&lt;h3 id=&quot;3-what-can-you-learn-from-the-profiler-&quot;&gt;3. What Can You Learn From the Profiler?&lt;/h3&gt;
&lt;p&gt;When you record a profiling session, the Profiler provides several useful ways to understand React's work.&lt;/p&gt;
&lt;h4 id=&quot;a-which-components-rendered-&quot;&gt;A. Which components rendered?&lt;/h4&gt;
&lt;p&gt;The Profiler helps you identify the components involved in an update.&lt;/p&gt;
&lt;p&gt;Suppose your component tree looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;App
├── Header
├── SearchBar
├── FilterSidebar
└── ProductGrid
    ├── ProductCard
    ├── ProductCard
    ├── ProductCard
    └── ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the user types into the search field, you might discover that &lt;code&gt;SearchBar&lt;/code&gt;, &lt;code&gt;ProductGrid&lt;/code&gt;, and many &lt;code&gt;ProductCard&lt;/code&gt; instances rendered.&lt;/p&gt;
&lt;p&gt;That doesn't automatically mean all those renders are unnecessary.&lt;/p&gt;
&lt;p&gt;You need to understand why they rendered and whether the work was expensive.&lt;/p&gt;
&lt;p&gt;The component tree gives you a starting point for that investigation.&lt;/p&gt;
&lt;h4 id=&quot;b-how-often-did-components-render-&quot;&gt;B. How often did components render?&lt;/h4&gt;
&lt;p&gt;Repeated rendering can be perfectly normal.&lt;/p&gt;
&lt;p&gt;For example, typing into a controlled input typically updates state as the user types:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;function SearchBar() {
  const [query, setQuery] = React.useState(&quot;&quot;);

  return (
    &amp;lt;input
      value={query}
      onChange={(event) =&amp;gt; {
        setQuery(event.target.value);
      }}
      placeholder=&quot;Search products...&quot;
    /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each keystroke can trigger an update.&lt;/p&gt;
&lt;p&gt;That's expected behavior.&lt;/p&gt;
&lt;p&gt;The more interesting question is what else happens during those updates.&lt;/p&gt;
&lt;p&gt;If typing into the search field also triggers expensive calculations or unnecessary rendering across a large product grid, the Profiler can help you investigate that work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Render frequency is a clue, not a performance verdict.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&quot;c-what-caused-a-component-to-render-&quot;&gt;C. What caused a component to render?&lt;/h4&gt;
&lt;p&gt;This is one of the most useful parts of profiling.&lt;/p&gt;
&lt;p&gt;A component might render because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Its state changed.&lt;/li&gt;
&lt;li&gt;Its parent rendered.&lt;/li&gt;
&lt;li&gt;Its props changed.&lt;/li&gt;
&lt;li&gt;Its context value changed.&lt;/li&gt;
&lt;li&gt;An external store or another subscription triggered an update.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The exact cause depends on the component and the update mechanism.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;function ProductPage() {
  const [query, setQuery] = React.useState(&quot;&quot;);
  const [selectedCategory, setSelectedCategory] =
    React.useState(&quot;all&quot;);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;SearchInput
        value={query}
        onChange={setQuery}
      /&amp;gt;

      &amp;lt;CategoryFilter
        value={selectedCategory}
        onChange={setSelectedCategory}
      /&amp;gt;

      &amp;lt;ProductGrid query={query} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When &lt;code&gt;selectedCategory&lt;/code&gt; changes, &lt;code&gt;ProductPage&lt;/code&gt; renders again.&lt;/p&gt;
&lt;p&gt;Because &lt;code&gt;ProductGrid&lt;/code&gt; is a child of &lt;code&gt;ProductPage&lt;/code&gt;, React may also render &lt;code&gt;ProductGrid&lt;/code&gt;, even though its &lt;code&gt;query&lt;/code&gt; prop hasn't changed.&lt;/p&gt;
&lt;p&gt;That can be a candidate for optimization, but it isn't automatically a problem. First, determine whether the work is expensive enough to matter.&lt;/p&gt;
&lt;p&gt;Also, remember that React DevTools' ability to display detailed render reasons depends on the React version, development tooling, and available settings. Don't assume every render will always have a definitive explanation displayed.&lt;/p&gt;
&lt;h3 id=&quot;4-how-to-use-react-devtools-profiler-a-step-by-step-workflow&quot;&gt;4. How to Use React DevTools Profiler: A Step-by-Step Workflow&lt;/h3&gt;
&lt;p&gt;Let's turn this into a practical workflow.&lt;/p&gt;
&lt;h4 id=&quot;step-1-reproduce-the-actual-performance-problem&quot;&gt;Step 1: Reproduce the actual performance problem&lt;/h4&gt;
&lt;p&gt;Start with the user interaction that feels slow.&lt;/p&gt;
&lt;p&gt;Examples include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Typing into a search field.&lt;/li&gt;
&lt;li&gt;Changing a product filter.&lt;/li&gt;
&lt;li&gt;Switching tabs.&lt;/li&gt;
&lt;li&gt;Expanding a large navigation menu.&lt;/li&gt;
&lt;li&gt;Updating a dashboard with multiple charts.&lt;/li&gt;
&lt;li&gt;Scrolling through a long list.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Avoid profiling random interactions without a clear question.&lt;/p&gt;
&lt;p&gt;A useful starting question might be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Why does changing a product filter cause so much rendering work?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This gives you a specific behavior to investigate.&lt;/p&gt;
&lt;h4 id=&quot;step-2-open-react-devtools&quot;&gt;Step 2: Open React DevTools&lt;/h4&gt;
&lt;p&gt;Install React Developer Tools for your browser if you haven't already.&lt;/p&gt;
&lt;p&gt;Open your application, launch the browser's developer tools, and locate the &lt;strong&gt;Profiler&lt;/strong&gt; tab.&lt;/p&gt;
&lt;p&gt;Make sure you're profiling the application and interaction you want to investigate.&lt;/p&gt;
&lt;p&gt;For realistic performance measurements, prefer a production build or a profiling-enabled production build where appropriate. Development mode can introduce extra overhead, and Strict Mode may intentionally invoke rendering-related logic more than once to help reveal bugs.&lt;/p&gt;
&lt;p&gt;Development profiling is still valuable for understanding component behavior, but don't assume its timings represent production performance.&lt;/p&gt;
&lt;h4 id=&quot;step-3-start-recording&quot;&gt;Step 3: Start recording&lt;/h4&gt;
&lt;p&gt;In the Profiler tab, start a recording.&lt;/p&gt;
&lt;p&gt;Then perform the exact interaction that causes the slowdown.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start recording.&lt;/li&gt;
&lt;li&gt;Type a search query.&lt;/li&gt;
&lt;li&gt;Change a category filter.&lt;/li&gt;
&lt;li&gt;Wait for the UI to settle.&lt;/li&gt;
&lt;li&gt;Stop recording.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Keep the recording focused.&lt;/p&gt;
&lt;h4 id=&quot;step-4-inspect-the-recorded-commits&quot;&gt;Step 4: Inspect the recorded commits&lt;/h4&gt;
&lt;p&gt;The Profiler organizes recorded updates into commits.&lt;/p&gt;
&lt;p&gt;A commit represents a point at which React applied an update to the host environment&lt;/p&gt;
&lt;p&gt;Select a commit related to your interaction, then inspect the available visualization and component details.&lt;/p&gt;
&lt;p&gt;Look for patterns such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A large subtree rendering during a small interaction.&lt;/li&gt;
&lt;li&gt;An expensive component repeatedly appearing in relevant commits.&lt;/li&gt;
&lt;li&gt;Components rendering even though their inputs appear unchanged.&lt;/li&gt;
&lt;li&gt;Expensive calculations associated with frequently occurring updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don't immediately optimize the component with the largest-looking bar. First establish what the measurement represents and whether that component is related to the user-visible problem.&lt;/p&gt;
&lt;h4 id=&quot;step-5-make-one-targeted-change&quot;&gt;Step 5: Make one targeted change&lt;/h4&gt;
&lt;p&gt;Change one thing at a time whenever possible.&lt;/p&gt;
&lt;p&gt;If you simultaneously add &lt;code&gt;React.memo&lt;/code&gt;, introduce several &lt;code&gt;useMemo&lt;/code&gt; calls, restructure the component tree, and change how state is managed, you won't know which change made the difference.&lt;/p&gt;
&lt;p&gt;A focused experiment makes the results easier to interpret.&lt;/p&gt;
&lt;h4 id=&quot;step-6-profile-again&quot;&gt;Step 6: Profile again&lt;/h4&gt;
&lt;p&gt;Repeat the same interaction under comparable conditions.&lt;/p&gt;
&lt;p&gt;Compare:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Actual rendering duration.&lt;/li&gt;
&lt;li&gt;Which components rendered.&lt;/li&gt;
&lt;li&gt;How much of the subtree participated in the update.&lt;/li&gt;
&lt;li&gt;Whether the interaction feels more responsive.&lt;/li&gt;
&lt;li&gt;Whether the optimization introduced additional complexity or bugs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the measured React work decreased but the interaction still feels slow, investigate other parts of the performance pipeline.&lt;/p&gt;
&lt;p&gt;An optimization isn't complete until you've verified its effect.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The React DevTools Profiler helps turn vague performance complaints into concrete questions about rendering behavior.&lt;/p&gt;
&lt;p&gt;Instead of asking:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Why is React so slow?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Start by asking:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Where is my application actually spending time, and what evidence do I have?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That shift—from guessing to measuring—is what makes performance optimization more systematic.&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/31532/30-days-of-frontend-day-5-react-devtools-profiler</guid>
<pubDate>Sat, 17 Oct 2026 16:39:44 +0000</pubDate>
</item>
<item>
<title>🔥 30 Days of Frontend — Day 4: Memoization in React</title>
<link>https://coderlegion.com/30728/30-days-of-frontend-day-4-memoization-in-react</link>
<description>&lt;p&gt;Have you ever looked at a React component and thought:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;“Maybe I should wrap this function with &lt;code&gt;useCallback&lt;/code&gt;, this calculation with &lt;code&gt;useMemo&lt;/code&gt;, and the component with &lt;code&gt;React.memo&lt;/code&gt;?”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You're not alone.&lt;/p&gt;
&lt;p&gt;Memoization is one of the most frequently discussed React performance techniques. But it's also one of the easiest to misuse.&lt;/p&gt;
&lt;p&gt;You can add memoization to an application, introduce more complexity, and still fail to improve its performance.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Because memoization is not about preventing every render. It's about avoiding work that doesn't need to happen again.&lt;/p&gt;
&lt;p&gt;Let's understand how it works, when it helps, and when it becomes unnecessary complexity.&lt;/p&gt;
&lt;h3 id=&quot;1-what-is-memoization-&quot;&gt;1. What Is Memoization?&lt;/h3&gt;
&lt;p&gt;Memoization is an optimization technique that caches the result of a computation so it can be reused when the relevant inputs haven't changed.&lt;/p&gt;
&lt;p&gt;Imagine you have an expensive function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;function calculateTotalPrice(products: Product[]) {
  console.log(&quot;Calculating total price...&quot;);

  return products.reduce(
    (total, product) =&amp;gt; total + product.price,
    0
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every time you call this function, it calculates the total again.&lt;/p&gt;
&lt;p&gt;If the product list hasn't changed, repeating the same calculation may be unnecessary.&lt;/p&gt;
&lt;p&gt;Memoization lets us reuse a previous result when the inputs are still valid.&lt;/p&gt;
&lt;p&gt;Conceptually:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Inputs
  |
  v
Have relevant inputs changed?
  |
  +---- Yes ----&amp;gt; Recalculate and cache the result
  |
  +---- No -----&amp;gt; Reuse the cached result
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;React provides three commonly used memoization APIs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useMemo&lt;/code&gt; — caches a calculated value.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useCallback&lt;/code&gt; — caches a function reference.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;React.memo&lt;/code&gt; — can skip a component render when its props are unchanged.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They solve different problems, so they shouldn't be treated as interchangeable.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-usememo-cache-an-expensive-calculation&quot;&gt;2. &lt;code&gt;useMemo&lt;/code&gt;: Cache an Expensive Calculation&lt;/h3&gt;
&lt;p&gt;Consider a product dashboard containing thousands of products.&lt;/p&gt;
&lt;p&gt;You need to filter products by category and calculate which products match a search query.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;function ProductList({
  products,
  search,
}: {
  products: Product[];
  search: string;
}) {
  const filteredProducts = products.filter((product) =&amp;gt;
    product.name.toLowerCase().includes(search.toLowerCase())
  );

  return (
    &amp;lt;ul&amp;gt;
      {filteredProducts.map((product) =&amp;gt; (
        &amp;lt;li key={product.id}&amp;gt;{product.name}&amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The filtering operation runs whenever &lt;code&gt;ProductList&lt;/code&gt; renders.&lt;/p&gt;
&lt;p&gt;That may be perfectly fine for a small list. But imagine the filtering logic is expensive and the component also renders because some unrelated state changes.&lt;/p&gt;
&lt;p&gt;We can cache the calculated array with &lt;code&gt;useMemo&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { useMemo } from &quot;react&quot;;

function ProductList({
  products,
  search,
}: {
  products: Product[];
  search: string;
}) {
  const filteredProducts = useMemo(() =&amp;gt; {
    return products.filter((product) =&amp;gt;
      product.name.toLowerCase().includes(search.toLowerCase())
    );
  }, [products, search]);

  return (
    &amp;lt;ul&amp;gt;
      {filteredProducts.map((product) =&amp;gt; (
        &amp;lt;li key={product.id}&amp;gt;{product.name}&amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;what-changed-&quot;&gt;What changed?&lt;/h4&gt;
&lt;p&gt;React recalculates &lt;code&gt;filteredProducts&lt;/code&gt; when &lt;code&gt;products&lt;/code&gt; or &lt;code&gt;search&lt;/code&gt; changes.&lt;/p&gt;
&lt;p&gt;If the component renders again while both dependencies remain unchanged, React can reuse the previous result.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Initial render
  └── products + search
        └── Calculate filtered products

Unrelated state changes
  └── products + search unchanged
        └── Reuse cached result

Search changes
  └── New search value
        └── Calculate filtered products again
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;an-important-limitation&quot;&gt;An important limitation&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;useMemo&lt;/code&gt; does not make every search update faster.&lt;/p&gt;
&lt;p&gt;When the user types another character, &lt;code&gt;search&lt;/code&gt; changes. The filtering calculation must run again to produce the correct results.&lt;/p&gt;
&lt;p&gt;Memoization is most useful when a calculation is expensive and its dependencies remain unchanged across renders.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-usecallback-cache-a-function-reference&quot;&gt;3. &lt;code&gt;useCallback&lt;/code&gt;: Cache a Function Reference&lt;/h3&gt;
&lt;p&gt;Now let's look at &lt;code&gt;useCallback&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Consider a parent component that passes an event handler to a child:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;function ProductPage() {
  const [count, setCount] = useState(0);

  const handleAddToCart = (productId: number) =&amp;gt; {
    console.log(&quot;Added product:&quot;, productId);
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;
        Count: {count}
      &amp;lt;/button&amp;gt;

      &amp;lt;ProductCard onAddToCart={handleAddToCart} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Whenever &lt;code&gt;ProductPage&lt;/code&gt; renders, the function expression creates a new function reference.&lt;/p&gt;
&lt;p&gt;Even though the function's logic hasn't changed, the reference is different.&lt;/p&gt;
&lt;p&gt;That matters if &lt;code&gt;ProductCard&lt;/code&gt; is memoized and receives the handler as a prop.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const ProductCard = React.memo(function ProductCard({
  onAddToCart,
}: {
  onAddToCart: (productId: number) =&amp;gt; void;
}) {
  console.log(&quot;ProductCard rendered&quot;);

  return (
    &amp;lt;button onClick={() =&amp;gt; onAddToCart(42)}&amp;gt;
      Add to cart
    &amp;lt;/button&amp;gt;
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default, &lt;code&gt;React.memo&lt;/code&gt; compares props. A new function reference means the handler prop is considered changed, so the child may render again.&lt;/p&gt;
&lt;p&gt;We can stabilize the function reference with &lt;code&gt;useCallback&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { useCallback, useState } from &quot;react&quot;;

function ProductPage() {
  const [count, setCount] = useState(0);

  const handleAddToCart = useCallback((productId: number) =&amp;gt; {
    console.log(&quot;Added product:&quot;, productId);
  }, []);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;
        Count: {count}
      &amp;lt;/button&amp;gt;

      &amp;lt;ProductCard onAddToCart={handleAddToCart} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because the callback doesn't depend on any reactive values from the component, its dependency array is empty.&lt;/p&gt;
&lt;p&gt;Now, when &lt;code&gt;count&lt;/code&gt; changes, React can reuse the same callback reference. That allows the memoized &lt;code&gt;ProductCard&lt;/code&gt; to skip rendering if its other props also remain unchanged.&lt;/p&gt;
&lt;h4 id=&quot;what-about-dependencies-&quot;&gt;What about dependencies?&lt;/h4&gt;
&lt;p&gt;Consider this callback:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const handleAddToCart = useCallback(() =&amp;gt; {
  setCartCount(cartCount + 1);
}, [cartCount]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The callback depends on &lt;code&gt;cartCount&lt;/code&gt;, so its reference changes whenever &lt;code&gt;cartCount&lt;/code&gt; changes.&lt;/p&gt;
&lt;p&gt;For state updates that depend on the previous state, a functional update can sometimes avoid that dependency:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const handleAddToCart = useCallback(() =&amp;gt; {
  setCartCount((currentCount) =&amp;gt; currentCount + 1);
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works because the updater receives the latest state value.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; &lt;code&gt;useCallback&lt;/code&gt; caches a function reference; it doesn't make the function's execution inherently faster.&lt;/p&gt;
&lt;p&gt;If you're not passing the function to a memoized child or using it in another dependency-sensitive context, &lt;code&gt;useCallback&lt;/code&gt; may provide no meaningful benefit.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-react-memo-skip-unnecessary-component-renders&quot;&gt;4. &lt;code&gt;React.memo&lt;/code&gt;: Skip Unnecessary Component Renders&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;React.memo&lt;/code&gt; is different from the two hooks.&lt;/p&gt;
&lt;p&gt;It wraps a component and lets React skip rendering it when its props are unchanged, subject to React's normal rendering behavior.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const ProductCard = React.memo(function ProductCard({
  name,
  price,
}: {
  name: string;
  price: number;
}) {
  console.log(&quot;Rendering ProductCard:&quot;, name);

  return (
    &amp;lt;article&amp;gt;
      &amp;lt;h3&amp;gt;{name}&amp;lt;/h3&amp;gt;
      &amp;lt;p&amp;gt;${price}&amp;lt;/p&amp;gt;
    &amp;lt;/article&amp;gt;
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Suppose the parent updates a separate counter:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;function ProductPage() {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount((current) =&amp;gt; current + 1)}&amp;gt;
        Count: {count}
      &amp;lt;/button&amp;gt;

      &amp;lt;ProductCard name=&quot;Keyboard&quot; price={120} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The parent renders when the counter changes, but the &lt;code&gt;ProductCard&lt;/code&gt; props remain the same.&lt;/p&gt;
&lt;p&gt;React can skip rendering &lt;code&gt;ProductCard&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;React.memo&lt;/code&gt; is not an absolute rendering lock. The component can still render because of its own state changes, consumed context changes, or other React behavior.&lt;/p&gt;
&lt;h4 id=&quot;a-common-mistake-unstable-object-props&quot;&gt;A common mistake: unstable object props&lt;/h4&gt;
&lt;p&gt;Consider this example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;&amp;lt;ProductCard
  product={{
    id: 1,
    name: &quot;Keyboard&quot;,
    price: 120,
  }}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A new object is created whenever the parent renders.&lt;/p&gt;
&lt;p&gt;Even if the object contains the same data, its reference is different.&lt;/p&gt;
&lt;p&gt;Consequently, a memoized child can still render.&lt;/p&gt;
&lt;p&gt;This is why understanding referential equality matters when optimizing React applications.&lt;/p&gt;
&lt;p&gt;Two objects can contain identical properties and still be different references:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const first = { name: &quot;Keyboard&quot; };
const second = { name: &quot;Keyboard&quot; };

console.log(first === second); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Memoization works best when the values that cross component boundaries have the stability needed for the optimization to be effective.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-how-these-three-apis-work-together&quot;&gt;5. How These Three APIs Work Together&lt;/h3&gt;
&lt;p&gt;Let's put the concepts together.&lt;/p&gt;
&lt;p&gt;Imagine a dashboard with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A product search field&lt;/li&gt;
&lt;li&gt;A product list&lt;/li&gt;
&lt;li&gt;A shopping cart counter&lt;/li&gt;
&lt;li&gt;Expensive product filtering&lt;/li&gt;
&lt;li&gt;Memoized product cards&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A possible optimization strategy is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;ProductPage
    |
    ├── useCallback
    |      └── Stabilize a handler passed to a memoized child
    |
    ├── useMemo
    |      └── Cache filtered products when dependencies are unchanged
    |
    └── ProductList
           |
           └── React.memo
                  └── Skip rendering when props are unchanged
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The APIs address different sources of repeated work:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;API &lt;/th&gt;&lt;th&gt;What it caches or optimizes &lt;/th&gt;&lt;th&gt;Useful when&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;useMemo&lt;/code&gt; &lt;/td&gt;&lt;td&gt;A calculated value &lt;/td&gt;&lt;td&gt;A calculation is expensive and dependencies often stay unchanged&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;useCallback&lt;/code&gt; &lt;/td&gt;&lt;td&gt;A function reference &lt;/td&gt;&lt;td&gt;Stable identity helps a memoized child or dependency-sensitive hook&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;React.memo&lt;/code&gt; &lt;/td&gt;&lt;td&gt;A component's render work based on props &lt;/td&gt;&lt;td&gt;A component renders often with unchanged props and rendering is costly&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The key is not to use all three together automatically. Use only the optimization that addresses the measured bottleneck.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;6-when-memoization-doesn-t-help&quot;&gt;6. When Memoization Doesn't Help&lt;/h3&gt;
&lt;p&gt;Memoization has costs too.&lt;/p&gt;
&lt;p&gt;It adds some combination of dependency tracking, comparisons, cached values, and code complexity.&lt;/p&gt;
&lt;p&gt;Consider this example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const fullName = useMemo(() =&amp;gt; {
  return `${firstName} ${lastName}`;
}, [firstName, lastName]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unless there is a specific reason to cache this value, the direct version is simpler:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const fullName = `${firstName} ${lastName}`;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Combining two strings is inexpensive. Memoizing it is unlikely to produce a measurable improvement.&lt;/p&gt;
&lt;p&gt;Another example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;const handleClick = useCallback(() =&amp;gt; {
  console.log(&quot;Clicked&quot;);
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If this function is used only by a regular button in the same component, stabilizing its identity may not improve anything.&lt;/p&gt;
&lt;p&gt;The lesson is simple:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not every calculation is expensive, not every render is a problem, and not every new function reference matters.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;7-react-compiler-changes-the-conversation&quot;&gt;7. React Compiler Changes the Conversation&lt;/h3&gt;
&lt;p&gt;Modern React projects may use the React Compiler, which can automatically memoize components, values, and functions when it can safely do so.&lt;/p&gt;
&lt;p&gt;This means manually adding &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt;, and &lt;code&gt;React.memo&lt;/code&gt; everywhere is less necessary in compiler-enabled applications.&lt;/p&gt;
&lt;p&gt;However, the compiler does not eliminate the need to understand performance.&lt;/p&gt;
&lt;p&gt;It cannot make every expensive algorithm cheap, remove the cost of rendering thousands of unnecessary elements, or guarantee that a slow interaction will become fast.&lt;/p&gt;
&lt;p&gt;You should still understand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What triggers a render&lt;/li&gt;
&lt;li&gt;How props and references change&lt;/li&gt;
&lt;li&gt;Which calculations are expensive&lt;/li&gt;
&lt;li&gt;When state should live closer to the components that use it&lt;/li&gt;
&lt;li&gt;How to measure actual rendering performance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If your project uses React Compiler, follow its guidance and avoid adding manual memoization without a reason. Manual memoization can still be useful in appropriate cases, but it shouldn't be automatic boilerplate.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;8-final-takeaway&quot;&gt;8. Final Takeaway&lt;/h3&gt;
&lt;p&gt;Memoization is a tool, not a coding style, and the goal isn't to eliminate every render, the goal is to make the application responsive while keeping the code maintainable.&lt;/p&gt;
&lt;p&gt;My preferred performance workflow remains:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Measure → Identify the bottleneck → Optimize → Measure again.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Don't optimize because a component rendered, optimize because you've found work that is unnecessarily expensive.&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/30728/30-days-of-frontend-day-4-memoization-in-react</guid>
<pubDate>Sun, 11 Oct 2026 17:45:13 +0000</pubDate>
</item>
<item>
<title>🔥 30 Days of Frontend — Day 2: React Reconciliation</title>
<link>https://coderlegion.com/28635/30-days-of-frontend-day-2-react-reconciliation</link>
<description>&lt;p&gt;Why doesn't React update the entire UI after every state change?&lt;/p&gt;
&lt;p&gt;Because React uses &lt;strong&gt;reconciliation&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When a component renders again, React produces a new element tree.&lt;/p&gt;
&lt;p&gt;React then determines what changed compared with the previous result and prepares the necessary updates.&lt;/p&gt;
&lt;p&gt;Think of it as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Previous tree + New tree
          ↓
    Reconciliation
          ↓
   Required updates
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;-a-simple-example&quot;&gt;🧠 A Simple Example&lt;/h3&gt;
&lt;p&gt;Imagine we have a list of todos:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;function TodoList({ todos }) {
  return (
    &amp;lt;ul&amp;gt;
      {todos.map((todo) =&amp;gt; (
        &amp;lt;TodoItem key={todo.id} todo={todo} /&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Initially, our list looks like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;[A, B, C]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then it changes to:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;[A, B, D]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Because we're using stable keys, React can reason about the identity of each item:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;A → same item
B → same item
C → removed
D → new item
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The important part isn't just that the data changed.&lt;/p&gt;
&lt;p&gt;It's that React can understand &lt;strong&gt;which elements represent the same identity across renders&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;-why-do-keys-matter-&quot;&gt;🔑 Why Do Keys Matter?&lt;/h3&gt;
&lt;p&gt;Consider this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;items.map((item) =&amp;gt; (
  &amp;lt;Item key={Math.random()} /&amp;gt;
))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Every render produces a different key.&lt;/p&gt;
&lt;p&gt;That makes it difficult for React to identify the item as the same item from the previous render.&lt;/p&gt;
&lt;p&gt;Instead, use a stable identifier:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;items.map((item) =&amp;gt; (
  &amp;lt;Item key={item.id} /&amp;gt;
))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now React has a stable way to understand:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;This is the same item as before.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This becomes especially important when components contain local state.&lt;/p&gt;
&lt;p&gt;For example, if each &lt;code&gt;Item&lt;/code&gt; contains an input field, unstable keys can cause component instances to be recreated and lead to unexpected state behavior.&lt;/p&gt;
&lt;h3 id=&quot;-a-useful-mental-model&quot;&gt;🧩 A Useful Mental Model&lt;/h3&gt;
&lt;p&gt;When debugging list rendering, don't only ask:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Why did this component render?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Also ask:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Does React know this is the same component as before?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That question can help explain many confusing behaviors involving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;List keys&lt;/li&gt;
&lt;li&gt;Component identity&lt;/li&gt;
&lt;li&gt;Local state&lt;/li&gt;
&lt;li&gt;Re-renders&lt;/li&gt;
&lt;li&gt;Elements being added or removed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-where-does-reconciliation-happen-&quot;&gt;⚙️ Where Does Reconciliation Happen?&lt;/h3&gt;
&lt;p&gt;Reconciliation happens during React's &lt;strong&gt;render phase&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;React determines what work needs to be done first. The resulting changes are then applied during the &lt;strong&gt;commit phase&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;A simplified mental model is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;State Update
     ↓
Render
     ↓
Reconciliation
     ↓
Determine required changes
     ↓
Commit
     ↓
DOM updates
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's important to remember that rendering does not mean React immediately changes the DOM.&lt;/p&gt;
&lt;p&gt;The render phase is where React figures out what the next UI should look like.&lt;/p&gt;
&lt;p&gt;The commit phase is where React applies the necessary changes to the DOM.&lt;/p&gt;
&lt;h3 id=&quot;-the-takeaway&quot;&gt;🎯 The Takeaway&lt;/h3&gt;
&lt;p&gt;Reconciliation is one of the core ideas behind how React updates the UI efficiently.&lt;/p&gt;
&lt;p&gt;Once you understand reconciliation, concepts like keys, component identity, and rendering behavior become much easier to reason about.&lt;/p&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/28635/30-days-of-frontend-day-2-react-reconciliation</guid>
<pubDate>Fri, 25 Sep 2026 17:17:09 +0000</pubDate>
</item>
<item>
<title>SEO Basics Every Frontend Developer Should Know</title>
<link>https://coderlegion.com/23011/seo-basics-every-frontend-developer-should-know</link>
<description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;SEO gets treated like it's purely a marketing job — write good content, use the right keywords, done. But a huge chunk of what actually affects search rankings is technical, and it lives entirely in the code, meaning it's the frontend developer's job whether anyone officially assigns it or not.&lt;/p&gt;
&lt;p&gt;Here's what I actually implement on every project, client or personal, without needing a marketing background.&lt;/p&gt;
&lt;h2 id=&quot;1-semantic-html-this-matters-more-than-you-think-&quot;&gt;1. Semantic HTML (This Matters More Than You Think)&lt;/h2&gt;
&lt;p&gt;Search engines read your HTML structure to understand what's important on the page.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- Weak --&amp;gt;
&amp;lt;div class=&quot;title&quot;&amp;gt;Best Frontend Tools&amp;lt;/div&amp;gt;
&amp;lt;div class=&quot;text&quot;&amp;gt;Content here...&amp;lt;/div&amp;gt;

&amp;lt;!-- Semantic --&amp;gt;
&amp;lt;h1&amp;gt;Best Frontend Tools&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Content here...&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;rules-to-follow-&quot;&gt;Rules to follow:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;One &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; per page, describing the main topic&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;h2&amp;gt;, &amp;lt;h3&amp;gt;&lt;/code&gt; in proper hierarchical order, not just for visualsize&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;&amp;lt;nav&amp;gt;, &amp;lt;header&amp;gt;, &amp;lt;main&amp;gt;, &amp;lt;footer&amp;gt;, &amp;lt;article&amp;gt;&lt;/code&gt; where appropriate instead of generic &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;s everywhere&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;2-meta-tags-the-basics-actually-matter-&quot;&gt;2. Meta Tags (The Basics Actually Matter)&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;15 Free Frontend Tools Every Developer Should Know | Your Site&amp;lt;/title&amp;gt;
  &amp;lt;meta name=&quot;description&quot; content=&quot;Discover 15 free frontend tools for design, CSS, icons, and testing — perfect for beginners and pros.&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; should be unique per page, under ~60 characters, with your main keyword near the front&lt;/li&gt;
&lt;li&gt;&lt;code&gt;meta description&lt;/code&gt; doesn't directly boost ranking, but it's what shows in search results — a good one improves click-through rate, which does matter&lt;/li&gt;
&lt;li&gt;&lt;code&gt;viewport&lt;/code&gt; meta tag is required for mobile-friendliness, which Google explicitly factors into ranking&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-image-alt-text&quot;&gt;3. Image Alt Text&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&quot;react-hooks-diagram.png&quot; alt=&quot;Diagram showing useState and useEffect hook lifecycle in React&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alt text serves two purposes: accessibility (screen readers rely on it) and SEO (search engines can't &quot;see&quot; images, only read this text). Never leave it empty on meaningful images, and never stuff it with random keywords — describe what's actually in the image.&lt;/p&gt;
&lt;h2 id=&quot;4-page-speed-a-direct-ranking-factor-&quot;&gt;4. Page Speed (A Direct Ranking Factor)&lt;/h2&gt;
&lt;p&gt;Google explicitly uses Core Web Vitals — loading speed, interactivity, and visual stability — as ranking signals. This connects directly to earlier articles in this series:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optimize images with Squoosh or TinyPNG (Article 1)&lt;/li&gt;
&lt;li&gt;Use max-width: 100% and proper responsive images instead of oversized&lt;br&gt;
files (Article 6)&lt;/li&gt;
&lt;li&gt;Lazy-load images below the fold: &lt;code&gt;&amp;lt;img loading=&quot;lazy&quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Check your score with Lighthouse and fix what it flags (Article 1)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A fast site isn't just a nice-to-have anymore — it's a direct, measurable ranking factor.&lt;/p&gt;
&lt;h2 id=&quot;5-mobile-friendliness&quot;&gt;5. Mobile-Friendliness&lt;/h2&gt;
&lt;p&gt;Google uses mobile-first indexing, meaning it primarily looks at your site's mobile version when determining rankings, even for desktop search results. Everything covered in Article 6 (Responsive Design) directly affects SEO, not just user experience.&lt;/p&gt;
&lt;h2 id=&quot;6-clean-descriptive-urls&quot;&gt;6. Clean, Descriptive URLs&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Weak:  yoursite.com/page?id=4829
Better: yoursite.com/blog/free-frontend-tools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Descriptive URLs help both search engines and users understand what a page is about before even clicking.&lt;/p&gt;
&lt;h2 id=&quot;7-internal-linking&quot;&gt;7. Internal Linking&lt;/h2&gt;
&lt;p&gt;Link related pages/articles to each other within your site (like this series does, referencing earlier articles). This helps search engines understand your site structure and helps visitors discover more of your content — both of which support better rankings over time.&lt;/p&gt;
&lt;h2 id=&quot;8-structured-data-optional-but-powerful-&quot;&gt;8. Structured Data (Optional but Powerful)&lt;/h2&gt;
&lt;p&gt;Adding Schema.org markup (JSON-LD format) helps search engines understand your content type — a blog post, a product, a review — and can unlock rich search result features like star ratings or FAQ dropdowns.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;application/ld+json&quot;&amp;gt;
{
  &quot;@context&quot;: &quot;https://schema.org&quot;,
  &quot;@type&quot;: &quot;Article&quot;,
  &quot;headline&quot;: &quot;SEO Basics Every Frontend Developer Should Know&quot;,
  &quot;author&quot;: &quot;Muhammad Farhan&quot;
}
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is more advanced and not essential for every project, but worth knowing it exists.&lt;/p&gt;
&lt;h2 id=&quot;common-beginner-mistakes&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Using &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; for everything instead of semantic tags. Costs you nothing to fix and genuinely helps both SEO and accessibility.&lt;/li&gt;
&lt;li&gt;Skipping alt text entirely. Easy to forget, meaningfully impactful when done right.&lt;/li&gt;
&lt;li&gt;Shipping unoptimized images. The single most common performance (and therefore SEO) killer on beginner and even client projects.&lt;/li&gt;
&lt;li&gt;Ignoring mobile experience because the desktop version &quot;looks fine.&quot; Google mostly doesn't care how your desktop version looks.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;You don't need to become an SEO specialist to meaningfully improve how a site ranks — most of the technical fundamentals are just good development practices you should be doing anyway: semantic HTML, fast load times, proper alt text, and mobile responsiveness. Build these habits into every project from the start, and SEO stops being a separate task tacked on at the end.&lt;/p&gt;
&lt;p&gt;That wraps this 15-article series — if you've followed along from Article 1, you now have a solid, practical foundation across CSS, React, tooling, deployment, freelancing, and SEO. Go build something with it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23011/seo-basics-every-frontend-developer-should-know</guid>
<pubDate>Tue, 01 Sep 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>No More Fake DOM: Testing Library Unit Tests in the Real Browser</title>
<link>https://coderlegion.com/25909/no-more-fake-dom-testing-library-unit-tests-in-the-real-browser</link>
<description>&lt;p&gt;Every Testing Library test you have written runs against a simulated DOM. You know this. You accepted it years ago, along with the small pile of things that come with it: no real layout, nothing ever drawn on a screen, &lt;code&gt;jsdom&lt;/code&gt; throwing on APIs it does not implement, and the quiet suspicion that a passing test and a working component are not quite the same claim.&lt;/p&gt;
&lt;p&gt;I co-maintain &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.npmjs.com/package/twd-js&quot;&gt;twd-js&lt;/a&gt;, which runs tests inside your actual dev server. It was built for flow testing: visit a route, click through the app, assert on what the user sees. Component testing was the thing it did not do, and I said so in print when I &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/kevinccbsg/in-browser-testing-vitest-browser-mode-and-twd-side-by-side-1i3j&quot;&gt;compared it to Vitest Browser Mode&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then I tried calling &lt;code&gt;render()&lt;/code&gt; inside a TWD test, mostly to see what would break.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { render, screen, cleanup } from &quot;@testing-library/react&quot;;
import { describe, it, afterEach } from &quot;twd-js/runner&quot;;
import { AppProvider } from &quot;@/context/AppContext&quot;;
import { twd } from &quot;twd-js&quot;;
import { Add } from &quot;../Add&quot;;
import { componentHost, restorePage } from &quot;@/twd-tests/support/componentHost&quot;;

describe(&quot;Add Component&quot;, () =&amp;gt; {
  afterEach(() =&amp;gt; {
    cleanup();
    restorePage();
  });

  it(&quot;renders the Add component&quot;, () =&amp;gt; {
    // componentHost() is a blank div on an empty page. More on it below.
    render(&amp;lt;AppProvider&amp;gt;&amp;lt;Add /&amp;gt;&amp;lt;/AppProvider&amp;gt;, { container: componentHost() });

    twd.should(screen.getByText(&quot;Add Item&quot;), &quot;be.visible&quot;);
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing broke. The component mounts into the page, the sidebar shows it running, and the assertion checks an element that exists in a real browser. Same Testing Library API, no fake DOM under it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/gj02099nimid4kw24kaz.png&quot; alt=&quot;component test in an actual browser&quot;&gt;&lt;/p&gt;
&lt;p&gt;That &lt;code&gt;AppProvider&lt;/code&gt; is the real one, not a test double. &lt;code&gt;Add&lt;/code&gt; uses a hook that reads from context and posts to an API, and in a real browser both of those work, so there is nothing to stand in for. That turns out to matter more than the missing jsdom.&lt;/p&gt;
&lt;h3 id=&quot;why-this-works-at-all&quot;&gt;Why this works at all&lt;/h3&gt;
&lt;p&gt;Testing Library was never tied to jsdom. &lt;code&gt;@testing-library/react&lt;/code&gt; renders a component into a DOM node and &lt;code&gt;@testing-library/dom&lt;/code&gt; queries it. jsdom is just the DOM most people hand it. Give it a real one and the same code runs, except now the component is actually on a screen, with a real size, a real position, and your CSS applied to it.&lt;/p&gt;
&lt;p&gt;TWD already runs inside your app in the browser, so the real DOM is right there. &lt;code&gt;render()&lt;/code&gt; uses it.&lt;/p&gt;
&lt;h3 id=&quot;the-setup&quot;&gt;The setup&lt;/h3&gt;
&lt;p&gt;One helper, and no changes to your app.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;render()&lt;/code&gt; appends its container to &lt;code&gt;document.body&lt;/code&gt;, so the component lands after the app, a full viewport below the layout. The app is also still on the page, so &lt;code&gt;screen&lt;/code&gt; matches its elements as well as the ones your test just rendered. Both of those are the same problem: the app is in the way.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;const HOST_ID = &quot;twd-component-host&quot;;
const APP_ROOT_ID = &quot;root&quot;;

let appRoot: HTMLElement | null = null;
let placeholder: Comment | null = null;

export function componentHost(): HTMLElement {
  detachApp();

  let host = document.getElementById(HOST_ID);
  if (!host) {
    host = document.createElement(&quot;div&quot;);
    host.id = HOST_ID;
  }
  if (!host.isConnected) {
    document.body.prepend(host);
  }

  host.innerHTML = &quot;&quot;;
  return host;
}

export function restorePage(): void {
  document.getElementById(HOST_ID)?.remove();
  attachApp();
}

function detachApp(): void {
  if (placeholder) return;

  const root = document.getElementById(APP_ROOT_ID);
  if (!root) return;

  appRoot = root;
  placeholder = document.createComment(&quot; app detached by twd component test &quot;);
  root.replaceWith(placeholder);
}

function attachApp(): void {
  if (!placeholder || !appRoot) return;

  placeholder.replaceWith(appRoot);
  placeholder = null;
  appRoot = null;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Detaching the app root is not the same as emptying it. &lt;code&gt;root.innerHTML = &quot;&quot;&lt;/code&gt; pulls the DOM out from under React while it still holds references to those nodes, and the app does not come back. Moving the node out and putting it back leaves the references intact, so &lt;code&gt;restorePage()&lt;/code&gt; returns a live app.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;prepend&lt;/code&gt; rather than &lt;code&gt;append&lt;/code&gt; puts the component at the top of the page instead of below where the app used to be, so you can watch it run without scrolling.&lt;/p&gt;
&lt;p&gt;The payoff is that &lt;code&gt;screen&lt;/code&gt; behaves exactly like it does in jsdom. The only thing in the document is what your test rendered, which also covers anything the component renders through a portal, since that lands on &lt;code&gt;document.body&lt;/code&gt; rather than inside the container.&lt;/p&gt;
&lt;p&gt;One detail worth keeping: &lt;code&gt;cleanup()&lt;/code&gt; and &lt;code&gt;restorePage()&lt;/code&gt; belong in &lt;code&gt;afterEach&lt;/code&gt;, not &lt;code&gt;beforeEach&lt;/code&gt;. In jsdom the environment is torn down for you between files. In a real browser it is not, so renders stack up, and your flow tests need the app back before they run.&lt;/p&gt;
&lt;p&gt;That is the whole setup. Your app does not change.&lt;/p&gt;
&lt;h3 id=&quot;two-traps&quot;&gt;Two traps&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;screenDom&lt;/code&gt; will not find your component.&lt;/strong&gt; TWD exposes &lt;code&gt;screenDom&lt;/code&gt;, a wrapper around Testing Library queries scoped to your app root so it never matches the TWD sidebar. Testing Library's &lt;code&gt;render()&lt;/code&gt; mounts outside that root. I probed it in a real app to be sure:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-plaintext&quot;&gt;container.parentElement=&amp;lt;body&amp;gt;   inside #root=false
screen: found   screenDom: not found   screenDomGlobal: found
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So use Testing Library's own &lt;code&gt;screen&lt;/code&gt;, or TWD's &lt;code&gt;screenDomGlobal&lt;/code&gt;, which queries the whole document. If you pick &lt;code&gt;screenDomGlobal&lt;/code&gt;, keep queries specific, because it can also match elements inside the sidebar.&lt;/p&gt;
&lt;p&gt;Everything else works normally. &lt;code&gt;twd.should&lt;/code&gt; takes any element you hand it, whether a query found it in your app or in a component you just rendered.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your test pattern probably says &lt;code&gt;.ts&lt;/code&gt;.&lt;/strong&gt; Component tests are &lt;code&gt;.tsx&lt;/code&gt;. A pattern of &lt;code&gt;/**/*.twd.test.ts&lt;/code&gt; skips them silently, with no error and no missing-file warning. They simply never appear in the sidebar:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;twd({
  testFilePattern: &quot;/**/*.twd.test.{ts,tsx}&quot;,
}),
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you also run Vitest in the same repo, exclude the browser tests from it. Vitest matches &lt;code&gt;*.test.tsx&lt;/code&gt; by default, collects the TWD files, finds no &lt;code&gt;describe&lt;/code&gt; it recognises, and fails the run with &lt;code&gt;No test suite found in file&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;test: {
  exclude: [...configDefaults.exclude, &quot;**/*.twd.test.*&quot;],
},
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;both-kinds-of-test-one-run&quot;&gt;Both kinds of test, one run&lt;/h3&gt;
&lt;p&gt;This is the part I did not expect to matter as much as it does.&lt;/p&gt;
&lt;p&gt;Component tests and flow tests are now the same kind of artifact. They are files in the same project, running in the same browser, in the same session, against the same instrumented bundle. So one command runs both:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-console&quot;&gt;$ npx twd-cli run
Running 14 test(s)...
Code coverage data written to .nyc_output/out.json

--- Run complete ---
  Passed: 14 | Failed: 0 | Skipped: 0
  Duration: 6.9s
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ten of those drive the whole app through routing, search, sorting and deletion. Four render a single dialog component in isolation. One coverage file comes out the other end, covering both.&lt;/p&gt;
&lt;p&gt;That last part is usually where multi-runner setups get tedious. Component coverage in one report, end-to-end coverage in another, and a merge step that someone maintains. Here there is nothing to merge, because there was only ever one run.&lt;/p&gt;
&lt;h3 id=&quot;where-each-style-fits&quot;&gt;Where each style fits&lt;/h3&gt;
&lt;p&gt;Rendering a component in isolation is the right move when the component is the subject: a form's validation states, a dialog that opens and closes, a table that sorts. You skip the navigation, you skip the fixtures, and the test says exactly what it is about.&lt;/p&gt;
&lt;p&gt;Flow tests stay the right move for anything that crosses a boundary. Routing, data loading, a sequence of screens, state that survives a navigation. Rendering a component in isolation to test those means rebuilding the app around it, which is how component test files end up longer than the components.&lt;/p&gt;
&lt;p&gt;The useful change is not that one replaced the other. It is that choosing between them is now a decision about scope, made per test, instead of a decision about which runner and which DOM you are committing to.&lt;/p&gt;
&lt;h3 id=&quot;try-it&quot;&gt;Try it&lt;/h3&gt;
&lt;p&gt;If you already have Testing Library tests, the fastest way to see this is to copy one, change the imports for &lt;code&gt;describe&lt;/code&gt; and &lt;code&gt;it&lt;/code&gt; to &lt;code&gt;twd-js/runner&lt;/code&gt;, and hand &lt;code&gt;render()&lt;/code&gt; the component host.&lt;/p&gt;
&lt;p&gt;The example app from this post is on GitHub, with the same component tested in jsdom and in the browser side by side: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/kevinccbsg/frontend-challenge&quot;&gt;kevinccbsg/frontend-challenge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In the next post I look at what happened when I put those two versions next to each other. The jsdom test mocked the hook it was testing through, and once I stopped mocking, it turned out the mocks had been doing most of the work.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25909/no-more-fake-dom-testing-library-unit-tests-in-the-real-browser</guid>
<pubDate>Mon, 31 Aug 2026 07:54:58 +0000</pubDate>
</item>
<item>
<title>How I Landed My First Freelance Client as a Frontend Developer</title>
<link>https://coderlegion.com/23010/how-i-landed-my-first-freelance-client-as-a-frontend-developer</link>
<description>&lt;h2 id=&quot;introduction-1&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I'm not going to pretend this was some overnight success story — it wasn't. It took real, unglamorous effort before anything happened. But I think that's exactly why this story is more useful than the polished &quot;I made $10k my first month&quot; posts you see floating around.&lt;/p&gt;
&lt;p&gt;Here's honestly what happened, and what I'd tell any beginner developer trying to land their first client right now.&lt;/p&gt;
&lt;h2 id=&quot;where-i-started&quot;&gt;Where I Started&lt;/h2&gt;
&lt;p&gt;I had a portfolio (see Article 12 for what actually goes into a good one), a few personal projects, and zero client work. No reviews, no testimonials, nothing to point to except &quot;trust me, I can build this.&quot;&lt;/p&gt;
&lt;p&gt;That's a genuinely hard position to sell from — and I want to be upfront about that instead of skipping past it.&lt;/p&gt;
&lt;h2 id=&quot;what-didn-t-work&quot;&gt;What Didn't Work&lt;/h2&gt;
&lt;p&gt;Mass-applying to generic Fiverr/Upwork gigs with a copy-pasted message. I sent probably 15-20 near-identical proposals early on. Zero responses. Clients can tell instantly when a message wasn't written specifically for their project.&lt;/p&gt;
&lt;p&gt;Underpricing to &quot;compete.&quot; I dropped my rate low, assuming price was the deciding factor. It wasn't — the clients I was losing to weren't choosing based on price; they were choosing based on trust, and a rock-bottom price can actually read as a red flag rather than a selling point.&lt;/p&gt;
&lt;h2 id=&quot;what-actually-worked&quot;&gt;What Actually Worked&lt;/h2&gt;
&lt;h3 id=&quot;1-i-stopped-applying-blind-and-started-researching-the-client-first&quot;&gt;1. I Stopped Applying Blind and Started Researching the Client First&lt;/h3&gt;
&lt;p&gt;Before sending a proposal, I'd actually look at the client's existing website or business, and mention something specific in my message.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Instead of: &quot;Hi, I'm a frontend developer available for your project.&quot;

I wrote: &quot;I checked out your current site — the mobile menu doesn't
open properly on iPhone Safari, which is likely costing you visitors.
I can fix that as part of rebuilding your homepage.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That single specific observation did more than 20 generic messages combined.&lt;/p&gt;
&lt;h3 id=&quot;2-i-led-with-a-live-demo-not-just-a-portfolio-link&quot;&gt;2. I Led With a Live Demo, Not Just a Portfolio Link&lt;/h3&gt;
&lt;p&gt;For one prospect, instead of just sending my portfolio, I built a quick, rough homepage mockup based on their existing brand and sent a live preview link alongside my proposal. It took maybe 90 minutes, and it was the deciding factor in getting that first &quot;yes.&quot;&lt;/p&gt;
&lt;p&gt;This doesn't scale to every application — but for a client you genuinely want, showing instead of just telling is worth the extra effort.&lt;/p&gt;
&lt;h3 id=&quot;3-i-asked-for-a-testimonial-immediately-after-finishing&quot;&gt;3. I Asked for a Testimonial Immediately After Finishing&lt;/h3&gt;
&lt;p&gt;The moment that first project wrapped up and the client was happy, I asked directly for a short written testimonial and permission to list the project in my portfolio. That single testimonial made every proposal after it noticeably stronger — I finally had proof, not just a promise.&lt;/p&gt;
&lt;h3 id=&quot;4-i-treated-the-first-project-as-a-portfolio-investment-not-just-a-paycheck&quot;&gt;4. I Treated the First Project as a Portfolio Investment, Not Just a Paycheck&lt;/h3&gt;
&lt;p&gt;I overdelivered slightly on that first project — a bit more polish, a bit more communication than strictly required. It wasn't about being a pushover; it was a deliberate decision, because that project was going to be my proof for every client after it.&lt;/p&gt;
&lt;h2 id=&quot;what-i-d-tell-beginners-specifically&quot;&gt;What I'd Tell Beginners Specifically&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Your first client won't come from volume — it'll come from one genuinely well-researched, specific pitch. Send fewer, better proposals.&lt;/li&gt;
&lt;li&gt;A rough live demo beats a polished portfolio link for a serious prospect. It proves you can actually do the specific thing they need, not just that you can build things in general.&lt;/li&gt;
&lt;li&gt;Don't undercharge to compete. Price confidently for the value, and let your specificity and communication build trust instead.&lt;/li&gt;
&lt;li&gt;Ask for a testimonial the moment you finish, while the client is happiest. Don't wait — that window closes fast.&lt;/li&gt;
&lt;li&gt;Your first project is marketing, not just income. Treat it that way, and the second client comes noticeably easier than the first.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts-1&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;There's no trick that skips the hard part — you do have to put in real, specific effort before that first client says yes. But once you have that first project and testimonial, everything after it gets meaningfully easier, because you're no longer selling a promise. You're selling proof.&lt;/p&gt;
&lt;p&gt;If you're still working on landing your first client, I'd genuinely love to hear where you're stuck — drop it in the comments.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23010/how-i-landed-my-first-freelance-client-as-a-frontend-developer</guid>
<pubDate>Fri, 28 Aug 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>How to Build a Portfolio Website That Actually Gets You Hired</title>
<link>https://coderlegion.com/23006/how-to-build-a-portfolio-website-that-actually-gets-you-hired</link>
<description>&lt;h2 id=&quot;introduction-2&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I've rebuilt my own portfolio more times than I can count, and every rebuild taught me something the last version got wrong. Most developer portfolios fail for the same handful of reasons — and none of them are &quot;not enough animations&quot; or &quot;not a fancy enough design.&quot;&lt;/p&gt;
&lt;p&gt;This article covers what actually matters, based on what I've learned building my own portfolio and two client portfolio sites.&lt;/p&gt;
&lt;h2 id=&quot;what-a-portfolio-is-actually-for&quot;&gt;What a Portfolio Is Actually For&lt;/h2&gt;
&lt;p&gt;A portfolio has one job: convince someone (a client or a hiring manager) that you can solve their problem. It's not a design showcase for its own sake — every section should answer the visitor's unspoken question, &quot;can this person help me?&quot;&lt;/p&gt;
&lt;h2 id=&quot;the-sections-that-actually-matter&quot;&gt;The Sections That Actually Matter&lt;/h2&gt;
&lt;h3 id=&quot;1-a-clear-headline-not-just-your-name-&quot;&gt;1. A Clear Headline (Not Just Your Name)&lt;/h3&gt;
&lt;p&gt;Weak: &quot;Muhammad Farhan&quot;&lt;br&gt;
Better: &quot;Frontend Developer building fast, clean websites with React &amp;amp; Tailwind CSS&quot;&lt;/p&gt;
&lt;p&gt;The second version tells a visitor exactly what you do within two seconds — no scrolling required.&lt;/p&gt;
&lt;h3 id=&quot;2-3-5-real-projects-quality-over-quantity-&quot;&gt;2. 3-5 Real Projects (Quality Over Quantity)&lt;/h3&gt;
&lt;p&gt;A portfolio with 3 well-explained projects beats one with 10 half-finished ones. For each project, include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A live link (not just a GitHub repo — most non-developers won't clone your code)&lt;/li&gt;
&lt;li&gt;A short description of the problem it solves&lt;/li&gt;
&lt;li&gt;Your specific role and the tech stack used&lt;/li&gt;
&lt;li&gt;1-2 sentences on a challenge you solved&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Example:
&quot;UX Gazette — A blog platform built for a real client using WordPress.
Customized the theme, set up categories and SEO structure, and optimized
page speed from a 60 to a 92 Lighthouse score.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That last sentence — a specific, measurable outcome — is worth more than any amount of visual polish.&lt;/p&gt;
&lt;h2 id=&quot;3-about-section-keep-it-short-and-human-&quot;&gt;3. About Section (Keep It Short and Human)&lt;/h2&gt;
&lt;p&gt;Skip the generic &quot;passionate developer who loves clean code&quot; line — everyone writes that. Say something specific: how you started, what you're currently learning, what kind of projects you enjoy.&lt;/p&gt;
&lt;h2 id=&quot;4-clear-contact-options&quot;&gt;4. Clear Contact Options&lt;/h2&gt;
&lt;p&gt;Don't make people hunt for how to reach you. Email, and at minimum one social/professional link (GitHub, LinkedIn), visible without scrolling to the very bottom.&lt;/p&gt;
&lt;h2 id=&quot;what-to-leave-out&quot;&gt;What to Leave Out&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A skills section with progress bars. &quot;HTML — 90%&quot; means nothing measurable — show skill through projects instead, not arbitrary percentages.&lt;/li&gt;
&lt;li&gt;Every single project you've ever built. Tutorial clones and unfinished experiments dilute your best work. Curate ruthlessly.&lt;/li&gt;
&lt;li&gt;Overly complex animations that slow load time. A portfolio that takes 6 seconds to load is actively working against you, no matter how good it looks once it finally does.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;technical-details-that-quietly-matter&quot;&gt;Technical Details That Quietly Matter&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Mobile responsiveness. A huge percentage of visitors, including recruiters, will open your link on their phone first. If it breaks there, that's often the entire impression formed.&lt;/li&gt;
&lt;li&gt;Fast load time. Run it through Lighthouse (see Article 1). Aim for 90+ on performance.&lt;/li&gt;
&lt;li&gt;Working links. Sounds obvious, but broken project links are one of the most common portfolio mistakes I've seen — test every single one before sharing.&lt;/li&gt;
&lt;li&gt;A resume/CV download link, if you're job hunting alongside freelancing.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;real-example-my-own-approach&quot;&gt;Real Example: My Own Approach&lt;/h2&gt;
&lt;p&gt;My portfolio &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/strong&gt; follows exactly this structure: a clear one-line headline about React + Tailwind, a curated project section instead of everything I've built, and direct contact info without needing to scroll far. It's not the most visually elaborate portfolio out there — but it's fast, clear, and gets straight to the point.&lt;/p&gt;
&lt;h2 id=&quot;common-beginner-mistakes-1&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Launching a portfolio, then never updating it. Add your best new project as soon as it's live — an outdated portfolio signals inactivity.&lt;/li&gt;
&lt;li&gt;No live demo links. A GitHub repo alone asks too much of a busy visitor. Deploy everything (see Article 10) and link the live version.&lt;/li&gt;
&lt;li&gt;Copying a template without understanding it. If someone asks about your portfolio's code in an interview and you can't explain a decision, that's a red flag they'll notice.&lt;/li&gt;
&lt;li&gt;Burying your best project. Lead with your strongest, most relevant work — not chronologically, but by impact.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts-2&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;A great portfolio isn't the flashiest one — it's the clearest one. Someone should be able to land on your site, understand what you do, see proof you can do it, and know how to contact you, all within about 30 seconds. Everything else is secondary.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23006/how-to-build-a-portfolio-website-that-actually-gets-you-hired</guid>
<pubDate>Fri, 21 Aug 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>Why Do AI-Generated Websites All Look the Same?</title>
<link>https://coderlegion.com/24598/why-do-ai-generated-websites-all-look-the-same</link>
<description>&lt;p&gt;Have you noticed something strange lately?&lt;/p&gt;
&lt;p&gt;You ask AI to build a modern website.&lt;/p&gt;
&lt;p&gt;And suddenly, your website looks like hundreds of other AI-generated websites.&lt;/p&gt;
&lt;p&gt;Blue or purple gradient.&lt;/p&gt;
&lt;p&gt;Big hero section.&lt;/p&gt;
&lt;p&gt;Rounded cards.&lt;/p&gt;
&lt;p&gt;Glassmorphism.&lt;/p&gt;
&lt;p&gt;Huge headline.&lt;/p&gt;
&lt;p&gt;A glowing CTA button.&lt;/p&gt;
&lt;p&gt;Three feature cards.&lt;/p&gt;
&lt;p&gt;And some random abstract 3D shapes in the background. 😅&lt;/p&gt;
&lt;p&gt;Then you try another AI tool.&lt;/p&gt;
&lt;p&gt;Different prompt.&lt;/p&gt;
&lt;p&gt;Different project.&lt;/p&gt;
&lt;p&gt;Same design.&lt;/p&gt;
&lt;p&gt;So...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why does this happen?&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-ai-is-getting-better-at-coding-but-something-is-missing&quot;&gt;🤖 AI Is Getting Better at Coding, But Something Is Missing&lt;/h3&gt;
&lt;p&gt;AI can now generate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React applications&lt;/li&gt;
&lt;li&gt;Next.js websites&lt;/li&gt;
&lt;li&gt;Dashboards&lt;/li&gt;
&lt;li&gt;Landing pages&lt;/li&gt;
&lt;li&gt;Mobile interfaces&lt;/li&gt;
&lt;li&gt;Complete frontend systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It can write thousands of lines of code in minutes.&lt;/p&gt;
&lt;p&gt;But there's a difference between:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building a website&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Designing a unique product experience.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;AI is extremely good at the first one.&lt;/p&gt;
&lt;p&gt;The second one still needs human judgment.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-why-does-everything-become-blue-and-purple-&quot;&gt;🎨 Why Does Everything Become Blue and Purple?&lt;/h3&gt;
&lt;p&gt;Let's say you ask:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Create a modern, professional SaaS website.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What does &quot;modern&quot; actually mean?&lt;/p&gt;
&lt;p&gt;AI has to make a decision.&lt;/p&gt;
&lt;p&gt;So it looks at patterns that commonly appear in modern digital products.&lt;/p&gt;
&lt;p&gt;And those patterns often include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Blue&lt;/li&gt;
&lt;li&gt;Purple&lt;/li&gt;
&lt;li&gt;Gradients&lt;/li&gt;
&lt;li&gt;Dark backgrounds&lt;/li&gt;
&lt;li&gt;Rounded corners&lt;/li&gt;
&lt;li&gt;Minimal typography&lt;/li&gt;
&lt;li&gt;Glass effects&lt;/li&gt;
&lt;li&gt;Large hero sections&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These aren't necessarily bad design choices.&lt;/p&gt;
&lt;p&gt;They're simply &lt;strong&gt;safe choices&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;AI knows these patterns usually look acceptable.&lt;/p&gt;
&lt;p&gt;So it uses them again.&lt;/p&gt;
&lt;p&gt;And again.&lt;/p&gt;
&lt;p&gt;And again.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-ai-loves-familiar-patterns&quot;&gt;🧠 AI Loves Familiar Patterns&lt;/h3&gt;
&lt;p&gt;This is probably the biggest reason.&lt;/p&gt;
&lt;p&gt;AI learns from enormous amounts of existing information.&lt;/p&gt;
&lt;p&gt;That includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Websites&lt;/li&gt;
&lt;li&gt;Open-source projects&lt;/li&gt;
&lt;li&gt;Design systems&lt;/li&gt;
&lt;li&gt;UI libraries&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Product pages&lt;/li&gt;
&lt;li&gt;Code repositories&lt;/li&gt;
&lt;li&gt;Public design examples&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when you ask for a website, AI doesn't magically invent an entirely new visual language.&lt;/p&gt;
&lt;p&gt;It generates something based on patterns it has learned.&lt;/p&gt;
&lt;p&gt;It's basically saying:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;I've seen thousands of websites like this. This combination usually works.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And honestly...&lt;/p&gt;
&lt;p&gt;It's often right.&lt;/p&gt;
&lt;p&gt;That's why the result looks good.&lt;/p&gt;
&lt;p&gt;But also familiar.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-the-prompt-makes-a-huge-difference&quot;&gt;🧩 The Prompt Makes a Huge Difference&lt;/h3&gt;
&lt;p&gt;Here's where developers sometimes make the problem worse.&lt;/p&gt;
&lt;p&gt;Imagine asking:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Build a modern landing page for my AI startup.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You'll probably get a very predictable result.&lt;/p&gt;
&lt;p&gt;Now compare that with:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Build a website for a local blood donation platform. The design should feel trustworthy, community-focused, warm, and human. Avoid SaaS-style gradients, glassmorphism, excessive rounded cards, and generic AI illustrations.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now AI has more direction.&lt;/p&gt;
&lt;p&gt;You're not just asking for a website.&lt;/p&gt;
&lt;p&gt;You're giving it a &lt;strong&gt;design identity&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-modern-is-not-a-design-system&quot;&gt;🚫 &quot;Modern&quot; Is Not a Design System&lt;/h3&gt;
&lt;p&gt;This is something worth remembering.&lt;/p&gt;
&lt;p&gt;Words like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modern&lt;/li&gt;
&lt;li&gt;Clean&lt;/li&gt;
&lt;li&gt;Professional&lt;/li&gt;
&lt;li&gt;Premium&lt;/li&gt;
&lt;li&gt;Minimal&lt;/li&gt;
&lt;li&gt;Beautiful&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;are extremely vague.&lt;/p&gt;
&lt;p&gt;Two designers can interpret &quot;modern&quot; completely differently.&lt;/p&gt;
&lt;p&gt;AI has to guess what you mean.&lt;/p&gt;
&lt;p&gt;And when AI guesses...&lt;/p&gt;
&lt;p&gt;It usually chooses the most common interpretation.&lt;/p&gt;
&lt;p&gt;That's where similarity starts.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-developers-also-have-a-role&quot;&gt;👨💻 Developers Also Have a Role&lt;/h3&gt;
&lt;p&gt;It's easy to blame AI.&lt;/p&gt;
&lt;p&gt;But developers are part of the problem too.&lt;/p&gt;
&lt;p&gt;We often say:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Make it look like a modern SaaS website.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then complain:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Why does AI-generated UI look generic?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;😂&lt;/p&gt;
&lt;p&gt;What did we expect?&lt;/p&gt;
&lt;p&gt;If you give AI a generic instruction, you'll probably get a generic design.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-give-ai-product-context&quot;&gt;🎯 Give AI Product Context&lt;/h3&gt;
&lt;p&gt;Instead of only telling AI &lt;strong&gt;what to build&lt;/strong&gt;, tell it &lt;strong&gt;who it's for&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;h4 id=&quot;don-t-say-&quot;&gt;Don't say:&lt;/h4&gt;
&lt;blockquote&gt;&lt;p&gt;Build a job portal.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;say-&quot;&gt;Say:&lt;/h4&gt;
&lt;blockquote&gt;&lt;p&gt;Build a job portal for fresh graduates who are applying for their first job. The interface should feel encouraging and simple, reduce anxiety, make job information easy to scan, and prioritize mobile users.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now AI has something meaningful to work with.&lt;/p&gt;
&lt;p&gt;It can make better design decisions.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-tell-ai-what-not-to-do&quot;&gt;🎨 Tell AI What NOT to Do&lt;/h3&gt;
&lt;p&gt;This is surprisingly powerful.&lt;/p&gt;
&lt;p&gt;You can tell AI:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Don't use purple gradients.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;Don't use glassmorphism.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;Don't use generic 3D illustrations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;Don't use three identical feature cards.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;Don't use oversized hero sections.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;Don't make every component rounded.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;These constraints force AI away from its default patterns.&lt;/p&gt;
&lt;p&gt;Sometimes &lt;strong&gt;negative instructions create more originality than adding more instructions.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-human-taste-still-matters&quot;&gt;🧠 Human Taste Still Matters&lt;/h3&gt;
&lt;p&gt;AI can generate 20 different designs.&lt;/p&gt;
&lt;p&gt;But someone still needs to ask:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Which one actually fits the product?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That's where humans matter.&lt;/p&gt;
&lt;p&gt;A good designer or developer understands things AI may not know automatically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Brand personality&lt;/li&gt;
&lt;li&gt;Target audience&lt;/li&gt;
&lt;li&gt;Cultural context&lt;/li&gt;
&lt;li&gt;User emotions&lt;/li&gt;
&lt;li&gt;Business goals&lt;/li&gt;
&lt;li&gt;Product positioning&lt;/li&gt;
&lt;li&gt;What competitors are doing&lt;/li&gt;
&lt;li&gt;What should feel different&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can generate possibilities.&lt;/p&gt;
&lt;p&gt;Humans decide what feels right.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-ai-isn-t-making-design-worse&quot;&gt;🚀 AI Isn't Making Design Worse&lt;/h3&gt;
&lt;p&gt;This is important.&lt;/p&gt;
&lt;p&gt;The problem isn't:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;AI-generated design is bad.&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The real problem is:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;AI-generated design is becoming predictable.&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And there's a big difference.&lt;/p&gt;
&lt;p&gt;AI gives developers an incredible starting point.&lt;/p&gt;
&lt;p&gt;You can build a working interface in minutes instead of days.&lt;/p&gt;
&lt;p&gt;That's huge.&lt;/p&gt;
&lt;p&gt;But if you simply accept the first design AI gives you...&lt;/p&gt;
&lt;p&gt;Your product may look like every other AI-built product.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-the-future-might-be-different&quot;&gt;🔥 The Future Might Be Different&lt;/h3&gt;
&lt;p&gt;I think we're going to see a shift.&lt;/p&gt;
&lt;p&gt;Right now, people are excited about:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;AI can build my website.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Soon, the more interesting question will be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;&quot;Can AI understand my product well enough to design something truly unique?&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That's a much harder problem.&lt;/p&gt;
&lt;p&gt;Because unique design isn't just about colors and fonts.&lt;/p&gt;
&lt;p&gt;It's about understanding &lt;strong&gt;context, users, emotions, and purpose.&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-the-real-skill-for-developers&quot;&gt;💡 The Real Skill for Developers&lt;/h3&gt;
&lt;p&gt;AI is making implementation cheaper.&lt;/p&gt;
&lt;p&gt;You don't need to spend hours creating every button or card from scratch.&lt;/p&gt;
&lt;p&gt;But that makes another skill more valuable:&lt;/p&gt;
&lt;h4 id=&quot;design-judgment-&quot;&gt;&lt;strong&gt;Design judgment.&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What to keep&lt;/li&gt;
&lt;li&gt;What to remove&lt;/li&gt;
&lt;li&gt;What feels generic&lt;/li&gt;
&lt;li&gt;What fits the brand&lt;/li&gt;
&lt;li&gt;What improves usability&lt;/li&gt;
&lt;li&gt;What makes the product memorable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That's becoming increasingly important.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;-final-thought&quot;&gt;🎯 Final Thought&lt;/h2&gt;
&lt;p&gt;AI can build your website.&lt;/p&gt;
&lt;p&gt;AI can choose your colors.&lt;/p&gt;
&lt;p&gt;AI can generate your components.&lt;/p&gt;
&lt;p&gt;AI can even create the entire frontend.&lt;/p&gt;
&lt;p&gt;But if you don't give it a clear identity...&lt;/p&gt;
&lt;p&gt;It will probably give you something that already exists in a thousand different forms.&lt;/p&gt;
&lt;p&gt;So the next time AI gives you another beautiful purple gradient with rounded cards...&lt;/p&gt;
&lt;p&gt;Don't immediately accept it. 😄&lt;/p&gt;
&lt;p&gt;Ask yourself:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;Does this actually represent my product, or does it just look like an AI-generated website?&quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Because in the age of AI...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Building a website is becoming easier.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Making it feel different is becoming harder.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;ai-webdesign-aidevelopment-frontenddevelopment-uiux-softwareengineering-webdevelopment-generativeai-developers-artificialintelligence&quot;&gt;AI #WebDesign #AIDevelopment #FrontendDevelopment #UIUX #SoftwareEngineering #WebDevelopment #GenerativeAI #Developers #ArtificialIntelligence&lt;/h2&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24598/why-do-ai-generated-websites-all-look-the-same</guid>
<pubDate>Thu, 13 Aug 2026 17:42:07 +0000</pubDate>
</item>
<item>
<title>CSS Animations for Beginners: Transitions, Keyframes &amp; Transforms</title>
<link>https://coderlegion.com/23001/css-animations-for-beginners-transitions-keyframes-transforms</link>
<description>&lt;h2 id=&quot;introduction-3&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;CSS animations were the thing that made me actually enjoy frontend development. Building a static layout is satisfying, but the moment something moves smoothly on hover or fades in on load, a project suddenly feels alive.&lt;/p&gt;
&lt;p&gt;The good news: you only need three concepts to cover almost every animation you'll want to build — transitions, transforms, and keyframes. Let's go through all three.&lt;/p&gt;
&lt;h2 id=&quot;1-transitions-smoothing-out-state-changes&quot;&gt;1. Transitions — Smoothing Out State Changes&lt;/h2&gt;
&lt;p&gt;A transition smooths out a property change between two states (like normal and hover).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.button {
  background-color: #3b82f6;
  transition: background-color 0.3s ease;
}

.button:hover {
  background-color: #2563eb;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Without &lt;strong&gt;transition&lt;/strong&gt;, the color change would be instant. With it, the color smoothly shifts over 0.3 seconds.&lt;/p&gt;
&lt;p&gt;Syntax breakdown: &lt;strong&gt;transition: [property] [duration] [easing];&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In Tailwind:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button class=&quot;bg-blue-500 hover:bg-blue-600 transition duration-300&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;2-transform-moving-scaling-rotating&quot;&gt;2. Transform — Moving, Scaling, Rotating&lt;/h2&gt;
&lt;p&gt;transform changes an element's position, size, or rotation without affecting the layout of surrounding elements.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.card {
  transition: transform 0.3s ease;
}

.card:hover {
  transform: translateY(-8px) scale(1.02);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This lifts a card slightly and grows it a tiny bit on hover — a very common effect on portfolio sites and product cards.&lt;/p&gt;
&lt;h2 id=&quot;common-transform-values-&quot;&gt;Common transform values:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;translateY(-8px)&lt;/strong&gt; — moves up&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;scale(1.05)&lt;/strong&gt; — grows by 5%&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rotate(5deg)&lt;/strong&gt; — rotates slightly&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;translateX(20px)&lt;/strong&gt; — moves right&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;In Tailwind:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;transition hover:-translate-y-2 hover:scale-105&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;3-keyframes-multi-step-animations&quot;&gt;3. Keyframes — Multi-Step Animations&lt;/h2&gt;
&lt;p&gt;Transitions handle two states. &lt;strong&gt;@keyframes&lt;/strong&gt; handles animations with multiple steps, or ones that run automatically without needing a trigger like &lt;strong&gt;:hover&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero-title {
  animation: fadeInUp 0.8s ease-out;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes an element fade in while sliding up slightly — a very common &quot;page load&quot; effect.&lt;/p&gt;
&lt;p&gt;You can also define multiple steps with percentages:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}

.notification-dot {
  animation: pulse 2s infinite;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a continuous pulsing effect, useful for notification badges or &quot;live&quot; indicators.&lt;/p&gt;
&lt;h2 id=&quot;putting-it-together-a-real-example&quot;&gt;Putting It Together: A Real Example&lt;/h2&gt;
&lt;p&gt;Here's a button with a hover lift, a smooth color transition, and a subtle entrance animation on page load:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.cta-button {
  background-color: #3b82f6;
  transition: all 0.3s ease;
  animation: fadeIn 0.6s ease-in;
}

.cta-button:hover {
  background-color: #2563eb;
  transform: translateY(-4px);
  box-shadow: 0 10px 20px rgba(59, 130, 246, 0.3);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is genuinely how most polished-feeling buttons on real websites are built — nothing exotic, just transitions and transforms combined thoughtfully.&lt;/p&gt;
&lt;h2 id=&quot;common-beginner-mistakes-2&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Animating too many properties at once. Subtlety wins — one or two properties changing smoothly looks more professional than five things moving at once.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;all&lt;/strong&gt; in transitions carelessly. &lt;strong&gt;transition: all 0.3s&lt;/strong&gt; works, but is slightly less performant than specifying exact properties like &lt;strong&gt;transition: transform 0.3s, background-color 0.3s&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Animating &lt;strong&gt;width/height/top/left&lt;/strong&gt; instead of &lt;strong&gt;transform&lt;/strong&gt;. These properties trigger layout recalculation and can feel janky. &lt;strong&gt;transform&lt;/strong&gt; and &lt;strong&gt;opacity&lt;/strong&gt; are GPU-accelerated and much smoother.&lt;/li&gt;
&lt;li&gt;Overusing &lt;strong&gt;infinite&lt;/strong&gt; animations. A pulsing badge is fine. A constantly bouncing hero heading gets annoying fast — use continuous animation sparingly.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts-3&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;You don't need a JavaScript animation library for most of what makes a website feel polished — smooth hovers, subtle lifts, and clean entrance animations are all achievable with plain CSS. Start by adding a transition to every hover state in your next project and see how much more &quot;finished&quot; it instantly feels.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23001/css-animations-for-beginners-transitions-keyframes-transforms</guid>
<pubDate>Tue, 11 Aug 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>How to Build Your First React Component (Step-by-Step)</title>
<link>https://coderlegion.com/23000/how-to-build-your-first-react-component-step-by-step</link>
<description>&lt;h2 id=&quot;introduction-4&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Your first React component doesn't need to be complicated. In fact, the biggest mistake beginners make is trying to build something too ambitious right away and getting stuck on concepts they haven't learned yet.&lt;/p&gt;
&lt;p&gt;We're building something practical and genuinely useful: a reusable Testimonial Card component — the kind of thing that shows up in real portfolios and client projects constantly.&lt;/p&gt;
&lt;h2 id=&quot;step-1-understand-what-a-component-actually-is&quot;&gt;Step 1: Understand What a Component Actually Is&lt;/h2&gt;
&lt;p&gt;A React component is just a JavaScript function that returns some JSX (HTML-like syntax). That's the whole concept.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function Greeting() {
  return &amp;lt;h1&amp;gt;Hello, world!&amp;lt;/h1&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You use it like an HTML tag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;Greeting /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;step-2-build-the-static-version-first&quot;&gt;Step 2: Build the Static Version First&lt;/h2&gt;
&lt;p&gt;Before adding any dynamic data, get the layout right with hardcoded content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function TestimonialCard() {
  return (
    &amp;lt;div className=&quot;bg-slate-800 rounded-2xl p-6 max-w-sm shadow-lg&quot;&amp;gt;
      &amp;lt;p className=&quot;text-slate-300 mb-4&quot;&amp;gt;
        &quot;This developer delivered exactly what we needed, on time and with great communication.&quot;
      &amp;lt;/p&amp;gt;
      &amp;lt;div className=&quot;flex items-center gap-3&quot;&amp;gt;
        &amp;lt;div className=&quot;w-10 h-10 rounded-full bg-blue-500&quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;p className=&quot;text-white font-semibold&quot;&amp;gt;Sarah Ahmed&amp;lt;/p&amp;gt;
          &amp;lt;p className=&quot;text-slate-400 text-sm&quot;&amp;gt;Product Manager&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice: no state, no props, nothing dynamic. Just structure and styling. This is genuinely how you should approach every new component — get the static layout right first.&lt;/p&gt;
&lt;h2 id=&quot;step-3-make-it-reusable-with-props&quot;&gt;Step 3: Make It Reusable with Props&lt;/h2&gt;
&lt;p&gt;Right now this card only shows one testimonial. Props let you reuse the same component with different data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function TestimonialCard({ quote, name, role }) {
  return (
    &amp;lt;div className=&quot;bg-slate-800 rounded-2xl p-6 max-w-sm shadow-lg&quot;&amp;gt;
      &amp;lt;p className=&quot;text-slate-300 mb-4&quot;&amp;gt;&quot;{quote}&quot;&amp;lt;/p&amp;gt;
      &amp;lt;div className=&quot;flex items-center gap-3&quot;&amp;gt;
        &amp;lt;div className=&quot;w-10 h-10 rounded-full bg-blue-500&quot;&amp;gt;&amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;p className=&quot;text-white font-semibold&quot;&amp;gt;{name}&amp;lt;/p&amp;gt;
          &amp;lt;p className=&quot;text-slate-400 text-sm&quot;&amp;gt;{role}&amp;lt;/p&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you use it like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;TestimonialCard
  quote=&quot;This developer delivered exactly what we needed, on time.&quot;
  name=&quot;Sarah Ahmed&quot;
  role=&quot;Product Manager&quot;
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;{ quote, name, role }&lt;/strong&gt; is destructuring the props object — same as writing &lt;strong&gt;props.quote, props.name, props.role&lt;/strong&gt;, just cleaner.&lt;/p&gt;
&lt;h2 id=&quot;step-4-render-a-list-of-them&quot;&gt;Step 4: Render a List of Them&lt;/h2&gt;
&lt;p&gt;In a real project, you'd map over an array of testimonial data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const testimonials = [
  { quote: &quot;Great work, fast turnaround.&quot;, name: &quot;Ali Raza&quot;, role: &quot;Founder&quot; },
  { quote: &quot;Clean code and clear communication.&quot;, name: &quot;Sarah Ahmed&quot;, role: &quot;PM&quot; },
  { quote: &quot;Would hire again without hesitation.&quot;, name: &quot;James Lee&quot;, role: &quot;CTO&quot; },
];

function TestimonialGrid() {
  return (
    &amp;lt;div className=&quot;grid md:grid-cols-3 gap-6 p-6&quot;&amp;gt;
      {testimonials.map((item, index) =&amp;gt; (
        &amp;lt;TestimonialCard key={index} {...item} /&amp;gt;
      ))}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;{...item}&lt;/strong&gt; spreads the object properties as individual props automatically — a common React pattern once you're comfortable with the basics.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; the key &lt;strong&gt;prop&lt;/strong&gt; is required whenever you render a list. React uses it to track which items changed. In a real project, use a unique ID from your data rather than the array index if possible.&lt;/p&gt;
&lt;h2 id=&quot;step-5-add-a-bit-of-interactivity-optional-&quot;&gt;Step 5: Add a Bit of Interactivity (Optional)&lt;/h2&gt;
&lt;p&gt;Want to show a &quot;Read more&quot; toggle for long quotes? That's where &lt;strong&gt;useState&lt;/strong&gt; comes in — covered in detail in Article 5, but here's the quick version:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function TestimonialCard({ quote, name, role }) {
  const [expanded, setExpanded] = useState(false);

  return (
    &amp;lt;div className=&quot;bg-slate-800 rounded-2xl p-6 max-w-sm shadow-lg&quot;&amp;gt;
      &amp;lt;p className={`text-slate-300 mb-4 ${!expanded &amp;amp;&amp;amp; &quot;line-clamp-2&quot;}`}&amp;gt;
        &quot;{quote}&quot;
      &amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setExpanded(!expanded)} className=&quot;text-blue-400 text-sm mb-4&quot;&amp;gt;
        {expanded ? &quot;Show less&quot; : &quot;Read more&quot;}
      &amp;lt;/button&amp;gt;
      {/* rest of the card */}
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;common-beginner-mistakes-3&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Trying to add state and interactivity before the static layout is right. Get the structure and styling working first — add logic after.&lt;/li&gt;
&lt;li&gt;Forgetting the &lt;strong&gt;key&lt;/strong&gt; prop when rendering lists. React will warn you in the console — don't ignore that warning.&lt;/li&gt;
&lt;li&gt;Not destructuring props. Writing &lt;strong&gt;props.quote&lt;/strong&gt; everywhere instead of destructuring is more typing and harder to read.&lt;/li&gt;
&lt;li&gt;Building one giant component instead of small, focused ones. If a component is doing three different jobs, split it into three components.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts-4&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Building your first real component is less about React &quot;magic&quot; and more about breaking a UI down into small, reusable pieces — static first, then props, then interactivity if needed. Rebuild this same pattern (static → props → list → interactivity) for your next few components and it'll start feeling automatic.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Muhammad Farhan is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23000/how-to-build-your-first-react-component-step-by-step</guid>
<pubDate>Fri, 07 Aug 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>Eight Weeks From Classroom to Production: My Software Engineering Internship Journey</title>
<link>https://coderlegion.com/24085/eight-weeks-from-classroom-to-production-my-software-engineering-internship-journey</link>
<description>&lt;h3 id=&quot;what-i-learned-building-a-real-talent-funnel-from-srs-and-figma-to-qa-handover-and-closing-without-a-perfect-ending-&quot;&gt;What I learned building a real talent funnel from SRS and Figma to QA, handover, and closing without a perfect ending.&lt;/h3&gt;
&lt;p&gt;Hey everyone,&lt;/p&gt;
&lt;p&gt;If you followed my weekly Hashnode series, you already know the short version: eight weeks, one real product, a lot of shipping, and a quieter finale than I expected.&lt;/p&gt;
&lt;p&gt;This post is the longer reflection on the whole arc in one place.&lt;/p&gt;
&lt;p&gt;Series link: &lt;a rel=&quot;nofollow&quot; href=&quot;https://shakiran.hashnode.dev/series/my-software-engineering-internship&quot;&gt;My Software Engineering Internship Journey&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;how-it-started&quot;&gt;How it started&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Week 1&lt;/strong&gt; did not feel like “writing production code on day one.” It felt like orientation into a different kind of seriousness.&lt;/p&gt;
&lt;p&gt;We were not building toys. We were joining a live talent funnel product, the &lt;strong&gt;Talent Funnel&lt;/strong&gt;, where candidates move through discovery, onboarding, assessments, and interviews, while admins need tools they can trust.&lt;/p&gt;
&lt;p&gt;Before the flashy UI work, there was the quieter foundation work: requirements, diagrams, architecture conversations, and learning how classroom theory behaves once real stakeholders and real timelines enter the room.&lt;/p&gt;
&lt;p&gt;That first week taught me something I kept rediscovering: industry work is less about knowing everything, and more about becoming useful quickly without breaking what already exists.&lt;/p&gt;
&lt;h3 id=&quot;the-middle-building-for-real-users&quot;&gt;The middle: building for real users&lt;/h3&gt;
&lt;p&gt;Across the middle weeks, the work widened fast.&lt;/p&gt;
&lt;p&gt;We moved through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;requirements and data architecture&lt;/li&gt;
&lt;li&gt;monorepo structure and type-safe environments&lt;/li&gt;
&lt;li&gt;custom auth and onboarding flows&lt;/li&gt;
&lt;li&gt;candidate home hubs, assessment surfaces, and UI states&lt;/li&gt;
&lt;li&gt;landing pages, hierarchy polish, and painful but necessary rework&lt;/li&gt;
&lt;li&gt;admin portals, route hardening, and access control&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some weeks felt like invention. Others felt like correction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Week 5&lt;/strong&gt; especially stuck with me: being right about a UI direction did not always protect the work from being redone. Branch overlap, merge calls, and scope cleanup taught me more than the feature itself. That was uncomfortable. It was also one of the most useful lessons of the internship.&lt;/p&gt;
&lt;p&gt;By &lt;strong&gt;Weeks 6 and 7,&lt;/strong&gt; the focus shifted again from “can we build this?” to “can this survive without scaffolding?” We migrated out of temporary paths, cleaned legacy naming, unified branding, hardened staff access, improved analytics and candidate summaries, and started thinking about handover as part of engineering, not as an afterthought.&lt;/p&gt;
&lt;h3 id=&quot;what-the-work-actually-looked-like&quot;&gt;What the work actually looked like&lt;/h3&gt;
&lt;p&gt;If I had to name the through-line of my internship, it would be consistency.&lt;/p&gt;
&lt;p&gt;Not just visual consistency. Product consistency.&lt;/p&gt;
&lt;p&gt;Making routes make sense. Making emails point to real places. Making settings and permissions match how staff actually work. Making responsive layouts behave on phones, not only on laptops. Making localization expose every missing string before a user does. Shipping in related batches instead of one giant pile that nobody can review.&lt;/p&gt;
&lt;p&gt;Those details do not always look impressive in a weekly update. They are what make a product feel intentional.&lt;/p&gt;
&lt;h3 id=&quot;how-it-ended&quot;&gt;How it ended&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Week 8&lt;/strong&gt; was the finale: QA, test documentation, and project handover.&lt;/p&gt;
&lt;p&gt;As a team, we closed the project. We did not get full client feedback before we wrapped. That is the honest part. Timelines move. Stakeholders are busy. Final reviews do not always land when you hope they will.&lt;/p&gt;
&lt;p&gt;Even so, we know they appreciated the work. That appreciation showed up in the collaboration, the trust, and the way the product kept moving forward with us. A long written review would have been nice. Knowing the work mattered still counts.&lt;/p&gt;
&lt;p&gt;Closing without a cinematic ending taught me something I did not expect to learn so clearly:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Finishing well is not the same as finishing loudly.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sometimes a good ending looks like regression checks, documented test cases, known issues written down honestly, and a handover package that lets the next engineers continue without reconstructing the story from commit messages alone.&lt;/p&gt;
&lt;h3 id=&quot;what-i-take-with-me&quot;&gt;What I take with me&lt;/h3&gt;
&lt;p&gt;I leave with more than a portfolio of screens.&lt;/p&gt;
&lt;p&gt;I leave with better instincts around:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;shipping in related batches&lt;/li&gt;
&lt;li&gt;treating documentation as part of delivery&lt;/li&gt;
&lt;li&gt;seeing responsive UI, localization, and access control as product integrity, not polish&lt;/li&gt;
&lt;li&gt;treating merge conflicts, CI surprises, and overlapping branches as the work itself&lt;/li&gt;
&lt;li&gt;measuring progress not only by what I can build, but by whether someone else can continue after me&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Somewhere between Week 1 and Week 8, I stopped thinking of an internship as a sequence of tasks. I started seeing it as practice in becoming leaveable, leaving systems, decisions, and context in a state where the team can keep going.&lt;/p&gt;
&lt;h3 id=&quot;if-you-are-starting-your-own-internship&quot;&gt;If you are starting your own internship&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;A few things I would tell my Week 1 self:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ask for context early. Why a decision exists matters as much as how to implement it.&lt;/li&gt;
&lt;li&gt;Expect rework. Being right once does not freeze the product forever.&lt;/li&gt;
&lt;li&gt;Write things down while they are still fresh. Future you and future teammates need that.&lt;/li&gt;
&lt;li&gt;Care about the unglamorous paths: empty states, mobile, permissions,&lt;br&gt;
broken links.&lt;/li&gt;
&lt;li&gt;Learn to close. Shipping is not only starting features. It is also QA, honesty about risk, and handover.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;closing&quot;&gt;Closing&lt;/h3&gt;
&lt;p&gt;Internships end. Products keep going.&lt;/p&gt;
&lt;p&gt;I am proud of what we built, proud of how we closed, and grateful for the team, mentors, and trust that made the experience real.&lt;/p&gt;
&lt;p&gt;If you want the week-by-week story, start here:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://shakiran.hashnode.dev/series/my-software-engineering-internship&quot;&gt;My Software Engineering Internship Journey&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Thanks for reading.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24085/eight-weeks-from-classroom-to-production-my-software-engineering-internship-journey</guid>
<pubDate>Tue, 04 Aug 2026 10:35:41 +0000</pubDate>
</item>
<item>
<title>AI Made Code Review the Bottleneck. Attach the UI to Your PR</title>
<link>https://coderlegion.com/24024/ai-made-code-review-the-bottleneck-attach-the-ui-to-your-pr</link>
<description>&lt;p&gt;You open a frontend pull request. The diff is 400 lines, an AI agent wrote most of it, and the description says &quot;adds the checkout flow&quot;. CI is green.&lt;/p&gt;
&lt;p&gt;You read the diff. It looks reasonable. You still have no idea what the UI actually does.&lt;/p&gt;
&lt;p&gt;So you do what you always do. You pull the branch, install dependencies, start the dev server, and click through the flow yourself.&lt;/p&gt;
&lt;p&gt;Ten minutes later you approve the PR.&lt;/p&gt;
&lt;p&gt;That ten minutes is the bottleneck now.&lt;/p&gt;
&lt;p&gt;AI made writing code dramatically faster. Reviewing frontend behavior did not.&lt;/p&gt;
&lt;h3 id=&quot;tests-solve-part-of-the-problem&quot;&gt;Tests solve part of the problem&lt;/h3&gt;
&lt;p&gt;Tests already reduce a large part of that uncertainty.&lt;/p&gt;
&lt;p&gt;With &lt;a rel=&quot;nofollow&quot; href=&quot;https://twd.dev/&quot;&gt;twd-js&lt;/a&gt;, they execute inside a real browser, against the real DOM, with the network mocked so runs stay deterministic. A green run means the entire flow actually executed.&lt;/p&gt;
&lt;p&gt;But a green run only tells the reviewer that the assertions passed.&lt;/p&gt;
&lt;p&gt;It does not tell them what the user sees.&lt;/p&gt;
&lt;p&gt;Was the validation message attached to the correct field?&lt;/p&gt;
&lt;p&gt;Did the modal actually close?&lt;/p&gt;
&lt;p&gt;Does the empty state look intentional, or does it look broken?&lt;/p&gt;
&lt;p&gt;Those are exactly the things reviewers still verify manually, and they are difficult to express as assertions alone.&lt;/p&gt;
&lt;h3 id=&quot;put-the-flow-in-the-pull-request&quot;&gt;Put the flow in the pull request&lt;/h3&gt;
&lt;p&gt;Your tests already drive the application through the exact flow under review.&lt;/p&gt;
&lt;p&gt;If reviewers could simply watch that execution, they would not need to pull the branch just to understand the UI.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;twd-cli&lt;/code&gt; can record the run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx twd-cli run --record --test &quot;checkout flow&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That produces:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;twd-artifacts/checkout-flow.mp4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Drop the video directly into the pull request description.&lt;/p&gt;
&lt;h3 id=&quot;the-first-problem-you-ll-hit&quot;&gt;The first problem you'll hit&lt;/h3&gt;
&lt;p&gt;The first time you try this, you discover something unexpected.&lt;/p&gt;
&lt;p&gt;The tests finish in about a second.&lt;/p&gt;
&lt;p&gt;The recording is technically correct.&lt;/p&gt;
&lt;p&gt;It is also almost impossible for a human to follow.&lt;/p&gt;
&lt;h3 id=&quot;slowing-the-video-down-is-the-wrong-fix&quot;&gt;Slowing the video down is the wrong fix&lt;/h3&gt;
&lt;p&gt;The obvious solution is to stretch the recording afterwards.&lt;/p&gt;
&lt;p&gt;A simple ffmpeg filter can do that, but it stretches the same frames across a longer duration. As playback slows down, the effective frame rate drops.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;right&quot;&gt;Speed &lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Duration &lt;/th&gt;&lt;th align=&quot;right&quot;&gt;Effective FPS&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;1x &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;   1.00s &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;           30&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;0.5x &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;   1.90s &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;         15.3&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;right&quot;&gt;0.25x &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;   3.90s &lt;/td&gt;&lt;td align=&quot;right&quot;&gt;          7.7&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;At quarter speed, you're watching an 8 FPS video.&lt;/p&gt;
&lt;p&gt;It also slows every moment equally. The interesting interactions and the idle time both become longer. The result is not easier to understand. It is simply slower.&lt;/p&gt;
&lt;h3 id=&quot;this-is-where-architecture-matters&quot;&gt;This is where architecture matters&lt;/h3&gt;
&lt;p&gt;Most testing tools record a browser that is being driven from the outside.&lt;/p&gt;
&lt;p&gt;The recording is a byproduct of automation, so once execution has finished, post processing is your only option.&lt;/p&gt;
&lt;p&gt;TWD works differently.&lt;/p&gt;
&lt;p&gt;Its commands execute as JavaScript inside the page itself.&lt;/p&gt;
&lt;p&gt;Because TWD owns the command loop, it can control &lt;strong&gt;when commands execute&lt;/strong&gt;, not just how the recording is encoded.&lt;/p&gt;
&lt;p&gt;Instead of stretching frames afterwards, it spaces out execution while the test is running.&lt;/p&gt;
&lt;p&gt;Frames are still captured at full frame rate.&lt;/p&gt;
&lt;p&gt;Pauses happen only after meaningful interactions.&lt;/p&gt;
&lt;p&gt;Typing is paced character by character instead of appearing all at once.&lt;/p&gt;
&lt;p&gt;That produces a recording that feels natural to watch without sacrificing smoothness.&lt;/p&gt;
&lt;p&gt;Which is why recordings are paced by default:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Default: 300ms pause after each command
npx twd-cli run --record --test &quot;checkout flow&quot;

# Better for demos or stakeholder reviews
npx twd-cli run --record --record-pace 500 --test &quot;checkout flow&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In practice, values between &lt;strong&gt;200ms and 500ms&lt;/strong&gt; are usually enough to make interactions comfortable to follow while keeping recordings concise.&lt;/p&gt;
&lt;p&gt;The result is still a smooth 30 FPS video.&lt;/p&gt;
&lt;p&gt;Only the moments that matter become easier to observe.&lt;/p&gt;
&lt;h3 id=&quot;what-the-reviewer-gets&quot;&gt;What the reviewer gets&lt;/h3&gt;
&lt;p&gt;The reviewer watches the actual flow.&lt;/p&gt;
&lt;p&gt;Driven by the actual tests.&lt;/p&gt;
&lt;p&gt;Running against the actual application.&lt;/p&gt;
&lt;p&gt;Not a screen recording someone remembered to make.&lt;/p&gt;
&lt;p&gt;Not a Loom video that becomes outdated after the next commit.&lt;/p&gt;
&lt;p&gt;The recording is regenerated every time the tests run.&lt;/p&gt;
&lt;p&gt;The review changes from:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Does this diff look correct?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;to:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Is this the behavior we actually wanted?&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the question worth a human's attention.&lt;/p&gt;
&lt;h3 id=&quot;the-bottleneck-moved&quot;&gt;The bottleneck moved&lt;/h3&gt;
&lt;p&gt;Every improvement in software development moves the bottleneck somewhere else.&lt;/p&gt;
&lt;p&gt;Today, AI has made writing code significantly faster.&lt;/p&gt;
&lt;p&gt;Frontend review is still largely manual because reviewers need to understand behavior, not just source code.&lt;/p&gt;
&lt;p&gt;A green checkmark confirms that the tests passed.&lt;/p&gt;
&lt;p&gt;It does not show what happened.&lt;/p&gt;
&lt;p&gt;Browser based tests can produce something much more valuable than a success badge.&lt;/p&gt;
&lt;p&gt;They can produce evidence.&lt;/p&gt;
&lt;p&gt;Sometimes, that evidence is a short video that saves every reviewer ten minutes.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npx twd-cli run --record --test &quot;the flow you changed&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your tests already know how to reproduce the feature, your pull request should show it.&lt;/p&gt;
&lt;p&gt;See the &lt;a rel=&quot;nofollow&quot; href=&quot;https://twd.dev/recording&quot;&gt;Recording Runs documentation&lt;/a&gt; for all available options.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/24024/ai-made-code-review-the-bottleneck-attach-the-ui-to-your-pr</guid>
<pubDate>Mon, 03 Aug 2026 07:01:36 +0000</pubDate>
</item>
<item>
<title>A Standard Arithmetic Calculator</title>
<link>https://coderlegion.com/23927/a-standard-arithmetic-calculator</link>
<description>&lt;p&gt;It is simple interface on the surface, but a good exercise in building interactive, state-driven user experiences.&lt;br&gt;
For the UI design I got it from the famous &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.frontendmentor.io&quot;&gt;https://www.frontendmentor.io&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Features include:&lt;br&gt;
🧮 Standard calculator operations&lt;br&gt;
🎨 Three switchable UI themes&lt;br&gt;
📱 Responsive design across screen sizes&lt;br&gt;
⚡ Smooth user interactions with JavaScript&lt;/p&gt;
&lt;p&gt;Projects like this are a reminder that even straightforward applications require thoughtful UI design, clean logic, and attention to user experience.&lt;/p&gt;
&lt;p&gt;I'd love to hear your thoughts or suggestions &lt;/p&gt;
</description>
<category>Launches</category>
<guid isPermaLink="true">https://coderlegion.com/23927/a-standard-arithmetic-calculator</guid>
<pubDate>Sat, 01 Aug 2026 13:03:10 +0000</pubDate>
</item>
<item>
<title>Responsive Design 101: How to Make Any Website Mobile-Friendly</title>
<link>https://coderlegion.com/22995/responsive-design-101-how-to-make-any-website-mobile-friendly</link>
<description>&lt;h2 id=&quot;introduction-5&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The first website I ever built looked great on my laptop and completely broken on my phone. Text overflowing, buttons cut off, images stretched way too big. That's the exact moment &quot;responsive design&quot; stopped being a buzzword and became something I actually had to understand.&lt;/p&gt;
&lt;p&gt;Here's the good news: responsive design isn't complicated once you learn a handful of core habits. This article covers exactly those.&lt;/p&gt;
&lt;h2 id=&quot;mobile-first-start-small-then-grow&quot;&gt;Mobile-First: Start Small, Then Grow&lt;/h2&gt;
&lt;p&gt;The most important mindset shift: design for the smallest screen first, then add complexity as the screen grows — not the other way around.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/* Base styles = mobile */
.container {
  display: flex;
  flex-direction: column;
}

/* Then adjust for larger screens */
@media (min-width: 768px) {
  .container {
    flex-direction: row;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Tailwind, this is built into the framework by default:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;flex flex-col md:flex-row&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No media query needed — flex-col is the mobile default, md:flex-row overrides it on tablets and up.&lt;/p&gt;
&lt;h3 id=&quot;understanding-breakpoints&quot;&gt;Understanding Breakpoints&lt;/h3&gt;
&lt;p&gt;A breakpoint is a screen width where your layout changes. Tailwind's defaults are a solid starting point for almost any project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;(none)&lt;/strong&gt; — Default styles apply to &lt;strong&gt;all screen sizes&lt;/strong&gt; starting from &lt;strong&gt;0px&lt;br&gt;
(Mobile)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sm:&lt;/strong&gt; — Applies styles on screens &lt;strong&gt;640px and wider&lt;/strong&gt; (Large phones).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;md:&lt;/strong&gt; — Applies styles on screens &lt;strong&gt;768px and wider&lt;/strong&gt; (Tablets).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;lg:&lt;/strong&gt; — Applies styles on screens &lt;strong&gt;1024px and wider&lt;/strong&gt; (Laptops).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;xl:&lt;/strong&gt; — Applies styles on screens &lt;strong&gt;1280px and wider&lt;/strong&gt; (Desktops).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You rarely need custom breakpoints — these five cover the vast majority of real devices.&lt;/p&gt;
&lt;h3 id=&quot;flexible-units-over-fixed-pixels&quot;&gt;Flexible Units Over Fixed Pixels&lt;/h3&gt;
&lt;p&gt;Fixed pixel widths break responsive layouts. Use flexible units instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;%&lt;/strong&gt; — relative to the parent container&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rem&lt;/strong&gt; — relative to the root font size (better than px for text)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vw / vh&lt;/strong&gt; — relative to viewport width/height&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;fr&lt;/strong&gt; — flexible fraction, used in CSS Grid&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;/* Breaks on small screens */
.card { width: 400px; }

/* Adapts to any screen */
.card { width: 100%; max-width: 400px; }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That second version is the pattern to remember: set a &lt;strong&gt;max-width&lt;/strong&gt; for large screens, but let it shrink to &lt;strong&gt;100%&lt;/strong&gt; on smaller ones.&lt;/p&gt;
&lt;h3 id=&quot;responsive-images&quot;&gt;Responsive Images&lt;/h3&gt;
&lt;p&gt;Images are the #1 cause of layout breakage for beginners. The fix is almost always this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;img {
  max-width: 100%;
  height: auto;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In Tailwind:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&quot;photo.jpg&quot; class=&quot;max-w-full h-auto&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This ensures an image never overflows its container, regardless of screen size, while keeping its aspect ratio intact.&lt;/p&gt;
&lt;h3 id=&quot;testing-your-responsive-design&quot;&gt;Testing Your Responsive Design&lt;/h3&gt;
&lt;p&gt;Don't just resize your browser window manually — use these instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chrome DevTools Device Mode (Ctrl+Shift+M) — simulates real device sizes, including touch input&lt;/li&gt;
&lt;li&gt;Responsively App — tests multiple device sizes side by side, syncing scroll and clicks (covered in Article 1)&lt;/li&gt;
&lt;li&gt;Actually open the site on your own phone before calling it done — emulators are close, but not perfect&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;common-beginner-mistakes-4&quot;&gt;Common Beginner Mistakes&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Designing desktop-first, then trying to &quot;fix&quot; mobile later. Almost always results in more work and more bugs.&lt;/li&gt;
&lt;li&gt;Fixed-width containers. &lt;strong&gt;width: 1200px&lt;/strong&gt; will always cause horizontal scrolling on smaller screens. Use &lt;strong&gt;max-width&lt;/strong&gt; instead.&lt;/li&gt;
&lt;li&gt;Text that's too small on mobile. 16px is a safe minimum for body text — anything smaller strains readability on phones.&lt;/li&gt;
&lt;li&gt;Forgetting touch targets. Buttons and links need enough padding to be tappable with a thumb — 44px height minimum is the common accessibility guideline.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;final-thoughts-5&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;Responsive design isn't a separate skill you learn once and forget — it's a habit you build into every single component from day one. Start mobile-first, use flexible units, test on real devices, and most layout bugs simply won't happen in the first place.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;em&gt;muhammad-farhan-dev.github.io/muhammadfarhan.dev&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22995/responsive-design-101-how-to-make-any-website-mobile-friendly</guid>
<pubDate>Fri, 31 Jul 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>Understanding React Hooks: useState and useEffect Explained Simply</title>
<link>https://coderlegion.com/22994/understanding-react-hooks-usestate-and-useeffect-explained-simply</link>
<description>&lt;h2 id=&quot;introduction-6&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Hooks confused me for longer than I'd like to admit. Not the syntax — the syntax is simple. What confused me was when to use useEffect versus just writing normal logic in my component.&lt;/p&gt;
&lt;p&gt;If you're at that stage right now, this article is for you. We're keeping this practical — real examples, real mistakes, no theory-heavy explanations of React's internal fiber architecture.&lt;/p&gt;
&lt;h3 id=&quot;usestate-giving-your-component-memory&quot;&gt;useState: Giving Your Component Memory&lt;/h3&gt;
&lt;p&gt;Without state, a component renders once and forgets everything. &lt;strong&gt;useState&lt;/strong&gt; lets a component remember values between renders — and re-render automatically when that value changes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;Count: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increase&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;count&lt;/strong&gt; is the current value. &lt;strong&gt;setCount&lt;/strong&gt; is the function you call to update it. Calling &lt;strong&gt;setCount&lt;/strong&gt; tells React &quot;re-render this component with the new value&quot; — you never update &lt;strong&gt;count&lt;/strong&gt; directly.&lt;/p&gt;
&lt;p&gt;Common Mistake: Updating State Based on Old State&lt;/p&gt;
&lt;p&gt;This looks fine but can cause bugs:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;setCount(count + 1);
setCount(count + 1); // still only adds 1, not 2!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fix it with the function form:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;setCount(prev =&amp;gt; prev + 1);
setCount(prev =&amp;gt; prev + 1); // now correctly adds 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This matters more than it seems — always use the function form when your new state depends on the previous state.&lt;/p&gt;
&lt;h3 id=&quot;useeffect-running-code-at-the-right-time&quot;&gt;useEffect: Running Code at the Right Time&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;useEffect&lt;/strong&gt; lets you run code in response to a component rendering, or a specific value changing — things like fetching data, updating the page title, or setting up an event listener.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() =&amp;gt; {
    fetch(`https://api.example.com/users/${userId}`)
      .then(res =&amp;gt; res.json())
      .then(data =&amp;gt; setUser(data));
  }, [userId]);

  if (!user) return &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;;
  return &amp;lt;h2&amp;gt;{user.name}&amp;lt;/h2&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The array at the end — &lt;strong&gt;[userId]&lt;/strong&gt; — is the dependency array. It tells React &quot;only re-run this effect when &lt;strong&gt;userId&lt;/strong&gt; changes.&quot;&lt;/p&gt;
&lt;p&gt;The Three Dependency Array Patterns&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;useEffect(() =&amp;gt; { /* code */ });          // runs after EVERY render
useEffect(() =&amp;gt; { /* code */ }, []);       // runs ONCE, after the first render
useEffect(() =&amp;gt; { /* code */ }, [userId]); // runs when userId changes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Beginners almost always want one of the last two. An empty array &lt;strong&gt;[]&lt;/strong&gt; is for one-time setup (like fetching initial data). A populated array is for &quot;re-run this when X changes.&quot;&lt;/p&gt;
&lt;h3 id=&quot;cleaning-up-after-effects&quot;&gt;Cleaning Up After Effects&lt;/h3&gt;
&lt;p&gt;Some effects need cleanup — like removing an event listener when the component unmounts:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  const handleResize = () =&amp;gt; console.log(window.innerWidth);
  window.addEventListener('resize', handleResize);

  return () =&amp;gt; {
    window.removeEventListener('resize', handleResize);
  };
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The function you &lt;strong&gt;return&lt;/strong&gt; inside &lt;strong&gt;useEffect&lt;/strong&gt; is the cleanup function. React calls it automatically before the component unmounts, or before the effect runs again.&lt;/p&gt;
&lt;h3 id=&quot;common-beginner-mistakes-5&quot;&gt;Common Beginner Mistakes&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Forgetting the dependency array entirely. This causes the effect to run after every single render, often triggering infinite fetch loops.&lt;/li&gt;
&lt;li&gt;Missing a dependency. If your effect uses a variable from outside it, add it to the array — ESLint's react-hooks/exhaustive-deps rule will warn you about this.&lt;/li&gt;
&lt;li&gt;Putting everything in useEffect. Not all logic needs to live in an effect. If you're just calculating a value from props or state, do it directly in the component body — no hook needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;final-thoughts-6&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;useState&lt;/strong&gt; gives your component memory. &lt;strong&gt;useEffect&lt;/strong&gt; lets it react to changes and the outside world (APIs, timers, event listeners). Once you separate those two jobs clearly in your head, hooks stop feeling mysterious.&lt;/p&gt;
&lt;p&gt;Try rebuilding a small feature — a search box with an API call, for example — using exactly these two hooks. That's usually the exercise that makes it click.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;em&gt;muhammad-farhan-dev.github.io/muhammadfarhan.dev&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22994/understanding-react-hooks-usestate-and-useeffect-explained-simply</guid>
<pubDate>Tue, 28 Jul 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>10 VS Code Extensions Every Frontend Developer Needs</title>
<link>https://coderlegion.com/22992/10-vs-code-extensions-every-frontend-developer-needs</link>
<description>&lt;h2 id=&quot;introduction-7&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I used to install every extension that looked interesting — ended up with 40+ extensions and a VS Code that took 10 seconds just to open. Eventually I stripped it back down to the ones I actually use every single day.&lt;/p&gt;
&lt;p&gt;These 10 are the ones that survived that cleanup. If you're setting up a fresh frontend dev environment, start here.&lt;/p&gt;
&lt;h3 id=&quot;1-eslint&quot;&gt;1. ESLint&lt;/h3&gt;
&lt;p&gt;Catches bugs and enforces consistent code style before you even run your code. If you're working in a team (or want to look like you know what you're doing), this is non-negotiable.&lt;/p&gt;
&lt;h3 id=&quot;2-prettier-code-formatter&quot;&gt;2. Prettier — Code Formatter&lt;/h3&gt;
&lt;p&gt;Auto-formats your code on save. No more arguing about tabs vs. spaces or where semicolons go — Prettier just decides and moves on.&lt;/p&gt;
&lt;p&gt;Setup tip: Enable &quot;Format on Save&quot; in VS Code settings so it happens automatically.&lt;/p&gt;
&lt;h3 id=&quot;3-tailwind-css-intellisense&quot;&gt;3. Tailwind CSS IntelliSense&lt;/h3&gt;
&lt;p&gt;If you're using Tailwind (and you should be, per Article 3), this gives you autocomplete for class names, shows the actual CSS values on hover, and even highlights conflicting classes.&lt;/p&gt;
&lt;h3 id=&quot;4-auto-rename-tag&quot;&gt;4. Auto Rename Tag&lt;/h3&gt;
&lt;p&gt;Rename an opening HTML/JSX tag and the closing tag updates automatically. Small thing, saves real time, especially in nested JSX.&lt;/p&gt;
&lt;h3 id=&quot;5-bracket-pair-colorizer-built-in-now-&quot;&gt;5. Bracket Pair Colorizer (Built-in now)&lt;/h3&gt;
&lt;p&gt;VS Code now has this built in by default — matching brackets get color-coded so you can actually see which { belongs to which } in deeply nested code. Just make sure it's enabled in settings.&lt;/p&gt;
&lt;h3 id=&quot;6-gitlens&quot;&gt;6. GitLens&lt;/h3&gt;
&lt;p&gt;Shows you who changed a line of code and when, right inline in the editor. Incredibly useful once you're working with any kind of version history — even solo projects benefit from seeing your own commit history at a glance.&lt;/p&gt;
&lt;h3 id=&quot;7-live-server&quot;&gt;7. Live Server&lt;/h3&gt;
&lt;p&gt;Spins up a local development server with live reload in one click — no need to manually refresh the browser every time you save a file. Especially useful for plain HTML/CSS/JS projects without a build tool.&lt;/p&gt;
&lt;h3 id=&quot;8-thunder-client&quot;&gt;8. Thunder Client&lt;/h3&gt;
&lt;p&gt;A lightweight REST API client built directly into VS Code. If you're testing an API endpoint for a project, you don't need to leave your editor or open Postman separately.&lt;/p&gt;
&lt;h3 id=&quot;9-error-lens&quot;&gt;9. Error Lens&lt;/h3&gt;
&lt;p&gt;Shows error and warning messages inline, right next to the line of code causing the problem, instead of making you check the Problems panel. Cuts down debugging time noticeably.&lt;/p&gt;
&lt;h3 id=&quot;10-material-icon-theme&quot;&gt;10. Material Icon Theme&lt;/h3&gt;
&lt;p&gt;Purely visual, but genuinely useful — gives every file type a distinct, recognizable icon in your file explorer. Makes navigating a large project noticeably faster once your eyes learn the icon shapes.&lt;/p&gt;
&lt;p&gt;How to Install Any of These&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open VS Code&lt;/li&gt;
&lt;li&gt;Click the Extensions icon in the sidebar (or Ctrl+Shift+X)&lt;/li&gt;
&lt;li&gt;Search the extension name&lt;/li&gt;
&lt;li&gt;Click Install&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That's it — no restart usually needed.&lt;/p&gt;
&lt;h3 id=&quot;final-thoughts-7&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;You don't need 40 extensions to be productive — you need the right 8 to 10. Install these, use them for a week, and you'll notice fewer small annoyances and less time spent on formatting, tag matching, and manual browser refreshing.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;em&gt;muhammad-farhan-dev.github.io/muhammadfarhan.dev&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22992/10-vs-code-extensions-every-frontend-developer-needs</guid>
<pubDate>Fri, 24 Jul 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>Hire Me: Muhammad Farhan — Frontend Developer Available for Remote Work</title>
<link>https://coderlegion.com/23328/hire-me-muhammad-farhan-frontend-developer-available-for-remote-work</link>
<description>&lt;h2 id=&quot;hi-i-m-muhammad-farhan&quot;&gt;Hi, I'm Muhammad Farhan&lt;/h2&gt;
&lt;p&gt;I'm a frontend developer based in Dera Ismail Khan, Pakistan, and I build clean, modern, fast-loading websites using React.js, Tailwind CSS, and WordPress. If you need a website built, a design turned into working code, or an existing site improved, I'd genuinely like to help — and I'm available to start right away.&lt;/p&gt;
&lt;h2 id=&quot;what-i-actually-do&quot;&gt;What I Actually Do&lt;/h2&gt;
&lt;p&gt;I specialize in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;React.js&lt;/strong&gt; — component-based, interactive web apps built to scale&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt; — clean, modern, fully responsive UI, my go-to styling approach&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML5 &amp;amp; CSS3&lt;/strong&gt; — solid, semantic, accessible markup underneath every project&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript (ES6+)&lt;/strong&gt; — smooth interactivity, no clunky or broken UI&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bootstrap&lt;/strong&gt; — for projects that need it, including maintaining older sites&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WordPress&lt;/strong&gt; — theme customization, blog setup, and full client websites, including custom frontend features layered on top&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;real-work-not-just-promises&quot;&gt;Real Work, Not Just Promises&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;UX Gazette&lt;/strong&gt; — a professional blog website I built for a real client on WordPress, live at uxgazette.com&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal Portfolio&lt;/strong&gt; — my own site, showcasing my design and development work&lt;/li&gt;
&lt;li&gt;Multiple additional projects across business landing pages, animated websites, and UI design work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don't just talk about being able to build things — every skill listed above has a real, live, shipped project behind it that you can actually visit and click through.&lt;/p&gt;
&lt;h2 id=&quot;why-work-with-me&quot;&gt;Why Work With Me&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I communicate clearly and respond fast.&lt;/strong&gt; No chasing me for updates — I keep you informed without being asked.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I care about clean, maintainable code&lt;/strong&gt;, not just something that looks right on the surface and breaks the moment it needs a change.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I'm affordable for the quality I deliver&lt;/strong&gt;, especially compared to larger agencies, while still meeting professional standards.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I'm available now&lt;/strong&gt; — for a single project, an ongoing freelance arrangement, or a part-time/remote role.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-i-can-help-you-with&quot;&gt;What I Can Help You With&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Building a new website from scratch (business site, portfolio, landing page)&lt;/li&gt;
&lt;li&gt;Converting a Figma or Adobe XD design into a fully working, responsive website&lt;/li&gt;
&lt;li&gt;Fixing bugs or improving performance on an existing site&lt;/li&gt;
&lt;li&gt;Customizing or maintaining a WordPress site&lt;/li&gt;
&lt;li&gt;Building custom tools, dashboards, or interactive features with React&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;let-s-talk-about-your-project&quot;&gt;Let's Talk About Your Project&lt;/h2&gt;
&lt;p&gt;If you have a project in mind — big or small — I'd love to hear about it. Reach out directly using any of the details below, and I'll get back to you quickly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email:&lt;/strong&gt; &lt;strong&gt;&lt;strong&gt;Emails are not allowed&lt;/strong&gt;&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Phone / WhatsApp:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;+92 335-4051272&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammadfarhandev.netlify.app&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://%20https://github.com/muhammad-farhan-dev&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Behance:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://behance.net/muhammadfarhan-dev&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Instagram:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://instagram.com/muhammadfarhan.dev&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;X (Twitter):&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://x.com/m_farhandev&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;WhatsApp Channel:&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;http://whatsapp.com/channel/0029Vb8GtTZ6mYPLeNwrgI3h&quot;&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Feel free to message me directly on WhatsApp for the fastest response — I usually reply within a few hours.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; — Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23328/hire-me-muhammad-farhan-frontend-developer-available-for-remote-work</guid>
<pubDate>Thu, 23 Jul 2026 09:31:37 +0000</pubDate>
</item>
<item>
<title>Tailwind CSS for Beginners: From Zero to Your First Component</title>
<link>https://coderlegion.com/22619/tailwind-css-for-beginners-from-zero-to-your-first-component</link>
<description>&lt;h2 id=&quot;introduction-8&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;The first time I saw a Tailwind CSS class list — something like flex items-center justify-between p-4 bg-slate-800 rounded-lg shadow-md — I genuinely thought it looked messy. Why not just write regular CSS?&lt;/p&gt;
&lt;p&gt;Then I actually used it on a real project, and within a week I understood why so many developers (myself included now) switched permanently. You stop context-switching between HTML and a separate CSS file, you stop naming classes like .card-wrapper-inner-2, and you build UI noticeably faster.&lt;/p&gt;
&lt;p&gt;This is the guide I wish I had when I started.&lt;/p&gt;
&lt;h2 id=&quot;what-tailwind-css-actually-is&quot;&gt;What Tailwind CSS Actually Is&lt;/h2&gt;
&lt;p&gt;Tailwind is a utility-first CSS framework. Instead of writing custom CSS classes, you compose your design directly in your HTML using small, single-purpose utility classes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Regular CSS:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.button {
  padding: 8px 16px;
  background-color: #3b82f6;
  border-radius: 8px;
  color: white;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Tailwind:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button class=&quot;px-4 py-2 bg-blue-500 rounded-lg text-white&quot;&amp;gt;
  Click Me
&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Same result. No separate CSS file needed for this button.&lt;/p&gt;
&lt;h3 id=&quot;setting-it-up-react-vite-&quot;&gt;Setting It Up (React + Vite)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;npm create vite@latest my-app -- --template react
cd my-app
npm install tailwindcss @tailwindcss/vite
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;In vite.config.js:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import tailwindcss from '@tailwindcss/vite'

export default {
  plugins: [tailwindcss()],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;In your main CSS file:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@import &quot;tailwindcss&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That's it — no separate config file required for modern Tailwind setups. Restart your dev server and you're ready to use utility classes anywhere.&lt;/p&gt;
&lt;h2 id=&quot;core-concepts-you-need-to-know&quot;&gt;Core Concepts You Need to Know&lt;/h2&gt;
&lt;h3 id=&quot;1-spacing&quot;&gt;1. Spacing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;p-4&lt;/strong&gt; = padding on all sides, &lt;strong&gt;px-4&lt;/strong&gt; = horizontal padding only, &lt;strong&gt;py-4&lt;/strong&gt; = vertical only, &lt;strong&gt;m-4&lt;/strong&gt; = margin. The number is a spacing scale &lt;strong&gt;(4 = 1rem = 16px)&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;2-flexbox-amp-grid-utilities&quot;&gt;2. Flexbox &amp;amp; Grid utilities&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;flex, items-center, justify-between, grid, grid-cols-3, gap-4&lt;/strong&gt; — everything from the Flexbox/Grid article, just as classes.&lt;/p&gt;
&lt;h3 id=&quot;3-responsive-design&quot;&gt;3. Responsive Design&lt;/h3&gt;
&lt;p&gt;Prefix any class with a breakpoint: &lt;strong&gt;md:flex-row&lt;/strong&gt; means &quot;apply this on medium screens and up.&quot;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;flex flex-col md:flex-row gap-4&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This stacks items vertically on mobile, then switches to a row on tablets and larger.&lt;/p&gt;
&lt;h3 id=&quot;4-hover-amp-state-variants&quot;&gt;4. Hover &amp;amp; State Variants&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;button class=&quot;bg-blue-500 hover:bg-blue-600 transition&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;hover:&lt;/strong&gt; applies only on hover. Same pattern works for &lt;strong&gt;focus:, active:, disabled:&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;building-your-first-component-a-pricing-card&quot;&gt;Building Your First Component: A Pricing Card&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;max-w-sm mx-auto bg-slate-800 rounded-2xl p-6 shadow-lg&quot;&amp;gt;
  &amp;lt;h3 class=&quot;text-xl font-bold text-white mb-2&quot;&amp;gt;Starter Plan&amp;lt;/h3&amp;gt;
  &amp;lt;p class=&quot;text-slate-400 mb-4&quot;&amp;gt;Perfect for small projects&amp;lt;/p&amp;gt;
  &amp;lt;p class=&quot;text-3xl font-bold text-white mb-6&quot;&amp;gt;$9&amp;lt;span class=&quot;text-base font-normal text-slate-400&quot;&amp;gt;/mo&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;
  &amp;lt;button class=&quot;w-full py-2 bg-blue-500 hover:bg-blue-600 rounded-lg text-white font-medium transition&quot;&amp;gt;
    Get Started
  &amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice what's happening: &lt;strong&gt;max-w-sm mx-auto&lt;/strong&gt; centers and constrains the card width, &lt;strong&gt;rounded-2xl&lt;/strong&gt; and &lt;strong&gt;shadow-lg&lt;/strong&gt; give it depth, and everything is readable directly from the class names — no jumping to a separate file to understand the styling.&lt;/p&gt;
&lt;h2 id=&quot;common-beginner-mistakes-6&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Fighting the spacing scale. Don't reach for custom pixel values&lt;br&gt;
immediately — Tailwind's default scale (4, 8, 12, 16...) covers 95%&lt;br&gt;
of real use cases.&lt;/li&gt;
&lt;li&gt;Not using @apply for repeated patterns. If you're copy-pasting the&lt;br&gt;
same 8 classes everywhere, extract them into a component instead of&lt;br&gt;
a CSS class — that's the React way to do it, not @apply.&lt;/li&gt;
&lt;li&gt;Ignoring the official docs. Tailwind's docs (tailwindcss.com) are&lt;br&gt;
genuinely excellent — searchable, example-driven, and the fastest&lt;br&gt;
way to find the exact class you need.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;final-thoughts-8&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Tailwind feels weird for about a week, then it feels like the only sane way to write CSS. The speed difference is real — I build UI noticeably faster now than when I wrote custom CSS files for every component.&lt;/p&gt;
&lt;p&gt;Start small: rebuild one existing component using Tailwind instead of your old CSS, and see how it feels.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a Frontend Developer specializing in React.js and Tailwind CSS, based in Dera Ismail Khan, Pakistan.&lt;br&gt;
Portfolio: muhammad-farhan-dev.github.io/muhammadfarhan.dev&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22619/tailwind-css-for-beginners-from-zero-to-your-first-component</guid>
<pubDate>Tue, 21 Jul 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>CSS Flexbox vs Grid: When to Use Which (Beginner's Guide)</title>
<link>https://coderlegion.com/22607/css-flexbox-vs-grid-when-to-use-which-beginners-guide</link>
<description>&lt;h2 id=&quot;introduction-9&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Every beginner hits this wall eventually: &quot;Do I use Flexbox or Grid here?&quot;&lt;/p&gt;
&lt;p&gt;I remember avoiding this question for months by just using Flexbox for everything — including things Grid was clearly built for. It worked, technically, but I was fighting the tool instead of using the right one.&lt;/p&gt;
&lt;p&gt;Here's the short version before we go deep: Flexbox is for one direction (a row or a column). Grid is for two directions at once (rows AND columns together). Once that clicks, the decision gets easy.&lt;/p&gt;
&lt;p&gt;Let's break it down properly.&lt;/p&gt;
&lt;h2 id=&quot;what-flexbox-actually-does&quot;&gt;What Flexbox Actually Does&lt;/h2&gt;
&lt;p&gt;Flexbox arranges items along a single axis — either horizontally or vertically.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.container {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;justify-content controls spacing along the main axis (usually horizontal), and align-items controls alignment on the cross axis (usually vertical).&lt;/p&gt;
&lt;h3 id=&quot;flexbox-is-perfect-for-&quot;&gt;Flexbox is perfect for:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Navigation bars (logo left, links right)&lt;/li&gt;
&lt;li&gt;Buttons sitting side by side&lt;/li&gt;
&lt;li&gt;Centering a single element vertically and horizontally&lt;/li&gt;
&lt;li&gt;Card content where items need to stretch or wrap in one direction&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-grid-actually-does&quot;&gt;What Grid Actually Does&lt;/h2&gt;
&lt;p&gt;Grid lets you define rows and columns at the same time, and place items precisely into that structure.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates 3 equal-width columns with 20px gaps — no media queries needed to get a basic responsive layout going.&lt;/p&gt;
&lt;h3 id=&quot;grid-is-perfect-for-&quot;&gt;Grid is perfect for:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Full page layouts (header, sidebar, main content, footer)&lt;/li&gt;
&lt;li&gt;Image galleries&lt;/li&gt;
&lt;li&gt;Card grids (like a blog listing page)&lt;/li&gt;
&lt;li&gt;Anything where you're thinking in rows AND columns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Real Test: Ask Yourself This&lt;/p&gt;
&lt;p&gt;&quot;Am I arranging things in one line, or am I building a layout?&quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One line → Flexbox&lt;/li&gt;
&lt;li&gt;Layout/grid of items → Grid&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;a-practical-example-building-a-card-grid&quot;&gt;A Practical Example: Building a Card Grid&lt;/h3&gt;
&lt;p&gt;Here's a common beginner project — a responsive grid of cards, done the right way with Grid:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;grid grid-cols-1 md:grid-cols-3 gap-6&quot;&amp;gt;
  &amp;lt;div class=&quot;bg-slate-800 p-4 rounded-lg&quot;&amp;gt;Card 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;bg-slate-800 p-4 rounded-lg&quot;&amp;gt;Card 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;bg-slate-800 p-4 rounded-lg&quot;&amp;gt;Card 3&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(That's Tailwind CSS classes, but it maps directly to Grid under the hood — grid, grid-cols-3, gap-6.)&lt;/p&gt;
&lt;p&gt;Now, inside each card, if you need to align an icon next to a title, or push a button to the bottom of the card — that's Flexbox's job:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;bg-slate-800 p-4 rounded-lg flex flex-col justify-between&quot;&amp;gt;
  &amp;lt;div class=&quot;flex items-center gap-2&quot;&amp;gt;
    &amp;lt;span&amp;gt;🔥&amp;lt;/span&amp;gt;
    &amp;lt;h3&amp;gt;Card Title&amp;lt;/h3&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;button&amp;gt;Learn More&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the pattern you'll use constantly: Grid for the outer layout, Flexbox for the inner content.&lt;/p&gt;
&lt;h2 id=&quot;common-beginner-mistakes-7&quot;&gt;Common Beginner Mistakes&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Using Grid for a simple navbar. Overkill — Flexbox does this in 3&lt;br&gt;
lines.&lt;/li&gt;
&lt;li&gt;Using Flexbox for a full page layout. You'll end up wrapping and&lt;br&gt;
fighting widths that Grid handles natively.&lt;/li&gt;
&lt;li&gt;Not using gap. Both Flexbox and Grid support gap now — no more&lt;br&gt;
margin hacks between items.&lt;/li&gt;
&lt;li&gt;Forgetting Grid can do more than equal columns.&lt;br&gt;
grid-template-columns: 200px 1fr gives you a fixed sidebar +&lt;br&gt;
flexible main content in one line.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;final-thoughts-9&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;You don't have to pick one and stick with it forever — most real websites use both together, Grid for structure and Flexbox for alignment inside components. Once you stop treating this as an either/or decision and start asking &quot;one direction or two?&quot;, it stops being confusing.&lt;/p&gt;
&lt;p&gt;Try rebuilding one of your old projects using this rule and see how much cleaner the CSS gets.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Muhammad Farhan&lt;/strong&gt; is a &lt;strong&gt;Frontend Developer&lt;/strong&gt; specializing in React.js and Tailwind CSS, based in &lt;strong&gt;Dera Ismail Khan, Pakistan&lt;/strong&gt;.&lt;br&gt;
Portfolio: &lt;a rel=&quot;nofollow&quot; href=&quot;https://muhammad-farhan-dev.github.io/muhammadfarhan.dev&quot;&gt;Muhammad Farhan&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22607/css-flexbox-vs-grid-when-to-use-which-beginners-guide</guid>
<pubDate>Fri, 17 Jul 2026 05:00:00 +0000</pubDate>
</item>
<item>
<title>15 Free Frontend Tools Every Developer Should Know in 2026</title>
<link>https://coderlegion.com/22579/15-free-frontend-tools-every-developer-should-know-in-2026</link>
<description>&lt;h2 id=&quot;introduction-10&quot;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When I started learning frontend development, I thought I needed expensive software to build things that looked &quot;professional.&quot; Turns out, that's completely false.&lt;/p&gt;
&lt;p&gt;Some of the best frontend tools out there are free — and a lot of developers, even experienced ones, don't know half of them exist. Whether you're picking colors, generating CSS animations, testing responsiveness, or just trying to find the right icon, there's a free tool for almost everything.&lt;/p&gt;
&lt;p&gt;In this post, I'm sharing 15 tools I personally use (or have used) while building real projects — from client websites to personal portfolios. No fluff, no &quot;100 tools you'll never open&quot; lists. Just the ones that actually save time.&lt;/p&gt;
&lt;p&gt;Let's get into it.&lt;/p&gt;
&lt;h3 id=&quot;1-design-amp-color-tools&quot;&gt;1. Design &amp;amp; Color Tools&lt;/h3&gt;
&lt;p&gt;Good design starts with good colors and layout inspiration. These tools take the guesswork out of it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Coolors&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Coolors is the fastest way to generate a color palette. Hit the spacebar and it keeps generating combinations until you find one you like. You can lock colors you love and regenerate the rest.&lt;/p&gt;
&lt;p&gt;Why beginners love it: No design theory needed — just pick what looks good.&lt;br&gt;
🔗 coolors.co&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adobe Color&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;More advanced than Coolors, this lets you build palettes based on color theory rules (complementary, triadic, monochromatic, etc.) and even extract a palette from an image.&lt;/p&gt;
&lt;p&gt;Why it's useful: Great when you want a palette that matches a client's brand photo or logo.&lt;br&gt;
🔗 color.adobe.com&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;2-css-generators-stop-writing-gradients-by-hand-&quot;&gt;2. CSS Generators (Stop Writing Gradients by Hand)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;CSS Gradient&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pick colors, choose the direction, and copy the ready-made CSS. Simple, fast, and works for linear and radial gradients.&lt;br&gt;
🔗 cssgradient.io&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Neumorphism.io&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you want that soft, &quot;pressed-in&quot; neumorphic UI style, this generator gives you the exact box-shadow code — adjustable by distance, blur, and intensity, with light/dark background support.&lt;br&gt;
🔗 neumorphism.io&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clippy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Need a custom shape (hexagon, arrow, triangle) using clip-path? Clippy lets you drag points visually and copies the CSS for you. No more guessing polygon coordinates.&lt;br&gt;
🔗 bennettfeely.com/clippy&lt;/p&gt;
&lt;p&gt;Pro tip: These generators are amazing for learning too — generate the code, then read it and understand why it works. That's how I actually learned box-shadow and clip-path properties.&lt;/p&gt;
&lt;h3 id=&quot;3-icons-that-don-t-look-generic&quot;&gt;3. Icons That Don't Look Generic&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Lucide Icons&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A clean, consistent icon set that works beautifully with React and Tailwind CSS. Lightweight, tree-shakable, and has an official React package (lucide-react).&lt;br&gt;
🔗 lucide.dev&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Heroicons&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Made by the Tailwind CSS team, so naturally it pairs perfectly with Tailwind projects. Comes in outline and solid styles.&lt;br&gt;
🔗 heroicons.com&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Font Awesome (Free Tier)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The classic. Massive icon library, and the free tier alone covers most needs — social icons, UI icons, brand logos.&lt;br&gt;
🔗 fontawesome.com&lt;/p&gt;
&lt;p&gt;My pick for React + Tailwind projects: Lucide. It's the one I use across my own builds because it's lightweight and easy to customize with Tailwind classes.&lt;/p&gt;
&lt;h3 id=&quot;4-fonts-amp-typography&quot;&gt;4. Fonts &amp;amp; Typography&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Google Fonts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The obvious one, but don't just grab the first font you see. Google Fonts also shows you popularity, styles, and lets you preview your own text before choosing.&lt;br&gt;
🔗 fonts.google.com&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fontjoy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Struggling to pair a heading font with a body font? Fontjoy uses AI to suggest font combinations that actually work together — and you can lock one font and regenerate the other.&lt;br&gt;
🔗 fontjoy.com&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;5-online-code-playgrounds&quot;&gt;5. Online Code Playgrounds&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;CodePen&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Great for quick CSS/JS experiments, sharing snippets, and browsing what other developers are building. Perfect for testing an animation idea before adding it to a real project.&lt;br&gt;
🔗 codepen.io&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;StackBlitz&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A full online IDE that runs actual React, Vue, or Node projects in your browser — no local setup needed. I use this a lot when testing a quick React component idea.&lt;br&gt;
🔗 stackblitz.com&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CodeSandbox&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Similar to StackBlitz, with strong support for sharing full working React apps and instant deployment previews. Great for collaborating or showing a client a live demo without deploying anywhere.&lt;br&gt;
🔗 codesandbox.io&lt;/p&gt;
&lt;h3 id=&quot;6-image-optimization-tools&quot;&gt;6. Image Optimization Tools&lt;/h3&gt;
&lt;p&gt;Heavy images kill website speed — and speed affects both user experience and SEO rankings.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Squoosh&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Made by Google. Drag in an image, compare compression formats (WebP, AVIF, JPEG) side by side, and download the optimized version — all in your browser, nothing uploaded to a server.&lt;br&gt;
🔗 squoosh.app&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TinyPNG&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Bulk compress PNG and JPEG images with barely noticeable quality loss. I run every client project's images through this before deployment.&lt;br&gt;
🔗 tinypng.com&lt;/p&gt;
&lt;h3 id=&quot;7-responsive-amp-accessibility-testing&quot;&gt;7. Responsive &amp;amp; Accessibility Testing&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Responsively App&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A free desktop app that shows your website on multiple device sizes at once, side by side, and syncs scrolling and clicks across all of them. Saves so much time compared to resizing your browser manually.&lt;br&gt;
🔗 responsively.app&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chrome DevTools (Lighthouse)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Built right into Chrome. Open DevTools → Lighthouse tab → run an audit. It scores your site on performance, accessibility, best practices, and SEO, and tells you exactly what to fix.&lt;/p&gt;
&lt;p&gt;Why this matters for freelancers: Clients love seeing a 90+ Lighthouse score. It's an easy way to prove your work is solid.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WAVE&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A free accessibility checker. Paste your URL and it visually flags missing alt text, low contrast, and other accessibility issues directly on the page.&lt;br&gt;
🔗 wave.webaim.org&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;8-reference-amp-learning&quot;&gt;8. Reference &amp;amp; Learning&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;MDN Web Docs&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The single most reliable source for HTML, CSS, and JavaScript documentation. When in doubt, check MDN before trusting a random blog post (including this one).&lt;br&gt;
🔗 developer.mozilla.org&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can I Use&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before using a newer CSS or JS feature, check browser support here. Saves you from shipping something that breaks in Safari or older browsers.&lt;br&gt;
🔗 caniuse.com&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You don't need a paid design subscription or premium plugin to build clean, professional websites. The tools above cover almost every stage of frontend work — design, coding, testing, and optimization — and they're all free.&lt;/p&gt;
&lt;p&gt;My honest advice as someone who's been learning and building for the past couple of years: don't try to learn all 15 tools at once. Pick 2–3 that solve a problem you're facing right now, use them in your next project, and the rest will come naturally as you build more.&lt;/p&gt;
&lt;p&gt;If you found this useful, save it — you'll probably come back to this list more than once.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Written by &lt;strong&gt;Muhammad Farhan&lt;/strong&gt; — Frontend Developer specializing in React.js &amp;amp; Tailwind CSS, based in &lt;strong&gt;Dera Ismail Khan, Pakistan&lt;/strong&gt;.&lt;br&gt;
&lt;strong&gt;Portfolio:&lt;/strong&gt; muhammad-farhan-dev.github.io/muhammadfarhan.dev &lt;br&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; github.com/muhammad-farhan-dev&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/22579/15-free-frontend-tools-every-developer-should-know-in-2026</guid>
<pubDate>Tue, 14 Jul 2026 06:38:30 +0000</pubDate>
</item>
<item>
<title>Why Every Frontend Project Should Have Its Own UI Layer</title>
<link>https://coderlegion.com/18448/why-every-frontend-project-should-have-its-own-ui-layer</link>
<description>&lt;p&gt;Modern frontend development is heavily centered around component frameworks: Vue, React, Svelte, Solid, Angular, and others. The ecosystem also provides endless UI libraries: Vuetify, PrimeVue, Naive UI, MUI, Ant Design, Chakra, Radix, Headless UI, shadcn/ui, and hundreds more.&lt;/p&gt;
&lt;p&gt;Most teams directly import these libraries into application code.&lt;/p&gt;
&lt;p&gt;I think that is a long-term architectural mistake.&lt;/p&gt;
&lt;p&gt;Every serious frontend project should have its own internal UI layer — its own component system — even if internally it relies almost entirely on third-party libraries.&lt;/p&gt;
&lt;p&gt;Not because reinventing buttons is fun.&lt;br&gt;
Because abstraction boundaries matter.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-problem-with-directly-using-ui-libraries&quot;&gt;The Problem With Directly Using UI Libraries&lt;/h3&gt;
&lt;p&gt;Direct usage tightly couples the application to external implementation details.&lt;/p&gt;
&lt;p&gt;You start with something simple:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;ElButton type=&quot;primary&quot; size=&quot;small&quot;&amp;gt;
    Save
&amp;lt;/ElButton&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A year later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the library changes APIs,&lt;/li&gt;
&lt;li&gt;design requirements evolve,&lt;/li&gt;
&lt;li&gt;accessibility requirements appear,&lt;/li&gt;
&lt;li&gt;dark theme becomes mandatory,&lt;/li&gt;
&lt;li&gt;SSR breaks,&lt;/li&gt;
&lt;li&gt;bundle size becomes a problem,&lt;/li&gt;
&lt;li&gt;a component becomes abandoned,&lt;/li&gt;
&lt;li&gt;or the team simply wants another UI system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now the entire codebase depends on thousands of scattered library-specific decisions.&lt;/p&gt;
&lt;p&gt;The UI library stops being a dependency.&lt;/p&gt;
&lt;p&gt;It becomes infrastructure.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;your-ui-layer-is-an-architectural-boundary&quot;&gt;Your UI Layer Is An Architectural Boundary&lt;/h2&gt;
&lt;p&gt;Instead of using third-party components directly, create your own application-level components:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;AppButton&amp;gt;
&amp;lt;AppInput&amp;gt;
&amp;lt;AppDialog&amp;gt;
&amp;lt;AppTable&amp;gt;
&amp;lt;AppDatePicker&amp;gt;
&amp;lt;AppPageLayout&amp;gt;
&amp;lt;AppEntityEditor&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Internally, these components may use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PrimeVue&lt;/li&gt;
&lt;li&gt;Vuetify&lt;/li&gt;
&lt;li&gt;Radix&lt;/li&gt;
&lt;li&gt;native browser APIs&lt;/li&gt;
&lt;li&gt;custom rendering&lt;/li&gt;
&lt;li&gt;or completely different implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The application itself should not care.&lt;/p&gt;
&lt;p&gt;This creates a stable internal contract between the product and external dependencies.&lt;/p&gt;
&lt;p&gt;The application talks to &lt;em&gt;your&lt;/em&gt; UI architecture.&lt;/p&gt;
&lt;p&gt;Your architecture talks to vendor libraries.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;wrappers-are-not-extra-boilerplate-&quot;&gt;Wrappers Are Not &quot;Extra Boilerplate&quot;&lt;/h2&gt;
&lt;p&gt;A common objection:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&quot;Why wrap everything? That's just unnecessary abstraction.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It is not abstraction for abstraction's sake.&lt;/p&gt;
&lt;p&gt;It is containment.&lt;/p&gt;
&lt;p&gt;The wrapper layer centralizes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;naming conventions,&lt;/li&gt;
&lt;li&gt;defaults,&lt;/li&gt;
&lt;li&gt;accessibility,&lt;/li&gt;
&lt;li&gt;theme propagation,&lt;/li&gt;
&lt;li&gt;behavior normalization,&lt;/li&gt;
&lt;li&gt;analytics hooks,&lt;/li&gt;
&lt;li&gt;keyboard handling,&lt;/li&gt;
&lt;li&gt;validation,&lt;/li&gt;
&lt;li&gt;localization,&lt;/li&gt;
&lt;li&gt;performance workarounds,&lt;/li&gt;
&lt;li&gt;SSR compatibility,&lt;/li&gt;
&lt;li&gt;browser quirks,&lt;/li&gt;
&lt;li&gt;and migration strategy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without wrappers, all of this leaks into product code.&lt;/p&gt;
&lt;p&gt;Then every page becomes infrastructure code.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-biggest-advantage-replaceability&quot;&gt;The Biggest Advantage: Replaceability&lt;/h2&gt;
&lt;p&gt;This is the most important benefit.&lt;/p&gt;
&lt;p&gt;When UI libraries are hidden behind your own components, replacing them becomes feasible.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;AppDatePicker&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Today internally:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;PrimeVue DatePicker
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tomorrow:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;Flatpickr
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;Native browser date input
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;Custom implementation
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The application code remains unchanged.&lt;/p&gt;
&lt;p&gt;This matters more than most teams realize.&lt;/p&gt;
&lt;p&gt;UI ecosystems move extremely fast. Libraries become abandoned surprisingly often.&lt;/p&gt;
&lt;p&gt;A thin internal UI layer dramatically reduces migration cost.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;mixing-multiple-ui-libraries-becomes-safe&quot;&gt;Mixing Multiple UI Libraries Becomes Safe&lt;/h2&gt;
&lt;p&gt;Direct usage of multiple UI systems usually creates chaos.&lt;/p&gt;
&lt;p&gt;Different:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;design languages,&lt;/li&gt;
&lt;li&gt;spacing systems,&lt;/li&gt;
&lt;li&gt;keyboard behavior,&lt;/li&gt;
&lt;li&gt;focus handling,&lt;/li&gt;
&lt;li&gt;overlay logic,&lt;/li&gt;
&lt;li&gt;animation systems,&lt;/li&gt;
&lt;li&gt;theming models,&lt;/li&gt;
&lt;li&gt;and accessibility semantics.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But with an internal UI layer, multiple libraries can coexist safely.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;one library provides excellent tables,&lt;/li&gt;
&lt;li&gt;another has better dialogs,&lt;/li&gt;
&lt;li&gt;another has superior date pickers,&lt;/li&gt;
&lt;li&gt;another has accessible comboboxes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your application never sees this complexity directly.&lt;/p&gt;
&lt;p&gt;Your wrapper layer normalizes it.&lt;/p&gt;
&lt;p&gt;This is extremely powerful.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;your-ui-layer-is-also-a-design-system&quot;&gt;Your UI Layer Is Also A Design System&lt;/h2&gt;
&lt;p&gt;The important shift:&lt;/p&gt;
&lt;p&gt;Your design system should not belong to the UI vendor.&lt;/p&gt;
&lt;p&gt;It should belong to the product.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;your naming,&lt;/li&gt;
&lt;li&gt;your semantics,&lt;/li&gt;
&lt;li&gt;your defaults,&lt;/li&gt;
&lt;li&gt;your UX patterns,&lt;/li&gt;
&lt;li&gt;your layout philosophy,&lt;/li&gt;
&lt;li&gt;your interaction rules.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not whatever the library authors decided.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;AppDangerButton /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;is far more meaningful than:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;ElButton type=&quot;danger&quot; plain /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first expresses product semantics.&lt;/p&gt;
&lt;p&gt;The second expresses vendor implementation details.&lt;/p&gt;
&lt;p&gt;That distinction becomes critical at scale.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;default-configuration-reduces-massive-verbosity&quot;&gt;Default Configuration Reduces Massive Verbosity&lt;/h2&gt;
&lt;p&gt;One underrated benefit of internal wrappers:&lt;/p&gt;
&lt;p&gt;They eliminate repetitive configuration.&lt;/p&gt;
&lt;p&gt;Without wrappers:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;ThirdPartyInput
    size=&quot;small&quot;
    variant=&quot;filled&quot;
    density=&quot;compact&quot;
    clearable
    rounded
    theme=&quot;dark&quot;
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Repeated hundreds or thousands of times.&lt;/p&gt;
&lt;p&gt;With wrappers:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;AppInput /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The wrapper already encodes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;project defaults,&lt;/li&gt;
&lt;li&gt;theme defaults,&lt;/li&gt;
&lt;li&gt;accessibility defaults,&lt;/li&gt;
&lt;li&gt;density rules,&lt;/li&gt;
&lt;li&gt;validation behavior,&lt;/li&gt;
&lt;li&gt;localization behavior,&lt;/li&gt;
&lt;li&gt;analytics integration,&lt;/li&gt;
&lt;li&gt;focus handling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This massively reduces UI noise in application code.&lt;/p&gt;
&lt;p&gt;The application becomes more declarative.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;theme-propagation-becomes-centralized&quot;&gt;Theme Propagation Becomes Centralized&lt;/h2&gt;
&lt;p&gt;Third-party UI libraries usually bring their own theme systems.&lt;/p&gt;
&lt;p&gt;That becomes problematic when multiple libraries coexist.&lt;/p&gt;
&lt;p&gt;Each library wants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;its own tokens,&lt;/li&gt;
&lt;li&gt;its own variables,&lt;/li&gt;
&lt;li&gt;its own dark mode implementation,&lt;/li&gt;
&lt;li&gt;its own color system.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your internal UI layer solves this.&lt;/p&gt;
&lt;p&gt;The application owns the real design tokens:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;:root {
    --color-bg: #ffffff;
    --color-text: #111111;
    --color-primary: #3b82f6;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then wrapper components propagate these tokens into underlying libraries.&lt;/p&gt;
&lt;p&gt;Your product controls the visual system.&lt;/p&gt;
&lt;p&gt;Libraries adapt to &lt;em&gt;you&lt;/em&gt;, not the other way around.&lt;/p&gt;
&lt;p&gt;This is one of the cleanest ways to support:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dark mode,&lt;/li&gt;
&lt;li&gt;white-labeling,&lt;/li&gt;
&lt;li&gt;custom themes,&lt;/li&gt;
&lt;li&gt;enterprise branding,&lt;/li&gt;
&lt;li&gt;runtime theme switching.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;modern-browser-apis-make-custom-ui-more-realistic&quot;&gt;Modern Browser APIs Make Custom UI More Realistic&lt;/h2&gt;
&lt;p&gt;Five years ago, fully custom UI infrastructure was expensive.&lt;/p&gt;
&lt;p&gt;Today browsers provide much better primitives.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Popover API&lt;/li&gt;
&lt;li&gt;anchor positioning&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:has()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;CSS nesting&lt;/li&gt;
&lt;li&gt;container queries&lt;/li&gt;
&lt;li&gt;inert&lt;/li&gt;
&lt;li&gt;view transitions&lt;/li&gt;
&lt;li&gt;modern focus management&lt;/li&gt;
&lt;li&gt;top-layer behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Especially important are the newer overlay-related APIs.&lt;/p&gt;
&lt;p&gt;Historically, dialogs, dropdowns, popovers, tooltips, and context menus were extremely difficult because of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;z-index wars,&lt;/li&gt;
&lt;li&gt;focus traps,&lt;/li&gt;
&lt;li&gt;scroll locking,&lt;/li&gt;
&lt;li&gt;portal systems,&lt;/li&gt;
&lt;li&gt;positioning,&lt;/li&gt;
&lt;li&gt;stacking contexts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Modern browser primitives increasingly solve these problems natively.&lt;/p&gt;
&lt;p&gt;This changes the economics of UI architecture.&lt;/p&gt;
&lt;p&gt;Building internal abstractions is becoming cheaper and more maintainable.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;ui-architecture-is-more-than-form-controls&quot;&gt;UI Architecture Is More Than Form Controls&lt;/h2&gt;
&lt;p&gt;Many teams think only about atomic components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;buttons,&lt;/li&gt;
&lt;li&gt;inputs,&lt;/li&gt;
&lt;li&gt;selects,&lt;/li&gt;
&lt;li&gt;checkboxes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the real value appears higher in the hierarchy.&lt;/p&gt;
&lt;p&gt;Your internal UI layer can orchestrate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;page layouts,&lt;/li&gt;
&lt;li&gt;entity editors,&lt;/li&gt;
&lt;li&gt;filter panels,&lt;/li&gt;
&lt;li&gt;data tables,&lt;/li&gt;
&lt;li&gt;toolbar systems,&lt;/li&gt;
&lt;li&gt;sidebars,&lt;/li&gt;
&lt;li&gt;navigation structures,&lt;/li&gt;
&lt;li&gt;CRUD workflows,&lt;/li&gt;
&lt;li&gt;master-detail layouts,&lt;/li&gt;
&lt;li&gt;save/cancel flows,&lt;/li&gt;
&lt;li&gt;loading orchestration,&lt;/li&gt;
&lt;li&gt;permissions handling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;EntityPage&amp;gt;
    &amp;lt;EntityToolbar /&amp;gt;
    &amp;lt;EntityFilters /&amp;gt;
    &amp;lt;EntityTable /&amp;gt;
&amp;lt;/EntityPage&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now your product develops consistent workflow patterns.&lt;/p&gt;
&lt;p&gt;Not just reusable buttons.&lt;/p&gt;
&lt;p&gt;This is where frontend architecture starts becoming a platform.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;internal-ui-layers-improve-long-term-stability&quot;&gt;Internal UI Layers Improve Long-Term Stability&lt;/h2&gt;
&lt;p&gt;Projects live longer than frontend trends.&lt;/p&gt;
&lt;p&gt;The average enterprise frontend outlives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multiple framework trends,&lt;/li&gt;
&lt;li&gt;multiple design trends,&lt;/li&gt;
&lt;li&gt;multiple UI libraries,&lt;/li&gt;
&lt;li&gt;and sometimes even multiple frontend teams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A dedicated UI layer creates isolation from ecosystem volatility.&lt;/p&gt;
&lt;p&gt;It reduces the blast radius of change.&lt;/p&gt;
&lt;p&gt;That is not premature abstraction.&lt;/p&gt;
&lt;p&gt;That is operational risk management.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;this-applies-beyond-vue&quot;&gt;This Applies Beyond Vue&lt;/h2&gt;
&lt;p&gt;Vue examples are convenient because Vue component composition is extremely ergonomic.&lt;/p&gt;
&lt;p&gt;But the idea is framework-agnostic.&lt;/p&gt;
&lt;p&gt;The same architecture works in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Svelte&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Solid&lt;/li&gt;
&lt;li&gt;Web Components&lt;/li&gt;
&lt;li&gt;even server-rendered systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Any component-based frontend benefits from stable internal UI contracts.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;a-practical-rule&quot;&gt;A Practical Rule&lt;/h2&gt;
&lt;p&gt;One of the first architectural tasks in a frontend project should be:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Define the project's internal UI hierarchy before building product pages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not after.&lt;/p&gt;
&lt;p&gt;Not during migration.&lt;/p&gt;
&lt;p&gt;Not after technical debt accumulates.&lt;/p&gt;
&lt;p&gt;At the beginning.&lt;/p&gt;
&lt;p&gt;Because once product code directly depends on third-party UI libraries, decoupling becomes expensive.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;potential-downsides&quot;&gt;Potential Downsides&lt;/h2&gt;
&lt;p&gt;This approach is not free.&lt;/p&gt;
&lt;p&gt;Possible drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;initial setup cost,&lt;/li&gt;
&lt;li&gt;additional maintenance,&lt;/li&gt;
&lt;li&gt;risk of over-abstraction,&lt;/li&gt;
&lt;li&gt;wrapper drift from underlying libraries,&lt;/li&gt;
&lt;li&gt;documentation burden,&lt;/li&gt;
&lt;li&gt;onboarding complexity,&lt;/li&gt;
&lt;li&gt;temptation to reinvent mature solutions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Poorly designed wrappers can absolutely become worse than direct usage.&lt;/p&gt;
&lt;p&gt;The goal is not to hide everything.&lt;/p&gt;
&lt;p&gt;The goal is to own the architectural boundary.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;final-thought&quot;&gt;Final Thought&lt;/h2&gt;
&lt;p&gt;Frontend developers often discuss frameworks.&lt;/p&gt;
&lt;p&gt;But frameworks are transient.&lt;/p&gt;
&lt;p&gt;Architecture lasts much longer.&lt;/p&gt;
&lt;p&gt;A frontend codebase should not structurally depend on the internal API decisions of a third-party UI vendor.&lt;/p&gt;
&lt;p&gt;It should depend on its own UI language.&lt;/p&gt;
&lt;p&gt;That language becomes one of the most valuable assets in the entire frontend architecture.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;What additional advantages or disadvantages have you seen with internal UI layers and wrapper-based component systems?&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/18448/why-every-frontend-project-should-have-its-own-ui-layer</guid>
<pubDate>Wed, 20 May 2026 11:48:03 +0000</pubDate>
</item>
<item>
<title>Why Your Backend, Frontend, and Database “Don’t Talk”</title>
<link>https://coderlegion.com/15065/why-your-backend-frontend-and-database-dont-talk</link>
<description>&lt;p&gt;I expected my first ever full-stack project to end with a sense of completion. my plan was to build the frontend, set up the backend, connect a database, then watch everything come together into a finished product.&lt;/p&gt;
&lt;p&gt;Instead, I ran into something far more frustrating than your average bug: nothing was connected properly, and i had no idea why. The strangest part was that, on the surface, everything looked completely fine. The frontend loaded without issues, the backend server ran, and the database connection didn’t show any errors, nothing was fundamentally wrong. But the moment I tried to use the system as a whole, everything collapsed in a way that didn’t make sense at fisrt.&lt;/p&gt;
&lt;p&gt;Requests didn’t behave correctly, data didn’t flow properly between layers, and responses that I did manage to recieve didn’t match what I was expecting at all. It felt less like a broken program, and more like 3 separate systems pretending to. be connected, but never actually communicating in any meaningful way.&lt;/p&gt;
&lt;p&gt;Naturally, I fell into what i now call the debugging spiral. I started guessing, checking to see if the frontend was sending the right requests. When I failed to find anything, i moved to the backend routes, assuming something wasn’t being handled correctly. I went back and forth, checking the database connections, back to the front end, repeating the same cycle slightly differently each time.&lt;/p&gt;
&lt;p&gt;But there was no single obvious error that I could fix. And this was where the real frustration came in, because debugging becomes almost disorientating when you have nothing concrete to grasp onto. You move endlessly between parts of the system, hoping if you look at it from a slightly different angle, something will eventually look wrong. But everything remains to appear technically correct, and the system remains to behave incorrectly.&lt;/p&gt;
&lt;p&gt;The real issue, which I didn’t realise at the time, was that I was treating the app as separate components instead of a single, connected system. In my head, the frontend was one thing, the backend was another, and the database was another independent piece. So, I assumed debugging meant finding which one of them was broken and fixing it in isolation. But, when dealing with full-stack systems, things don’t usually fail in a clean, isolated way. They fail in the spaces between components, the communication layers that tie everything together. But at that point in my learning, I didn’t really understand those connections properly, and understand how fragile they really are.&lt;/p&gt;
&lt;p&gt;What I eventually started to realise is that ‘connection’ in full-stack development isn’t just an abstract idea that magically links everything together. It consists of a series of very explicit interactions that all have t line up perfectly for a system to work.&lt;/p&gt;
&lt;p&gt;You define routes on the backend that expect specific requests, which you have to send from the frontend in a particular format. The data has to be structured using formats like JSON so both sides can understand each other. You handle responses manually and then update the UI based off of that data. If even one of these steps fails, the system doesn’t only partially fail, or break a little bit, it quietly stops behaving in the way you would expect, without always sowing you a clear error message explaining why.&lt;/p&gt;
&lt;p&gt;That is part of what made the whole experience so confusing. The most deceptive part for me wasn’t that things were breaking, it was that everything looked like it was working. No console errors were being logged, no visible crashes, which lead me to a dangerous assumption: if nothing is visibly wrong, then everything must be fine. But when dealing with full-stack development, that assumption falls apart incredibly quickly.&lt;/p&gt;
&lt;p&gt;You can have a system that is completely broken in terms of logic and data flow, while showing no obvious signs of failure in wither the logs or the interface. The system doesn’t always announce it’s problems, it expects you to connect the dots yourself.&lt;/p&gt;
&lt;p&gt;Looking back, the real lesson I learnt wasn’t about fixing one specific bug in my code. It was about changing how I think about a system as a whole. I spent hours looking for broken parts, when I should’ve been looking for broken communication instead. And that difference matters more than I realised at the time, because debugging isn’t all about understanding individual components, you have to also understand how those components interact with one another, and where that interaction has the possibility of falling apart.&lt;/p&gt;
&lt;p&gt;My project didn’t fail because I wrote bad code, it failed because I failed to understand that debugging a system is a completely different skill to debugging a single piece of code.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/15065/why-your-backend-frontend-and-database-dont-talk</guid>
<pubDate>Fri, 17 Apr 2026 11:13:45 +0000</pubDate>
</item>
<item>
<title>Exploring the power of 3D experiences on the web</title>
<link>https://coderlegion.com/12896/exploring-the-power-of-3d-experiences-on-the-web</link>
<description>&lt;p&gt;This is an experimental 3D sports landing page built with modern frontend technologies. The goal was to create a more immersive and interactive experience compared to traditional flat landing pages.&lt;br&gt;
Inspired by a great tutorial from JS Mastery, I built this 3D Basketball Landing Page as a creative frontend experiment.&lt;/p&gt;
&lt;p&gt;Tech stack&lt;br&gt;
• Three.js – for rendering interactive 3D scenes&lt;br&gt;
• GSAP – for smooth, high-performance animations&lt;br&gt;
• Next.js – for modern React architecture and performance&lt;/p&gt;
&lt;p&gt;Three.js allows developers to render interactive 3D graphics directly in the browser using WebGL, enabling immersive web experiences and real-time animations.&lt;/p&gt;
&lt;p&gt;The page combines 3D elements, animated transitions, and camera movement to make the interface feel more alive and interactive.&lt;/p&gt;
&lt;p&gt;The idea was to move beyond static layouts and create a landing page where motion, depth, and interactivity become part of the user experience.&lt;/p&gt;
&lt;p&gt;I also used AI tools during development to speed up experimentation and explore different creative approaches.&lt;/p&gt;
&lt;p&gt;Live project:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://3d-basketball-template.vercel.app/&quot;&gt;https://3d-basketball-template.vercel.app/&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12896/exploring-the-power-of-3d-experiences-on-the-web</guid>
<pubDate>Sun, 15 Mar 2026 12:29:25 +0000</pubDate>
</item>
<item>
<title>Exploring the power of 3D experiences on the modern web</title>
<link>https://coderlegion.com/12895/exploring-the-power-of-3d-experiences-on-the-modern-web</link>
<description>&lt;p&gt;This is an experimental 3D sports landing page built with modern frontend technologies. The goal was to create a more immersive and interactive experience compared to traditional flat landing pages.&lt;br&gt;
Inspired by a great tutorial from JS Mastery, I built this 3D Basketball Landing Page as a creative frontend experiment.&lt;/p&gt;
&lt;p&gt;Tech stack&lt;br&gt;
• Three.js – for rendering interactive 3D scenes&lt;br&gt;
• GSAP – for smooth, high-performance animations&lt;br&gt;
• Next.js – for modern React architecture and performance&lt;/p&gt;
&lt;p&gt;Three.js allows developers to render interactive 3D graphics directly in the browser using WebGL, enabling immersive web experiences and real-time animations.&lt;/p&gt;
&lt;p&gt;The page combines 3D elements, animated transitions, and camera movement to make the interface feel more alive and interactive.&lt;/p&gt;
&lt;p&gt;The idea was to move beyond static layouts and create a landing page where motion, depth, and interactivity become part of the user experience.&lt;/p&gt;
&lt;p&gt;I also used AI tools during development to speed up experimentation and explore different creative approaches.&lt;/p&gt;
&lt;p&gt;Live project:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://3d-basketball-template.vercel.app/&quot;&gt;https://3d-basketball-template.vercel.app/&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/12895/exploring-the-power-of-3d-experiences-on-the-modern-web</guid>
<pubDate>Sun, 15 Mar 2026 12:28:47 +0000</pubDate>
</item>
<item>
<title>Boosting Frontend Productivity with Large Language Models</title>
<link>https://coderlegion.com/11778/boosting-frontend-productivity-with-large-language-models</link>
<description>&lt;p&gt;Large Language Models (LLMs) such as GPT are starting to reshape how frontend developers build, debug, and deliver applications. They are no longer just tools for chatbots or natural language processing—they are becoming development assistants that reduce repetitive work, accelerate prototyping, and even power features inside modern web applications.&lt;/p&gt;
&lt;p&gt;In this post, we’ll explore how LLMs can be applied to different areas of frontend development, from scaffolding and debugging to prototyping and integration.&lt;br&gt;
Scaffolding and Boilerplate Generation&lt;/p&gt;
&lt;p&gt;One of the most time-consuming aspects of frontend work is setting up repetitive structures. Developers often spend hours creating responsive navigation bars, authentication forms, or reusable UI components. With an LLM, these tasks can be simplified dramatically.&lt;/p&gt;
&lt;p&gt;By describing what you need in natural language, you can instantly generate starting points for React, Vue, or Angular components. For example, a simple prompt like “Create a responsive React navbar with Tailwind CSS, including a dropdown and dark mode toggle” can produce a functional scaffold in seconds. The generated code won’t be perfect, but it provides a strong foundation that can be refined and customized.&lt;br&gt;
Debugging and Refactoring&lt;/p&gt;
&lt;p&gt;LLMs can also function as on-demand code reviewers. Instead of searching through documentation or debugging forums, you can paste your code into a model and ask for help. Models are particularly effective at identifying common mistakes in state management, suggesting optimizations, and even refactoring legacy code into modern frameworks.&lt;/p&gt;
&lt;p&gt;Imagine a scenario where a Vue watch function isn’t firing as expected. Instead of spending an hour troubleshooting, you could simply ask an LLM, “Why isn’t this watch function firing, and how can I fix it?” In many cases, the model will highlight the issue and provide a working alternative.&lt;br&gt;
Prototyping for UI and UX&lt;/p&gt;
&lt;p&gt;Frontend development is about speed and iteration, and this is where LLMs excel. They allow developers to quickly experiment with variations of UI components, test accessibility improvements, and even convert text-based requirements into functional wireframes.&lt;/p&gt;
&lt;p&gt;Combined with design tools like Figma, LLMs can bridge the gap between design and implementation. This means teams can move from concept to code faster, while still keeping accessibility and best practices in mind.&lt;br&gt;
Documentation and Learning&lt;/p&gt;
&lt;p&gt;Good documentation is often an afterthought, yet it is essential for maintainable projects. LLMs make it easier to generate clear explanations for complex logic, produce onboarding notes for new developers, and even create project README files.&lt;/p&gt;
&lt;p&gt;For example, by asking a model to “Explain what this custom React hook does in plain English,” you can transform intricate code into developer-friendly documentation that can be immediately reused. This not only saves time but also improves team communication.&lt;br&gt;
Embedding LLMs in Frontend Applications&lt;/p&gt;
&lt;p&gt;LLMs are not only useful during development they can also become part of the product itself. Modern web applications are increasingly embedding AI-powered features to enhance user experience.&lt;/p&gt;
&lt;p&gt;This can include smart search bars that understand user intent, chat assistants for customer support, AI-generated content such as product descriptions, or personalized dashboards that adapt to user behavior. Implementing these features typically involves connecting the frontend to an LLM API and building intuitive interfaces around the responses.&lt;br&gt;
Best Practices&lt;/p&gt;
&lt;p&gt;While the benefits are clear, it’s important to use LLMs responsibly. Generated code should always be reviewed for accuracy, security, and maintainability. LLMs should be seen as accelerators rather than replacements—tools that help you focus on creativity and architecture rather than boilerplate.&lt;/p&gt;
&lt;p&gt;When integrating LLMs directly into applications, developers must also consider the trade-offs of cost, latency, and privacy. A well-designed implementation balances these factors while still delivering value to the end user.&lt;br&gt;
Conclusion&lt;/p&gt;
&lt;p&gt;Large Language Models are quickly becoming part of the frontend developer’s toolkit. They help cut development time, improve code quality, and unlock new possibilities for user experience. More importantly, they allow developers to focus on solving meaningful problems rather than getting stuck on repetitive tasks.&lt;/p&gt;
&lt;p&gt;The future of frontend development isn’t just about writing code faster—it’s about building smarter, more adaptive, and more user-centered applications. LLMs are not here to replace frontend developers, but to amplify their skills and open up new ways of thinking about how we design and build the web.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11778/boosting-frontend-productivity-with-large-language-models</guid>
<pubDate>Mon, 16 Feb 2026 15:35:31 +0000</pubDate>
</item>
<item>
<title>Setting Up a Frontend Build for HTML Email Templating with MJML</title>
<link>https://coderlegion.com/8585/setting-up-a-frontend-build-for-html-email-templating-with-mjml</link>
<description>&lt;p&gt;In this article, we'll break down two key stages: first, we'll create a repository for email templating, and then we'll configure local test sending via SMTP.&lt;/p&gt;
&lt;p&gt;Why go through all this?&lt;/p&gt;
&lt;p&gt;On one of our projects, we actively use HTML emails. Initially, templates were placed directly in the backend microservices - scattered and with repetitive parts. This created difficulties in maintenance and email testing. We wanted to simplify the development process, and most importantly - make email templating and checking convenient.&lt;/p&gt;
&lt;p&gt;And as we know, email templating is painful. It's like you're developing for Internet Explorer - if you even remember what that is.&lt;/p&gt;
&lt;h3 id=&quot;moving-emails-to-a-separate-repository&quot;&gt;Moving Emails to a Separate Repository&lt;/h3&gt;
&lt;p&gt;We decided to create a separate repository where all email templates would be stored. The backend would be able to pull them centrally.&lt;/p&gt;
&lt;p&gt;The next step was choosing tools for templating and testing. We considered:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MJML&lt;/li&gt;
&lt;li&gt;Maizzle&lt;/li&gt;
&lt;li&gt;Foundation HTML&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We wanted to write in a higher-level language, using pre-built components. With Maizzle and Foundation HTML, it seemed like we'd have to write more raw HTML code.&lt;/p&gt;
&lt;p&gt;In the end, we settled on MJML - a markup language for email templates that compiles into full-fledged HTML, adapted for the specifics of email clients.&lt;/p&gt;
&lt;h3 id=&quot;what-is-mjml-and-why-is-it-convenient-&quot;&gt;What is MJML and Why is it Convenient?&lt;/h3&gt;
&lt;p&gt;MJML is a language designed for HTML email templating, which compiles into regular HTML. This means you can write in an abstract syntax that then turns into HTML code with support for different mail clients. This eases adaptation for various mail clients and gives the ability to use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;responsive templating;&lt;/li&gt;
&lt;li&gt;pre-built components;&lt;/li&gt;
&lt;li&gt;code reuse with mj-include.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can see how MJML code turns into HTML &lt;a rel=&quot;nofollow&quot; href=&quot;https://mjml.io/try-it-live&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;basic-project-setup&quot;&gt;Basic Project Setup&lt;/h3&gt;
&lt;p&gt;Let's go through the basic project setup - without delving into MJML syntax.&lt;/p&gt;
&lt;p&gt;Install dependencies:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install mjml live-server concurrently
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What each one does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mjml&lt;/code&gt; - compilation MJML → HTML&lt;/li&gt;
&lt;li&gt;&lt;code&gt;live-server&lt;/code&gt; - starting a dev server with live reload (you can use any&lt;br&gt;
server)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;concurrently&lt;/code&gt; - running commands in parallel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;configuring-package-json&quot;&gt;Configuring package.json&lt;/h3&gt;
&lt;p&gt;Add to &lt;code&gt;scripts&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;scripts&quot;: {
  &quot;start&quot;: &quot;mjml --watch ./src/templates/**/*.mjml --output ./templates&quot;,
  &quot;server&quot;: &quot;live-server --host=localhost --watch=templates --open=templates --ignorePattern=\&quot;.*.mjml\&quot;&quot;,
  &quot;dev&quot;: &quot;concurrently \&quot;npm run start\&quot; \&quot;npm run server\&quot;&quot;,
  &quot;build&quot;: &quot;mjml ./src/templates/**/*.mjml --output ./templates&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What each command does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;start&lt;/code&gt;&lt;/strong&gt; - watches &lt;code&gt;*.mjm&lt;/code&gt;l files in &lt;code&gt;src/templates/&lt;/code&gt;, compiles them to &lt;code&gt;./templates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;server&lt;/code&gt;&lt;/strong&gt; - starts a server and tracks changes in &lt;code&gt;./templates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;dev&lt;/code&gt;&lt;/strong&gt; - runs &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;server&lt;/code&gt; in parallel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;build&lt;/code&gt;&lt;/strong&gt; - one-time template compilation without a watcher&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;creating-the-first-template&quot;&gt;Creating the First Template&lt;/h3&gt;
&lt;p&gt;Create a file &lt;code&gt;example.mjml&lt;/code&gt; at &lt;code&gt;/src/templates/example.mjml&lt;/code&gt;. All templates will be in the &lt;code&gt;/src/templates&lt;/code&gt; folder. Add the following code to the file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;mjml&amp;gt;
  &amp;lt;mj-body background-color=&quot;#f5f5f5&quot;&amp;gt;
    &amp;lt;mj-section padding=&quot;40px 0 20px&quot;&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-text align=&quot;center&quot; font-size=&quot;28px&quot; font-weight=&quot;bold&quot;&amp;gt;Email built with MJML&amp;lt;/mj-text&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
    &amp;lt;mj-section background-color=&quot;#ffffff&quot;&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-image src=&quot;https://placehold.jp/300x200.png&quot; /&amp;gt;
      &amp;lt;/mj-column&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-text font-size=&quot;18px&quot; font-weight=&quot;bold&quot;&amp;gt;Hello, world!&amp;lt;/mj-text&amp;gt;
        &amp;lt;mj-text&amp;gt;This email was sent using MJML.&amp;lt;/mj-text&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
    &amp;lt;mj-section&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-button href=&quot;#&quot; background-color=&quot;#4CAF50&quot;&amp;gt;Subscribe&amp;lt;/mj-button&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
  &amp;lt;/mj-body&amp;gt;
&amp;lt;/mjml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;npm run dev&lt;/code&gt; - and a browser will open with the HTML generated from MJML. Each time the template changes, the page will automatically update. It's also useful to create a &lt;code&gt;./src/parts&lt;/code&gt; folder for reusable layout components.&lt;/p&gt;
&lt;p&gt;As a result, we'll get desktop and mobile versions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=3147744939798681032&quot; alt=&quot;Desktop version&quot;&gt;&lt;br&gt;
&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=10103968853670003385&quot; alt=&quot;Mobile version&quot;&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;./src/parts&lt;/code&gt; folder, create reusable email parts:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;./src/parts/global-settings.mjml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;mj-style inline=&quot;inline&quot;&amp;gt;
  body { background-color: #f0f4f6; font-family: Arial, sans-serif; }
  a { color: #1d5cdb; text-decoration: none; }
&amp;lt;/mj-style&amp;gt;
&amp;lt;mj-attributes&amp;gt;
  &amp;lt;mj-text
    font-size=&quot;17px&quot;
    line-height=&quot;24px&quot;
    color=&quot;#000&quot;
    padding-top=&quot;5px&quot;
    padding-bottom=&quot;5px&quot;
  /&amp;gt;
&amp;lt;/mj-attributes&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;./src/parts/header.mjml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;mj-section&amp;gt;
  &amp;lt;mj-column&amp;gt;
    &amp;lt;mj-image
      src=&quot;https://placehold.jp/82x47.png&quot;
      alt=&quot;Logo&quot;
      width=&quot;82px&quot;
      height=&quot;47px&quot;
    /&amp;gt;
  &amp;lt;/mj-column&amp;gt;
&amp;lt;/mj-section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let's include them in &lt;code&gt;example.mjml&lt;/code&gt; and remove unnecessary styles:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;mjml&amp;gt;
  &amp;lt;mj-head&amp;gt;
    &amp;lt;mj-include path=&quot;../parts/global-settings.mjml&quot; /&amp;gt;
    &amp;lt;mj-title&amp;gt;Example&amp;lt;/mj-title&amp;gt;
  &amp;lt;/mj-head&amp;gt;
  &amp;lt;mj-body&amp;gt;
    &amp;lt;mj-include path=&quot;../parts/header.mjml&quot; /&amp;gt;
    &amp;lt;mj-section padding=&quot;40px 0 20px&quot;&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-text align=&quot;center&quot; font-size=&quot;28px&quot; font-weight=&quot;bold&quot;&amp;gt;Email built with MJML&amp;lt;/mj-text&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
    &amp;lt;mj-section background-color=&quot;#ffffff&quot;&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-image src=&quot;https://placehold.jp/300x200.png&quot; /&amp;gt;
      &amp;lt;/mj-column&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-text font-size=&quot;18px&quot; font-weight=&quot;bold&quot;&amp;gt;Hello, world!&amp;lt;/mj-text&amp;gt;
        &amp;lt;mj-text&amp;gt;This email was sent using MJML.&amp;lt;/mj-text&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
    &amp;lt;mj-section&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-button href=&quot;#&quot; background-color=&quot;#4CAF50&quot;&amp;gt;Subscribe&amp;lt;/mj-button&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
  &amp;lt;/mj-body&amp;gt;
&amp;lt;/mjml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We get the result:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=9133145016542465759&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In summary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can globally set common styles and settings for components using&lt;br&gt;
global-settings.&lt;/li&gt;
&lt;li&gt;We can similarly extract code parts, as done with header.&lt;/li&gt;
&lt;li&gt;We develop and see changes in the browser in real-time thanks to the configured dev server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;using-templates-on-the-backend-go-&quot;&gt;Using Templates on the Backend (Go)&lt;/h3&gt;
&lt;p&gt;Our project backend is written in Go. The compiled email templates end up in the &lt;code&gt;./templates&lt;/code&gt; folder. From there, the backend can pull them and send emails. In our case, connecting templates looks like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the project root - &lt;code&gt;go.mod&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt; module gitlab.site.ru/front-html-email-templates&lt;/p&gt;
&lt;p&gt; go 1.22.0&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;code&gt;./templates/templates.go&lt;/code&gt;&lt;/p&gt;
&lt;p&gt; package templates&lt;/p&gt;
&lt;p&gt; import _ &quot;embed&quot;&lt;/p&gt;
&lt;p&gt; //go:embed example.html&lt;/p&gt;
&lt;p&gt; var Example string&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When adding a new template, a similar variable needs to be added to &lt;code&gt;templates.go&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Also, emails have variables that the backend substitutes using its templating engine. In our case, the syntax for variables is &lt;code&gt;{{.variableName}}&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;mjml&amp;gt;
  &amp;lt;mj-body&amp;gt;
    &amp;lt;mj-section padding=&quot;40px 0 20px&quot;&amp;gt;
      &amp;lt;mj-column&amp;gt;
        &amp;lt;mj-text align=&quot;center&quot; font-size=&quot;28px&quot; font-weight=&quot;bold&quot;&amp;gt;{{.title}}&amp;lt;/mj-text&amp;gt;
      &amp;lt;/mj-column&amp;gt;
    &amp;lt;/mj-section&amp;gt;
  &amp;lt;/mj-body&amp;gt;
&amp;lt;/mjml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To understand what variables are needed in a template, we created a &lt;code&gt;./docs/templates&lt;/code&gt; folder where we store markdown files with the same name as the template and a description of which variables are used, for example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## Candidate

Email template 'Application without a vacancy'

### Variables
- `{{.date}}` Application Date
- `{{.title}}` Vacancy Title
- `{{.region}}` Region
- `{{.name}}` Full Name
- `{{.phone}}` Phone
- `{{.email}}` Email
- `{{.comment}}` Comment
- `{{.resume_link}}` Resume Link
- `{{.year}}` Current Year
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The variables themselves can be added to the files by the backend developer, and the frontend developer just needs to place them in the layout in the correct spots.&lt;/p&gt;
&lt;h3 id=&quot;local-smtp-testing&quot;&gt;Local SMTP Testing&lt;/h3&gt;
&lt;p&gt;Let's write a simple JS script that will send our templates to a real email.&lt;/p&gt;
&lt;p&gt;First, install the following packages:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install dotenv nodemailer
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dotenv&lt;/code&gt; — package for loading .env files in JS;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;nodemailer&lt;/code&gt; — package for sending emails with SMTP support.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that, create a file &lt;code&gt;./send-test-email.js&lt;/code&gt; and add the code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import nodemailer from 'nodemailer'
import dotenv from 'dotenv'
import fs from 'fs/promises'

dotenv.config()

async function sendTestEmail() {
  const transporter = nodemailer.createTransport({
    host: process.env.SMTP_HOST,
    port: process.env.SMTP_PORT,
    secure: true, // true for port 587, false for other ports
    auth: {
      user: process.env.SEND_FROM_EMAIL,
      pass: process.env.SEND_FROM_EMAIL_PASSWORD,
    },
  })gmail.com

  const htmlEmailString = await fs.readFile(
    `./templates/${process.env.TEMPLATE_NAME}.html`,
    'utf-8'
  )

  const mailOptions = {
    from: `Test Sender &amp;lt;${process.env.SEND_FROM_EMAIL}&amp;gt;`,
    to: process.env.SEND_TO_EMAIL,
    subject: 'Test HTML Email',
    html: htmlEmailString,
  }

  const info = await transporter.sendMail(mailOptions)
  console.log('Message sent: %s', info.messageId)
}

sendTestEmail().catch(console.error)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a simple implementation for sending emails via SMTP. We also need to create a .env file with the necessary variables:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;TEMPLATE_NAME=email-confirmation
SEND_TO_EMAIL=*Emails are not allowed*
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SEND_FROM_EMAIL=*Emails are not allowed*
SEND_FROM_EMAIL_PASSWORD=BcsftTdfdsf
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TEMPLATE_NAME&lt;/code&gt; - the name of the template to be sent;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SEND_TO_EMAIL&lt;/code&gt; - where the email will be sent;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMTP_HOST&lt;/code&gt; - SMTP host;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMTP_PORT&lt;/code&gt; - port;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SEND_FROM_EMAIL&lt;/code&gt; - the sender's email address.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SEND_FROM_EMAIL_PASSWORD&lt;/code&gt; - the sender's email password.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Primarily, the &lt;code&gt;TEMPLATE_NAME&lt;/code&gt; and &lt;code&gt;SEND_TO_EMAIL&lt;/code&gt; variables change. For testing different templates and different mail clients.The other variables only need to be configured once.&lt;/p&gt;
&lt;p&gt;After all the setup, to send an email, you need to run the script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;node ./send-test-email.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For convenience, you can add a script to package.json. You can also implement support for bulk sending a template to different mail clients.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;The current concept can be applied with other tools as well. As a result, we have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a centralized repository for HTML emails;&lt;/li&gt;
&lt;li&gt;email templating with best practices and reusable parts;&lt;/li&gt;
&lt;li&gt;local SMTP testing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's important to keep in mind that templating can still break in old Outlook clients and with solutions like MJML where standard templates are provided. Even using best practices doesn't completely solve this issue. To avoid &quot;breaking&quot; in old solutions, you can use very trivial layout: simple texts and headings, no styling or visual elements. &lt;/p&gt;
&lt;p&gt;&lt;em&gt;Author: Dmitry Berdnikov&lt;/em&gt;&lt;/p&gt;
</description>
<category>Frontend Dev</category>
<guid isPermaLink="true">https://coderlegion.com/8585/setting-up-a-frontend-build-for-html-email-templating-with-mjml</guid>
<pubDate>Thu, 18 Dec 2025 10:17:17 +0000</pubDate>
</item>
<item>
<title>Architecture Pattern: &quot;Compound Components&quot; and Advanced Projection with `ngProjectAs`</title>
<link>https://coderlegion.com/7975/architecture-pattern-compound-components-and-advanced-projection-with-ngprojectas</link>
<description>&lt;p&gt;When building a Design System or a library of shared components, the most difficult challenge is &lt;strong&gt;balancing consistency with flexibility.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You want all your Modals to look the same (consistency), but some Modals contain forms, others contain text, and others contain complex grids (flexibility).&lt;/p&gt;
&lt;p&gt;The Architectural Pattern that solves this is &lt;strong&gt;Content Projection&lt;/strong&gt; (specifically Multi-Slot Projection).&lt;/p&gt;
&lt;h4 id=&quot;the-basics-the-select-api&quot;&gt;The Basics: The &quot;Select&quot; API&lt;/h4&gt;
&lt;p&gt;When you build a container, you define its API not by Inputs, but by &lt;strong&gt;Slots&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;@Component({
  selector: 'app-layout',
  template: `
    &amp;lt;header&amp;gt;
      &amp;lt;ng-content select=&quot;nav&quot;&amp;gt;&amp;lt;/ng-content&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;main&amp;gt;
      &amp;lt;ng-content&amp;gt;&amp;lt;/ng-content&amp;gt;
    &amp;lt;/main&amp;gt;
  `
})
export class AppLayoutComponent {}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;the-senior-gotcha-wrapper-elements&quot;&gt;The Senior &quot;Gotcha&quot;: Wrapper Elements&lt;/h4&gt;
&lt;p&gt;Here is a problem 99% of devs hit.&lt;/p&gt;
&lt;p&gt;Imagine your &lt;code&gt;app-layout&lt;/code&gt; expects a &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; tag because of &lt;code&gt;select=&quot;nav&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But you want to project a custom component called &lt;code&gt;&amp;lt;app-top-bar&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;app-layout&amp;gt;
  &amp;lt;app-top-bar&amp;gt;&amp;lt;/app-top-bar&amp;gt;
&amp;lt;/app-layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your &lt;code&gt;app-top-bar&lt;/code&gt; will fall into the &lt;em&gt;default&lt;/em&gt; slot (Main), not the Header slot.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Junior Fix:&lt;/strong&gt;&lt;br&gt;
Wrap it in a nav tag.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;app-layout&amp;gt;
  &amp;lt;nav&amp;gt; &amp;lt;app-top-bar&amp;gt;&amp;lt;/app-top-bar&amp;gt;
  &amp;lt;/nav&amp;gt;
&amp;lt;/app-layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Problem:&lt;/em&gt; You just introduced an extra DOM node (&lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;) that might mess up your Flexbox or Grid layout.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Senior Fix: &lt;code&gt;ngProjectAs&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Angular has a special attribute that allows you to &quot;disguise&quot; an element so it matches a specific selector, without adding extra DOM nodes.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;app-layout&amp;gt;
  &amp;lt;app-top-bar ngProjectAs=&quot;nav&quot;&amp;gt;&amp;lt;/app-top-bar&amp;gt;
&amp;lt;/app-layout&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells Angular: &quot;Treat this component as if it were a &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; tag for the purposes of projection.&quot;&lt;/p&gt;
&lt;h4 id=&quot;the-projected-content-lifecycle-risk&quot;&gt;The &quot;Projected Content&quot; Lifecycle Risk&lt;/h4&gt;
&lt;p&gt;As a Senior Developer, you need to know the performance cost.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Projected content is instantiated EAGERLY.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you project a heavy component:&lt;br&gt;
&lt;code&gt;&amp;lt;app-modal&amp;gt;&amp;lt;app-heavy-chart&amp;gt;&amp;lt;/app-heavy-chart&amp;gt;&amp;lt;/app-modal&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;app-heavy-chart&lt;/code&gt; is created, its &lt;code&gt;constructor&lt;/code&gt; runs, and its &lt;code&gt;ngOnInit&lt;/code&gt; runs &lt;strong&gt;immediately&lt;/strong&gt;, even if the modal is hidden via &lt;code&gt;display: none&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Optimization:&lt;/strong&gt;&lt;br&gt;
If the content is extremely heavy, do not use basic Content Projection. Use &lt;strong&gt;Template Projection&lt;/strong&gt; (&lt;code&gt;ng-template&lt;/code&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;app-modal [contentTemplate]=&quot;myChart&quot;&amp;gt;&amp;lt;/app-modal&amp;gt;

&amp;lt;ng-template #myChart&amp;gt;
  &amp;lt;app-heavy-chart&amp;gt;&amp;lt;/app-heavy-chart&amp;gt;
&amp;lt;/ng-template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// Child (Modal)
@Input() contentTemplate: TemplateRef&amp;lt;any&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;ng-container *ngTemplateOutlet=&quot;contentTemplate&quot;&amp;gt;&amp;lt;/ng-container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This ensures the chart is not instantiated until the Modal actually renders the template outlet.&lt;/p&gt;
&lt;p&gt;Mastering these nuances—&lt;code&gt;ngProjectAs&lt;/code&gt; and &lt;code&gt;TemplateRef&lt;/code&gt;—is what separates a component library author from a component user.&lt;/p&gt;
</description>
<category>Components</category>
<guid isPermaLink="true">https://coderlegion.com/7975/architecture-pattern-compound-components-and-advanced-projection-with-ngprojectas</guid>
<pubDate>Sat, 29 Nov 2025 17:37:29 +0000</pubDate>
</item>
<item>
<title>Deep Dive: Solving Race Conditions and Concurrency with RxJS Operators</title>
<link>https://coderlegion.com/7766/deep-dive-solving-race-conditions-and-concurrency-with-rxjs-operators</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=6157093721072778817&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Race conditions are the nightmares of frontend development. They happen when your code assumes that network request A will finish before network request B, but the internet decides otherwise.&lt;/p&gt;
&lt;p&gt;In React or Vue (without RxJS), managing complex concurrency often requires boolean flags (&lt;code&gt;isLoading&lt;/code&gt;), timestamp checks, or &lt;code&gt;AbortControllers&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Angular, we solve this elegantly with &lt;strong&gt;RxJS Mapping Operators&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But RxJS gives us four different tools: &lt;code&gt;mergeMap&lt;/code&gt;, &lt;code&gt;switchMap&lt;/code&gt;, &lt;code&gt;concatMap&lt;/code&gt;, and &lt;code&gt;exhaustMap&lt;/code&gt;. Choosing the wrong one isn't just a style choice; it determines whether your app creates bugs or prevents them.&lt;/p&gt;
&lt;p&gt;Let's break down exactly which concurrency strategy each operator uses.&lt;/p&gt;
&lt;h4 id=&quot;1-switchmap-the-latest-and-greatest-fixing-read-races-&quot;&gt;1. &lt;code&gt;switchMap&lt;/code&gt;: The &quot;Latest and Greatest&quot; (Fixing Read Races)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The Strategy:&lt;/strong&gt; &lt;em&gt;Cancel the previous request if a new one arrives.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
Imagine a user is on a &quot;User Details&quot; page.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;They click &quot;User A&quot;. (Request A starts - Slow Network).&lt;/li&gt;
&lt;li&gt;They get bored and click &quot;User B&quot; immediately. (Request B starts - Fast Network).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;The Bug (without switchMap):&lt;/strong&gt;&lt;br&gt;
Request B finishes first and shows User B. Then, Request A finishes and &lt;em&gt;overwrites&lt;/em&gt; the screen with User A. The URL says &quot;User B&quot;, but the screen shows &quot;User A&quot;. This is a dirty UI state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;this.route.params.pipe(
  // When params change, cancel any pending request!
  switchMap(params =&amp;gt; this.userService.getUser(params.id))
).subscribe(user =&amp;gt; {
  // We are GUARANTEED that 'user' matches the current URL.
  this.displayUser(user);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Best For:&lt;/strong&gt; GET requests (Search, Route Params, Filters).&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;2-concatmap-the-single-file-line-fixing-write-races-&quot;&gt;2. &lt;code&gt;concatMap&lt;/code&gt;: The &quot;Single File Line&quot; (Fixing Write Races)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The Strategy:&lt;/strong&gt; &lt;em&gt;Wait for the current request to finish before starting the next.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
An &quot;Auto-Save&quot; feature in a text editor.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;User types &quot;Hello&quot;. (Request A sent).&lt;/li&gt;
&lt;li&gt;User immediately types &quot; World&quot;. (Request B sent).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;The Bug (with switchMap):&lt;/strong&gt;&lt;br&gt;
If you used &lt;code&gt;switchMap&lt;/code&gt;, Request B would cancel Request A. The server only receives &quot; World&quot;. The word &quot;Hello&quot; is lost forever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt;&lt;br&gt;
We need a Queue. Request B must wait in line.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;this.textInput.valueChanges.pipe(
  // Queue the requests. Request B waits for Request A to complete.
  concatMap(text =&amp;gt; this.api.saveDraft(text))
).subscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Best For:&lt;/strong&gt; PUT/POST requests where &lt;strong&gt;order matters&lt;/strong&gt; (Auto-saves, sequential steps).&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;3-mergemap-the-free-for-all-parallel-execution-&quot;&gt;3. &lt;code&gt;mergeMap&lt;/code&gt;: The &quot;Free-for-All&quot; (Parallel Execution)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The Strategy:&lt;/strong&gt; &lt;em&gt;Run everything immediately. I don't care about order.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
A &quot;Bulk Delete&quot; feature. The user selects 5 items from a list and clicks &quot;Delete Selected&quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Strategy:&lt;/strong&gt;&lt;br&gt;
We don't want to wait for Item 1 to delete before starting Item 2 (too slow). And we certainly don't want to cancel Item 1 if Item 2 starts (bug). We want them all to fly to the server at once.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;const idsToDelete = [1, 2, 3, 4, 5];

from(idsToDelete).pipe(
  // Fire 5 network requests in parallel
  mergeMap(id =&amp;gt; this.api.deleteItem(id))
).subscribe(deletedId =&amp;gt; {
  console.log(`Deleted ${deletedId}`);
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Best For:&lt;/strong&gt; DELETE requests or fetching unrelated data (e.g., getting Widget A and Widget B at the same time).&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;4-exhaustmap-the-do-not-disturb-spam-prevention-&quot;&gt;4. &lt;code&gt;exhaustMap&lt;/code&gt;: The &quot;Do Not Disturb&quot; (Spam Prevention)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;The Strategy:&lt;/strong&gt; &lt;em&gt;Ignore new requests while I am busy.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;br&gt;
A &quot;Pay Now&quot; button or a Login form.&lt;br&gt;
A nervous user clicks the button 10 times in one second because the spinner didn't appear instantly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Bug (with mergeMap):&lt;/strong&gt;&lt;br&gt;
You charge the user's credit card 10 times.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Bug (with switchMap):&lt;/strong&gt;&lt;br&gt;
You cancel the payment 9 times, and only the 10th one works (maybe).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt;&lt;br&gt;
We want to completely ignore clicks 2 through 10.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;fromEvent(this.payButton, 'click').pipe(
  // If a payment is processing, IGNORE this click.
  exhaustMap(() =&amp;gt; this.paymentService.chargeCard())
).subscribe();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Best For:&lt;/strong&gt; Non-idempotent POST requests (Login, Payment, Submit).&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;summary-cheat-sheet&quot;&gt;Summary Cheat Sheet&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Operator &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Concurrency Strategy &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Ideal Use Case&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;switchMap&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Kill the previous &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Reads (Search, Routing)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;concatMap&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Wait in line &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Ordered Writes (Save)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;mergeMap&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Run in parallel &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Parallel Writes (Delete)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;exhaustMap&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Ignore the new &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Submit Buttons (Auth)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;RxJS operators are tools for managing &lt;strong&gt;time&lt;/strong&gt;. Master these four, and you master concurrency.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7766/deep-dive-solving-race-conditions-and-concurrency-with-rxjs-operators</guid>
<pubDate>Tue, 25 Nov 2025 05:39:27 +0000</pubDate>
</item>
<item>
<title>The Complete Guide to Angular Subscriptions: Template vs. Component Logic</title>
<link>https://coderlegion.com/7552/the-complete-guide-to-angular-subscriptions-template-vs-component-logic</link>
<description>&lt;p&gt;Every Angular developer eventually faces the dilemma: &lt;em&gt;How do I get my data out of the Observable?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There are two correct answers, and they serve different purposes. Let's look at the code for both.&lt;/p&gt;
&lt;h4 id=&quot;scenario-1-pure-display-the-happy-path-&quot;&gt;Scenario 1: Pure Display (The Happy Path)&lt;/h4&gt;
&lt;p&gt;If your data is just going onto the screen, use the &lt;strong&gt;Async Pipe&lt;/strong&gt;. It is Declarative, meaning you describe &lt;em&gt;what&lt;/em&gt; you want (the stream value), not &lt;em&gt;how&lt;/em&gt; to get it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// component.ts
data$ = this.service.getData(); // No subscription here!
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;p&amp;gt;{{ data$ | async }}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Verdict:&lt;/strong&gt; Use this 90% of the time. It prevents memory leaks automatically.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;scenario-2-component-logic-the-necessary-evil-&quot;&gt;Scenario 2: Component Logic (The Necessary Evil)&lt;/h4&gt;
&lt;p&gt;Sometimes, the Async Pipe isn't enough. You might need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Filter data based on local state.&lt;/li&gt;
&lt;li&gt;Trigger a side effect (like a Toast notification).&lt;/li&gt;
&lt;li&gt;Patch a Form Control value.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here, you must subscribe. And to avoid Zombie Components (listeners that stay alive after the component dies), you need the &lt;code&gt;takeUntil&lt;/code&gt; pattern.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Code:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;export class MyComponent implements OnDestroy {
  private destroy$ = new Subject&amp;lt;void&amp;gt;();

  ngOnInit(): void {
    this.dataService.getData()
      .pipe(takeUntil(this.destroy$)) // Use takeUntil with the destroy$ subject
      .subscribe(response =&amp;gt; {
        this.data = response;
        this.form.patchValue(response); // Specific logic!
      });
  }

  ngOnDestroy(): void {
    this.destroy$.next(); // Emit a value to signal completion
    this.destroy$.complete(); // Complete the subject
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt;&lt;br&gt;
Don't be afraid of manual subscriptions, but respect them. They require explicit cleanup logic. If you can avoid them by using &lt;code&gt;| async&lt;/code&gt;, do it. If not, use &lt;code&gt;takeUntil&lt;/code&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/7552/the-complete-guide-to-angular-subscriptions-template-vs-component-logic</guid>
<pubDate>Wed, 19 Nov 2025 18:25:11 +0000</pubDate>
</item>
<item>
<title>The Indispensable Practice of Abstraction: Decoupling Your Frontend Logic from External Libraries</title>
<link>https://coderlegion.com/6656/indispensable-practice-abstraction-decoupling-your-frontend-logic-external-libraries</link>
<description>&lt;p&gt;In modern frontend architecture, the principle of &lt;strong&gt;separation of concerns&lt;/strong&gt; is paramount. Your application's core logic (business rules, state, and UI) must be entirely isolated from the specific Application Programming Interfaces (APIs) of third-party libraries. This best practice, known as creating an &lt;strong&gt;Anti-Corruption Layer (ACL)&lt;/strong&gt;, is the difference between a flexible, maintainable codebase and a fragile, tightly coupled one.&lt;/p&gt;
&lt;h3 id=&quot;the-problem-tight-coupling-and-vendor-lock-in&quot;&gt;The Problem: Tight Coupling and Vendor Lock-in&lt;/h3&gt;
&lt;p&gt;When you directly integrate a library's specific methods into your components, you create a dependency that is rigid and difficult to change. For instance, directly using &lt;code&gt;window.Stripe.redirectToCheckout()&lt;/code&gt; in a checkout button component couples your UI directly to the &lt;strong&gt;Stripe SDK&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;the-core-risks-&quot;&gt;The Core Risks:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Vendor Lock-in:&lt;/strong&gt; You are locked into a specific vendor (e.g., Supabase, Auth0, Stripe). If a better, cheaper, or more performant alternative emerges, changing libraries means a massive, error-prone refactor across your entire application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Difficult Testing:&lt;/strong&gt; Unit testing a component that directly calls an external SDK requires complex mocking of that entire library's API, cluttering your test setup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inconsistent Code:&lt;/strong&gt; Error handling, data formatting, and asynchronous logic become inconsistent when repeated across many components.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;the-solution-the-abstraction-layer&quot;&gt;The Solution: The Abstraction Layer&lt;/h3&gt;
&lt;p&gt;The solution is an intermediate layer—a &lt;strong&gt;Service&lt;/strong&gt;, &lt;strong&gt;Repository&lt;/strong&gt;, or &lt;strong&gt;Utility&lt;/strong&gt; module—that acts as the single point of entry for all library interactions.&lt;/p&gt;
&lt;h4 id=&quot;how-abstraction-works-&quot;&gt;How Abstraction Works:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Generic Interface:&lt;/strong&gt; Define functions using &lt;strong&gt;domain language&lt;/strong&gt; (e.g., &lt;code&gt;getProducts&lt;/code&gt;, &lt;code&gt;processPayment&lt;/code&gt;) that describe &lt;em&gt;what&lt;/em&gt; your app needs to do, not &lt;em&gt;how&lt;/em&gt; it's done.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encapsulation:&lt;/strong&gt; All library-specific imports and calls are &lt;em&gt;encapsulated&lt;/em&gt; within this single module.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Standardization:&lt;/strong&gt; The layer is responsible for translating the external library's quirky response formats and error structures into the simple, predictable formats your application expects.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-abstracting-data-access-the-repository-pattern-&quot;&gt;1. Abstracting Data Access (The Repository Pattern)&lt;/h3&gt;
&lt;p&gt;This is the most critical area for separation. We &lt;strong&gt;separate the database library (like Supabase) from the code itself&lt;/strong&gt; by creating a &lt;strong&gt;Service&lt;/strong&gt; or &lt;strong&gt;Repository&lt;/strong&gt; layer with &lt;strong&gt;generic names&lt;/strong&gt;.&lt;/p&gt;
&lt;h4 id=&quot;example-decoupling-data-fetching-supabase-vs-custom-rest-api-&quot;&gt;Example: Decoupling Data Fetching (Supabase vs. Custom REST API)&lt;/h4&gt;
&lt;p&gt;Let's assume our application needs to fetch product data.&lt;/p&gt;
&lt;h5 id=&quot;tightly-coupled-bad-&quot;&gt;&lt;strong&gt;Tightly Coupled (Bad)&lt;/strong&gt;&lt;/h5&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// src/components/ProductList.jsx

import { supabase } from '../lib/supabaseClient'; // Directly importing the library

const fetchProducts = async () =&amp;gt; {
  // Hard dependency on Supabase API structure (from, select, etc.)
  const { data: products, error } = await supabase.from('products').select(`
    id,
    name,
    price_cents,
    inventory:product_inventory(stock_count)
  `);

  if (error) throw new Error(error.message);

  // Data requires complex, specific formatting here
  return products.map(p =&amp;gt; ({
      ...p,
      price: p.price_cents / 100,
      stock: p.inventory[0]?.stock_count || 0
  }));
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id=&quot;decoupled-good-with-a-service&quot;&gt;&lt;strong&gt;Decoupled (Good) with a Service&lt;/strong&gt;&lt;/h5&gt;
&lt;p&gt;First, the abstraction layer handles the library call and data standardization:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// src/services/productService.js (The Abstraction Layer)

import { supabase } from '../lib/supabaseClient'; // Encapsulates the library dependency

// Defines a predictable structure for the rest of the application
const formatProduct = (productData) =&amp;gt; ({
    id: productData.id,
    name: productData.name,
    price: productData.price_cents / 100, // Standardize cents to dollars
    stock: productData.product_inventory[0]?.stock_count || 0,
});

export const productService = {
  // Generic function name: getProducts
  getProducts: async () =&amp;gt; {
    // 1. Library-specific call is confined here
    const { data, error } = await supabase.from('products').select(`
      id,
      name,
      price_cents,
      product_inventory(stock_count)
    `);

    if (error) {
      // 2. Standardize error handling
      throw new Error(&quot;Failed to retrieve products from data source.&quot;);
    }
    // 3. Standardize and return clean, formatted data
    return data.map(formatProduct);
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Second, the component uses the clean interface:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// src/components/ProductList.jsx

import { productService } from '../services/productService'; // Generic interface

const fetchProducts = async () =&amp;gt; {
  // Clean, generic call. The component doesn't know (or care) about Supabase
  const products = await productService.getProducts();
  // ... use products
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;The Flexibility:&lt;/strong&gt; If you replace Supabase with a custom &lt;strong&gt;REST API&lt;/strong&gt; using &lt;strong&gt;Axios&lt;/strong&gt;, you only change &lt;code&gt;productService.js&lt;/code&gt;. The component code remains &lt;strong&gt;untouched&lt;/strong&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// src/services/productService.js (Rewritten for Custom REST API via Axios)

import axios from 'axios'; // Encapsulates the new dependency

// formatProduct function remains the same!

export const productService = {
  getProducts: async () =&amp;gt; {
    try {
      // New library-specific call
      const response = await axios.get('/api/v1/products');
      // Assume the API returns raw data that still needs to be formatted
      return response.data.map(formatProduct);
    } catch (error) {
      throw new Error(&quot;Failed to retrieve products from REST API.&quot;);
    }
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-abstraction-for-all-external-dependencies&quot;&gt;2. Abstraction for All External Dependencies&lt;/h3&gt;
&lt;p&gt;This principle should be applied to every external dependency to ensure your application is &lt;strong&gt;future-proof&lt;/strong&gt; and &lt;strong&gt;agile&lt;/strong&gt; when a library becomes obsolete or unsuitable.&lt;/p&gt;
&lt;h4 id=&quot;a-payment-sdks-e-g-stripe-&quot;&gt;A. Payment SDKs (e.g., Stripe)&lt;/h4&gt;
&lt;p&gt;Your checkout flow must be protected from library changes.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Component's Need &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Tightly Coupled (Bad) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Decoupled (Good)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Payment:&lt;/strong&gt; Redirect to checkout screen. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Component calls: &lt;code&gt;window.Stripe.redirectToCheckout({ /*... config */ })&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Component calls: &lt;code&gt;paymentService.initiateCheckout(cartId)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Abstraction Layer:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;None &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;paymentService.js&lt;/code&gt; handles all Stripe SDK imports, configurations, and API calls.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Switching to PayPal or Square requires modifying every component that touches payment. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Only &lt;code&gt;paymentService.js&lt;/code&gt; needs to be rewritten. The &lt;code&gt;initiateCheckout&lt;/code&gt; function signature is preserved.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;b-internationalization-i18n-libraries-e-g-formatjs-vs-react-i18next-&quot;&gt;B. Internationalization (i18n) Libraries (e.g., FormatJS vs. react-i18next)&lt;/h4&gt;
&lt;p&gt;Components should only request a translated string using a generic key.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Component's Need &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Tightly Coupled (Bad) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Decoupled (Good)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Translation:&lt;/strong&gt; Get a welcome message. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Component uses: &lt;code&gt;const { formatMessage } = useIntl(); return formatMessage(messages.welcome)&lt;/code&gt; (FormatJS-specific) &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Component uses: &lt;code&gt;const { T } = useAppTranslation(); return T('welcome_message', { name: user.name })&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Abstraction Layer:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;None &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;useAppTranslation.js&lt;/code&gt; wraps the specific library's translation hook/functionality.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Switching to a different i18n library means changing hook imports and function names in every component. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Only the implementation inside &lt;code&gt;useAppTranslation.js&lt;/code&gt; changes, maintaining the generic &lt;code&gt;T&lt;/code&gt; interface.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;c-client-side-authentication-e-g-auth0-vs-firebase-auth-&quot;&gt;C. Client-Side Authentication (e.g., Auth0 vs. Firebase Auth)&lt;/h4&gt;
&lt;p&gt;Decoupling auth ensures your routing and UI logic are stable regardless of the provider.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Component's Need &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Tightly Coupled (Bad) &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Decoupled (Good)&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Auth Status:&lt;/strong&gt; Check if a user is logged in. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Router guard calls: &lt;code&gt;Auth0Client.isAuthenticated()&lt;/code&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Router guard calls: &lt;code&gt;authService.isLoggedIn()&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Abstraction Layer:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;None &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;code&gt;authService.js&lt;/code&gt; or &lt;code&gt;useAuth&lt;/code&gt; hook handles token storage, session checks, and specific library methods.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;If you migrate from Auth0 to Firebase Auth, you need to update logic everywhere Auth0's specific methods are called. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Only &lt;code&gt;authService.js&lt;/code&gt; is rewritten to use Firebase SDK methods, keeping the generic interface intact.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h3 id=&quot;key-takeaways-for-robust-frontend-architecture&quot;&gt;Key Takeaways for Robust Frontend Architecture&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th align=&quot;left&quot;&gt;Practice &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Principle &lt;/th&gt;&lt;th align=&quot;left&quot;&gt;Rationale&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Name Generically&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Domain Language Over Technology:&lt;/strong&gt; Use names like &lt;code&gt;userService&lt;/code&gt; or &lt;code&gt;paymentService&lt;/code&gt;, not &lt;code&gt;clerkAuthService&lt;/code&gt; or &lt;code&gt;supabasePosts&lt;/code&gt;. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The name reflects the &lt;em&gt;domain concept&lt;/em&gt;, not the &lt;em&gt;implementation detail&lt;/em&gt;.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Standardize Data&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;ACL Responsibility:&lt;/strong&gt; The service layer must convert the library's output (e.g., a complex object with metadata) into the exact clean object your app needs. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;The rest of your application code deals with a single, predictable data format.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Error Handling&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Translate Errors:&lt;/strong&gt; Catch library-specific errors and re-throw them as simple, standardized application-level errors (e.g., a &lt;code&gt;DataFetchError&lt;/code&gt;). &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Components only need to handle a few generic error types, simplifying UI feedback.&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Apply Universally&lt;/strong&gt; &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;Systematic Abstraction:&lt;/strong&gt; If you use a library, abstract it. This applies to data access, state management, auth, analytics, utility functions, and more. &lt;/td&gt;&lt;td align=&quot;left&quot;&gt;Maximizes code agility, testability, and reduces maintenance complexity across the board.&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;By committing to this principle of &lt;strong&gt;universal abstraction&lt;/strong&gt;, you build a frontend application that is architecturally sound, easier to test, and perfectly positioned to adapt to the technological shifts of tomorrow.&lt;/p&gt;
</description>
<category>Time Management</category>
<guid isPermaLink="true">https://coderlegion.com/6656/indispensable-practice-abstraction-decoupling-your-frontend-logic-external-libraries</guid>
<pubDate>Mon, 20 Oct 2025 11:14:55 +0000</pubDate>
</item>
<item>
<title>JavaScript: Array Iteration and DOM Manipulation in Game Development</title>
<link>https://coderlegion.com/6392/javascript-array-iteration-and-dom-manipulation-in-game-development</link>
<description>&lt;h5 id=&quot;this-article-explores-javascript-array-iteration-and-dom-manipulation-including-practical-game-development-examples-you-will-also-learn-a-game-state-sync-technique-to-enhance-your-own-projects-&quot;&gt;This article explores JavaScript array iteration and DOM manipulation, including practical game development examples. You will also learn a game-state sync technique to enhance your own projects!&lt;/h5&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1760124390275/2b9d0f10-5198-4e88-83aa-5f1babb8acb4.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;array-iteration&quot;&gt;Array Iteration&lt;/h4&gt;
&lt;p&gt;What is array iteration? Array iteration is the process of sequentially accessing each element in an array to perform operations or calculations. This technique is essential in JavaScript for efficiently managing and manipulating data stored in arrays, such as updating game states or displaying information.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In my JavaScript Pac-Man game, I store information in arrays and iterate through them for my game logic to carry out various tasks. For example, the fruit bonus that appears twice per level utilizes an emoji and a matching point value based on the level.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For a simple demonstration, the code block below shows an iteration over the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;fruitBonus&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;array: The console logs the corresponding emoji along with the point value stored in the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;fruitBonusValue&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;array.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Arrays store fruit icons and their bonus values for each level
export const fruitBonus = ['','','','','','','','','','',''];
export const fruitBonusValue = [100,300,500,500,700,700,1000,1000,2000,3000,5000];

// Example: Display all fruit bonuses and their values
for (let i = 0; i &amp;lt; fruitBonus.length; i++) {
  console.log(`Level ${i + 1}: ${fruitBonus[i]} = ${fruitBonusValue[i]} points`);
}

// Console log:
&quot;Level 1:  = 100 points&quot;
&quot;Level 2:  = 300 points&quot;
&quot;Level 3:  = 500 points&quot;
&quot;Level 4:  = 500 points&quot;
&quot;Level 5:  = 700 points&quot;
&quot;Level 6:  = 700 points&quot;
&quot;Level 7:  = 1000 points&quot;
&quot;Level 8:  = 1000 points&quot;
&quot;Level 9:  = 2000 points&quot;
&quot;Level 10:  = 3000 points&quot;
&quot;Level 11:  = 5000 points&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;(The actual game logic is more complex but follows the same iterative approach.)&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;array-iteration-and-dom-manipulation&quot;&gt;Array Iteration and DOM Manipulation&lt;/h4&gt;
&lt;p&gt;The Document Object Model (DOM) is a programming interface for web documents, representing the page structure as a tree of objects. With JavaScript, you can manipulate the DOM to dynamically alter a webpage's content, structure, and style, enabling you to build interactive and responsive user experiences.&lt;/p&gt;
&lt;p&gt;The main functionality of game level completion in my project is for Pac-Man to eat all the pellets on the game board. I initially handled this by checking if Pac-Man’s current index also had a CSS pellet class, using the JavaScript &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes&quot;&gt;includes method&lt;/a&gt;. However, this approach proved unreliable for tracking game progress. To solve this, I created a dedicated &lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/09-25/what-is-state-in-javascript-and-how-to-use-it-in-your-projects/&quot;&gt;pelletState&lt;/a&gt; array to track the state of each pellet throughout the game.&lt;/p&gt;
&lt;p&gt;Now with the &lt;strong&gt;pelletState&lt;/strong&gt; array, I can properly track the status of every pellet and power pellet on the board, regardless of visual glitches or overlapping game elements. This ensures that Pac-Man’s progress, level completion, and scoring are always accurate, and the game logic remains in sync with what the player sees.&lt;/p&gt;
&lt;p&gt;However, a new glitch emerged: ghosts occasionally removed CSS pellet classes while traversing through the gameboard, preventing level completion because the corresponding pellets remained in the &lt;strong&gt;pelletState&lt;/strong&gt; array. It was a pretty funny glitch because the ghosts would eventually return the pellets when they passed by the divs they took them from, as if they were cheating me out of finishing the level! &lt;/p&gt;
&lt;p&gt;&lt;em&gt;As part of my pelletState array solution, the CSS pellet classes are temporarily removed from a square when a ghost enters and restored when the ghost leaves. The pellet’s state, however, is always tracked in the array, ensuring consistent game logic regardless of visual changes. This approach is necessary due to CSS scaling; ghosts visually shrink to the size of the pellet when sharing a square, so managing the classes separately prevents display issues.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;syncing-game-state-and-dom-with-array-iteration&quot;&gt;Syncing Game State and DOM with Array Iteration&lt;/h4&gt;
&lt;p&gt;I created a &lt;code&gt;syncPelletClasses&lt;/code&gt; function to keep the &lt;strong&gt;pelletState&lt;/strong&gt; array and pellet CSS classes in sync, running it every time the board state changes. This function, syncPelletClasses(), iterates through the pelletState array and updates the DOM for each square: if a pellet or power pellet is present in the array and no ghost is on that square, the corresponding CSS class is added; if a ghost is present, the class is removed. This keeps the visuals accurate without affecting the underlying game logic.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;By separating the visual state (CSS classes) from the game state (the array), I ensured that pellets are never “lost” due to ghost movement or display quirks. Pac-Man’s progress and level completion are now reliably tracked, and the game remains arcade-authentic—even when ghosts and pellets overlap.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export function syncPelletClasses() {
  for (let i = 0; i &amp;lt; pelletState.length; i++) {
    // Only add pellet class if no ghost is present
    if (pelletState[i] === 'pellet' &amp;amp;&amp;amp; !squares[i].classList.contains('ghost')) {
      squares[i].classList.add('pellet');
    } else {
      squares[i].classList.remove('pellet');
    }
    if (pelletState[i] === 'powerPellet' &amp;amp;&amp;amp; !squares[i].classList.contains('ghost')) {
      squares[i].classList.add('powerPellet');
    } else {
      squares[i].classList.remove('powerPellet');
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; &lt;strong&gt;Tip:&lt;/strong&gt; &lt;em&gt;By utilizing this game-state sync technique, you can build more reliable, visually accurate games and interactive apps. Try applying array-driven state management in your own projects for smoother, bug-free experiences!&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;js-pac-man-project-links-&quot;&gt;JS Pac-Man Project Links:&lt;/h4&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://pac-man-javascript-laroccade.netlify.app/&quot;&gt;Link to the deployed project&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/MichaelLarocca/pac-man-javascript-laroccade&quot;&gt;Link to GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/users/MichaelLarocca/projects/1&quot;&gt;Link to the sprint board&lt;/a&gt;&lt;/p&gt;
&lt;h6 id=&quot;note-since-i-m-following-team-development-practices-and-pushing-updates-to-the-develop-branch-some-of-the-changes-i-describe-in-this-article-may-not-be-live-in-the-deployed-version-of-the-game-yet-&quot;&gt;&lt;strong&gt;&lt;em&gt;Note:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;Since I’m following team development practices and pushing updates to the develop branch, some of the changes I describe in this article may not be live in the deployed version of the game yet.&lt;/em&gt;&lt;/h6&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1759271049893/b91c44cf-e68b-401f-b61f-d25bc986d617.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;my-other-related-articles&quot;&gt;My other related articles&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/10-25/javascript-game-timing-how-independent-intervals-can-cause-missed-collisions/&quot;&gt;JavaScript Game Timing: How Independent Intervals Can Cause Missed Collisions&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/09-25/css-pseudo-elements-enhance-your-projects-with-style/&quot;&gt;CSS Pseudo-Elements: Enhance Your Projects with Style!&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/09-25/what-is-state-in-javascript-and-how-to-use-it-in-your-projects/&quot;&gt;What Is “State” in JavaScript, and How to Use It in Your Projects&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2022/03-22/Ania_Kubow-Tetris/&quot;&gt;Ania Kubow: Building Tetris with JavaScript&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/08-25/mastering-javascript-the-power-of-foreach-and-ternary-operators/&quot;&gt;Mastering JavaScript: The Power of forEach and Ternary Operators&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/06-25/javascript-understanding-the-set-and-clear-interval-methods/&quot;&gt;JavaScript: Understanding the Set and Clear Interval Methods&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1740168177634/1ff578a9-5d03-4800-9c0c-9092e4e60c4f.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;be-sure-to-listen-to-the-html-all-the-things-podcast-&quot;&gt;&lt;strong&gt;Be sure to listen to the HTML All The Things Podcast!&lt;/strong&gt;&lt;/h4&gt;
&lt;h5 id=&quot;i-also-write-articles-for-the-html-all-the-things-podcast-which-you-can-read-on-their-website-https-www-htmlallthethings-com-&quot;&gt;&lt;em&gt;I also write articles for the HTML All The Things Podcast, which you can read on their website:&lt;/em&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.htmlallthethings.com/&quot;&gt;&lt;em&gt;https://www.htmlallthethings.com/&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/h5&gt;
&lt;h5 id=&quot;be-sure-to-check-out-html-all-the-things-on-socials-&quot;&gt;&lt;strong&gt;Be sure to check out HTML All The Things on socials!&lt;/strong&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://twitter.com/htmleverything&quot;&gt;Twitter&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.linkedin.com/company/html-all-the-things/&quot;&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.tiktok.com/@htmlallthethings&quot;&gt;TikTok&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.instagram.com/htmlallthethings/&quot;&gt;Instagram&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;affiliate-amp-discount-links-&quot;&gt;Affiliate &amp;amp; Discount Links!&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1740168473785/c85789c9-1594-4000-aa2f-43e842f9825f.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With CodeMonkey, learning can be all fun and games!&lt;/strong&gt; CodeMonkey transforms education into an engaging experience, enabling children to evolve from tech consumers to creators. Use CodeMonkey's &lt;strong&gt;FREE trial&lt;/strong&gt; to unlock the incredible potential of young tech creators!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With a structured learning path tailored for various age groups, kids progress from block coding to more advanced topics like data science and artificial intelligence, using languages such as CoffeeScript and Python. The platform includes features for parents and teachers to track progress, making integrating coding into home and classroom settings easy.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Through fun games, hands-on projects, and community interaction, CodeMonkey helps young learners build teamwork skills and receive recognition for their achievements. It fosters a love for coding and prepares children for future career opportunities in an ever-evolving tech landscape.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;To learn more about CodeMonkey, you can read my detailed&lt;/em&gt;&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2025/02-25/inspiring-young-coders-how-codemonkey-turns-kids-into-tech-creators/&quot;&gt;&lt;strong&gt;&lt;em&gt;review article&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Affiliate Links:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://codemonkey.sjv.io/c/5987452/919057/12259&quot;&gt;Sign Up for Parents&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://codemonkey.sjv.io/c/5987452/919060/12259&quot;&gt;Sign Up for Teachers&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1740169191630/ac8c5360-d1c5-4c85-8504-18b9c755841e.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;advance-your-career-with-a-20-discount-on-scrimba-pro-using-this-affiliate-link-&quot;&gt;Advance your career with a 20% discount on Scrimba Pro using this &lt;a rel=&quot;nofollow&quot; href=&quot;https://scrimba.com/?via=MichaelLarocca&quot;&gt;affiliate link&lt;/a&gt;!&lt;/h4&gt;
&lt;p&gt;Become a hireable developer with Scrimba Pro! Discover a world of coding knowledge with full access to all courses, hands-on projects, and a vibrant community. You can &lt;a rel=&quot;nofollow&quot; href=&quot;https://selftaughttxg.com/2021/06-21/06-07-21/&quot;&gt;read my article&lt;/a&gt; to learn more about my exceptional experiences with Scrimba and how it helps many become confident, well-prepared web developers!&lt;/p&gt;
&lt;h6 id=&quot;important-this-discount-is-for-new-accounts-only-if-a-higher-discount-is-currently-available-it-will-be-applied-automatically-&quot;&gt;&lt;strong&gt;&lt;em&gt;Important:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;This discount is for new accounts only. If a higher discount is currently available, it will be applied automatically.&lt;/em&gt;&lt;/h6&gt;
&lt;p&gt;&lt;strong&gt;How to Claim Your Discount:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click &lt;a rel=&quot;nofollow&quot; href=&quot;https://scrimba.com/?via=MichaelLarocca&quot;&gt;the link&lt;/a&gt; to explore the new Scrimba 2.0.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new account.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upgrade to Pro; the 20% discount will automatically apply.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h6 id=&quot;disclosure-this-article-contains-affiliate-links-i-will-earn-a-commission-from-any-purchases-made-through-these-links-at-no-extra-cost-to-you-your-support-helps-me-continue-creating-valuable-content-thank-you-&quot;&gt;&lt;strong&gt;&lt;em&gt;Disclosure:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;This article contains affiliate links. I will earn a commission from any purchases made through these links at no extra cost to you. Your support helps me continue creating valuable content. Thank you!&lt;/em&gt;&lt;/h6&gt;
&lt;hr&gt;
&lt;h4 id=&quot;conclusion-1&quot;&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Array iteration lets you efficiently access and update each element in a collection, making it a foundation for managing dynamic data in JavaScript. The Document Object Model (DOM) is a programming interface representing a webpage's structure as a tree of objects, which, in JavaScript, allows for dynamic modification of content, structure, and style for interactive experiences.&lt;/p&gt;
&lt;p&gt;Using array iteration for DOM manipulation, I solved glitches in my game using array-driven state management: I used a syncPelletClasses function to align the pelletState array with the DOM, updating visuals based on game state changes. This solution ensured that the game logic always matched what players saw on screen and what was accessible to the code.&lt;/p&gt;
&lt;p&gt;If you’re building interactive apps or games, try leveraging array-driven state management and DOM syncing techniques to help create smoother, more reliable user experiences!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Let’s connect! I’m active on&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.linkedin.com/in/michaeljudelarocca/&quot;&gt;&lt;strong&gt;LinkedIn&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://twitter.com/MikeJudeLarocca&quot;&gt;&lt;strong&gt;Twitter&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://miro.medium.com/v2/resize:fit:700/0*WkkMi-AgjubeODf8.jpeg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h6 id=&quot;do-you-now-have-a-better-understanding-of-javascript-array-iteration-and-dom-manipulation-are-you-ready-to-use-these-techniques-to-improve-your-own-projects-please-share-the-article-and-comment-&quot;&gt;&lt;em&gt;Do you now have a better understanding of JavaScript array iteration and DOM manipulation? Are you ready to use these techniques to improve your own projects? Please share the article and comment!&lt;/em&gt;&lt;/h6&gt;
&lt;hr&gt;
</description>
<category>JavaScript</category>
<guid isPermaLink="true">https://coderlegion.com/6392/javascript-array-iteration-and-dom-manipulation-in-game-development</guid>
<pubDate>Mon, 13 Oct 2025 17:54:24 +0000</pubDate>
</item>
<item>
<title>Beyond the Array: Why Normalized Maps and Sets Supercharge Your Frontend Performance</title>
<link>https://coderlegion.com/6140/beyond-the-array-why-normalized-maps-and-sets-supercharge-your-frontend-performance</link>
<description>&lt;p&gt;In modern frontend development, API responses often arrive as arrays of objects. While simple, relying solely on these arrays for state management introduces a fundamental performance bottleneck: &lt;strong&gt;linear time complexity (&lt;/strong&gt;O(N)&lt;strong&gt;)&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;By adopting a &lt;strong&gt;normalization&lt;/strong&gt; strategy using JavaScript's &lt;strong&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/strong&gt;, we shift critical operations to &lt;strong&gt;constant time (O(1))&lt;/strong&gt;, making applications faster, more consistent, and scalable.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-core-performance-barrier-array-s-o-n-lookups&quot;&gt;The Core Performance Barrier: Array's &lt;strong&gt;O(N)&lt;/strong&gt; Lookups&lt;/h3&gt;
&lt;p&gt;The problem with a simple array is that accessing an item by its ID requires iterating through the list until a match is found.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Impact:&lt;/strong&gt; If you have &lt;strong&gt;N&lt;/strong&gt; items, finding a specific one requires an average of &lt;strong&gt;N/2&lt;/strong&gt; checks. As your data scales, retrieval and update times worsen linearly. This manifests as UI lag and sluggish response times, especially on large datasets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution is to decouple the data's &lt;strong&gt;storage structure&lt;/strong&gt; from its &lt;strong&gt;display order&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;-the-normalized-solution-o-1-consistency-and-access&quot;&gt;️ The Normalized Solution: &lt;strong&gt;O(1)&lt;/strong&gt; Consistency and Access&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Normalization&lt;/strong&gt; is the architectural practice of storing each unique entity (like a product, user, or post) in a single, central location keyed by its unique identifier.&lt;/p&gt;
&lt;h4 id=&quot;1-map-as-the-entity-store-the-source-of-truth-&quot;&gt;1. &lt;code&gt;Map&lt;/code&gt; as the Entity Store (The Source of Truth)&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;Map&lt;/code&gt; becomes your application's single source of truth because its hash-table-like structure allows for &lt;strong&gt;instantaneous key-based retrieval (&lt;/strong&gt;O(1)&lt;strong&gt;)&lt;/strong&gt;, regardless of the map's size.&lt;/p&gt;
&lt;h5 id=&quot;advantage-a-guaranteed-data-consistency&quot;&gt;Advantage A: Guaranteed Data Consistency&lt;/h5&gt;
&lt;p&gt;In large applications, the same data might be displayed in a main feed, a sidebar, and a notification area.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Map Impact:&lt;/strong&gt; When an update arrives (e.g., a post's like count increases), you mutate the single object within the &lt;code&gt;Map&lt;/code&gt;. Because all views are referencing this same object, &lt;strong&gt;consistency is guaranteed automatically&lt;/strong&gt; by the reactive framework. There is no need for slow searches across multiple separate arrays.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&quot;advantage-b-instantaneous-updates&quot;&gt;Advantage B: Instantaneous Updates&lt;/h5&gt;
&lt;p&gt;In high-frequency scenarios, like social media feeds or chat applications, every millisecond counts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Map Impact:&lt;/strong&gt; When a specific item needs updating (e.g., Post ID 500), the system skips the array search entirely and performs a direct, instantaneous lookup: &lt;code&gt;postsMap.get(500).likes = 101&lt;/code&gt;. This efficiency is crucial for &lt;strong&gt;real-time responsiveness&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;2-set-for-ultra-fast-membership-testing&quot;&gt;2. &lt;code&gt;Set&lt;/code&gt; for Ultra-Fast Membership Testing&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;Set&lt;/code&gt; is ideal when you only need to know &lt;strong&gt;if&lt;/strong&gt; an item exists, not the item's details.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Set Impact:&lt;/strong&gt; Using a &lt;strong&gt;Set&lt;/strong&gt; to store active user IDs in a chatroom allows the system to check permissions with &lt;strong&gt;O(1) speed&lt;/strong&gt;. This is far more efficient than an &lt;strong&gt;O(N)&lt;/strong&gt; array check, particularly for operations like sending messages that are triggered frequently.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-hybrid-approach-filtering-and-display-order&quot;&gt;The Hybrid Approach: Filtering and Display Order&lt;/h3&gt;
&lt;p&gt;While Maps handle storage, &lt;strong&gt;Arrays are still necessary for ordered display&lt;/strong&gt;. The optimal strategy is a hybrid: use the Map for the data, and an Array of IDs for the view structure.&lt;/p&gt;
&lt;h4 id=&quot;the-display-logic-flow&quot;&gt;The Display Logic Flow&lt;/h4&gt;
&lt;p&gt;This pattern is most powerful when managing complex filtering and sorting:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Filtering:&lt;/strong&gt; When a user applies criteria (e.g., location, salary), the system iterates through the keys of the massive &lt;strong&gt;&lt;code&gt;jobsMap&lt;/code&gt;&lt;/strong&gt; (the only remaining &lt;strong&gt;O(N)&lt;/strong&gt; step).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resulting Array:&lt;/strong&gt; The output is a &lt;strong&gt;small array of matching IDs&lt;/strong&gt; (e.g., &lt;code&gt;[205, 112, 340]&lt;/code&gt;), not an array of full data objects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sorting:&lt;/strong&gt; The application only sorts this small array of IDs, which is dramatically faster than sorting the original 10,000-item dataset.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rendering:&lt;/strong&gt; The application iterates through the small array of IDs. For each ID, it performs an &lt;strong&gt;instant O(1) lookup&lt;/strong&gt; in the &lt;strong&gt;&lt;code&gt;jobsMap&lt;/code&gt;&lt;/strong&gt; to retrieve the full object details for rendering.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This hybrid approach isolates the &lt;strong&gt;O(N)&lt;/strong&gt; complexity to the filtering step, making all subsequent and more frequent operations (retrieval, sorting, and single-item updates) perform at &lt;strong&gt;O(1) efficiency&lt;/strong&gt;. This separation of concerns ensures your UI remains fast and responsive, regardless of the size of your underlying data.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/6140/beyond-the-array-why-normalized-maps-and-sets-supercharge-your-frontend-performance</guid>
<pubDate>Mon, 06 Oct 2025 17:31:36 +0000</pubDate>
</item>
<item>
<title>Space vs. Gap — Tailwind CSS Explained</title>
<link>https://coderlegion.com/6038/space-vs-gap-tailwind-css-explained</link>
<description>&lt;p&gt;&lt;img src=&quot;http://&quot; alt=&quot;&quot;&gt;&lt;br&gt;
Tailwind is an awesome resource when styling web applications. It’s fast, lightweight, and easy to use once you get used to the class-first syntax. But what do you use when you need to add some spacing between items — &lt;strong&gt;gap&lt;/strong&gt; or &lt;strong&gt;space&lt;/strong&gt;?&lt;br&gt;
Let’s get into it.&lt;/p&gt;
&lt;h4 id=&quot;what-do-i-use-&quot;&gt;&lt;strong&gt;What do I use?&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;To tackle this question, let’s create a scenario. We’ll be using three boxes represented by &lt;code&gt;divs&lt;/code&gt; in an HTML document.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;section&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-300&quot;&amp;gt;Box 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-400&quot;&amp;gt;Box 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-500&quot;&amp;gt;Box 3&amp;lt;/div&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, there are three boxes we need to add some spacing to. Normally, the way to go about this would be to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use a flex layout on the &lt;code&gt;section&lt;/code&gt; parent element and add a &lt;code&gt;gap&lt;/code&gt; value to create space.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use a margin on each box.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But what happens when there’s no need to use a flex layout or margin? What do we use?&lt;/p&gt;
&lt;p&gt;That’s where the space Tailwind class comes in. Picture it as what &lt;code&gt;gap&lt;/code&gt; is capable of in a grid or flex layout, but without the flex/grid. So let's see a side-by-side comparison.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- with tailwind space --&amp;gt;
&amp;lt;section class=&quot;space-5&quot;&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-300&quot;&amp;gt;Box 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-400&quot;&amp;gt;Box 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-500&quot;&amp;gt;Box 3&amp;lt;/div&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- with tailwind gap --&amp;gt;
&amp;lt;section class=&quot;flex gap-5&quot;&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-300&quot;&amp;gt;Box 1&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-400&quot;&amp;gt;Box 2&amp;lt;/div&amp;gt;
  &amp;lt;div class=&quot;w-48 h-48 bg-slate-500&quot;&amp;gt;Box 3&amp;lt;/div&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the first code block, using Tailwind &lt;code&gt;space&lt;/code&gt;creates spacing between the items in the section element. The main difference is that when using &lt;code&gt;gap&lt;/code&gt;, a flex or grid layout is required, whereas when using &lt;code&gt;space&lt;/code&gt;, it's not.&lt;/p&gt;
&lt;p&gt;This is something I discovered earlier when exploring more of what Tailwind CSS can do in my projects.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Hopefully, this article has helped to simplify the &lt;strong&gt;gap vs. space&lt;/strong&gt; concept in Tailwind. For more detailed documentation, please visit the official Tailwind docs: &lt;a rel=&quot;nofollow&quot; href=&quot;https://tailwindcss.com/docs/gap&quot;&gt;&lt;em&gt;Tailwind gap&lt;/em&gt;&lt;/a&gt; &lt;em&gt;vs.&lt;/em&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://tailwindcss.com/docs/margin#adding-space-between-children&quot;&gt;&lt;em&gt;Tailwind space&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Thanks for reading, and have a great day.&lt;br&gt;
Ciao &lt;/p&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/6038/space-vs-gap-tailwind-css-explained</guid>
<pubDate>Sat, 04 Oct 2025 07:32:09 +0000</pubDate>
</item>
<item>
<title>Blockchain and Frontend Development: Building the Decentralized Web</title>
<link>https://coderlegion.com/4687/blockchain-and-frontend-development-building-the-decentralized-web</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=2294317395354630018&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h3 id=&quot;where-blockchain-meets-the-frontend&quot;&gt;Where Blockchain Meets the Frontend&lt;/h3&gt;
&lt;p&gt;At a high level:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Blockchain is the backend layer in many decentralized applications (dApps).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Frontend is the user interface that allows people to interact with that blockchain.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unlike traditional apps where the frontend talks to a server and database you control, in blockchain apps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The frontend communicates with smart contracts on a blockchain network.&lt;/li&gt;
&lt;li&gt;Data is fetched from decentralized sources instead of centralized APIs.&lt;/li&gt;
&lt;li&gt;Users connect their wallets (e.g., MetaMask) to sign and send transactions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-how-frontend-connects-to-blockchain&quot;&gt;2. How Frontend Connects to Blockchain&lt;/h3&gt;
&lt;p&gt;To bridge frontend with blockchain, developers use:&lt;/p&gt;
&lt;p&gt;Web3 Libraries&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ethers.js – Lightweight and modern.&lt;/li&gt;
&lt;li&gt;web3.js – Older but widely used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Wallet APIs&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Browser extensions like MetaMask or Phantom inject JavaScript APIs&lt;br&gt;
(e.g., window.ethereum).&lt;/li&gt;
&lt;li&gt;Smart Contract ABIs&lt;/li&gt;
&lt;li&gt;The ABI (Application Binary Interface) acts like a contract’s “menu”&lt;br&gt;
— telling the frontend what functions exist and how to call them.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example flow:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User clicks “Buy NFT” button on a React app.&lt;/li&gt;
&lt;li&gt;Frontend calls a function in a smart contract via ethers.js.&lt;/li&gt;
&lt;li&gt;Wallet pops up asking for confirmation.&lt;/li&gt;
&lt;li&gt;Transaction is sent to the blockchain.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UI updates after blockchain confirms.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;h3 id=&quot;common-frontend-tools-for-blockchain-projects&quot;&gt;Common Frontend Tools for Blockchain Projects&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Frameworks – React, Next.js, Vue.js, Svelte.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;State Management – Redux, Zustand, Vuex.&lt;/li&gt;
&lt;li&gt;UI Libraries – Tailwind CSS, Chakra UI, Ant Design.&lt;/li&gt;
&lt;li&gt;Blockchain Integrations&lt;/li&gt;
&lt;li&gt;WalletConnect (connect mobile wallets)&lt;/li&gt;
&lt;li&gt;RainbowKit (wallet UI for Ethereum)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apollo Client (for GraphQL APIs like The Graph)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;h3 id=&quot;challenges-in-blockchain-frontend&quot;&gt;Challenges in Blockchain Frontend&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transaction delays – Need loading states and confirmations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;Gas fees – Must display cost estimates clearly.&lt;/li&gt;
&lt;li&gt;Network switching – Sometimes users are on the wrong blockchain&lt;br&gt;
network.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security – Never expose private keys in the frontend.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;h3 id=&quot;real-world-examples&quot;&gt;Real-World Examples&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NFT Marketplaces – Frontend handles image galleries, bidding UI, and&lt;br&gt;
wallet connections.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;DeFi Dashboards – React or Vue UI showing real-time balances and&lt;br&gt;
yield calculations.&lt;/li&gt;
&lt;li&gt;Gaming dApps – Game UIs integrated with blockchain-based asset&lt;br&gt;
ownership.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;6-the-future-of-blockchain-frontends&quot;&gt;6. The Future of Blockchain Frontends&lt;/h3&gt;
&lt;p&gt;As Web3 grows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Frontends will become more wallet-native (log in with your wallet&lt;br&gt;
instead of username/password).&lt;/li&gt;
&lt;li&gt;Data fetching will rely more on decentralized indexing tools like The&lt;br&gt;
Graph.&lt;/li&gt;
&lt;li&gt;Frameworks may include blockchain-ready templates out of the box.&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/4687/blockchain-and-frontend-development-building-the-decentralized-web</guid>
<pubDate>Wed, 13 Aug 2025 20:47:13 +0000</pubDate>
</item>
<item>
<title>What is Javascript and How It Powers Modern Websites</title>
<link>https://coderlegion.com/4623/what-is-javascript-and-how-it-powers-modern-websites</link>
<description>&lt;p&gt;Picture this: You click a button on a webpage, and absolutely nothing happens .&lt;/p&gt;
&lt;p&gt;There are no dropdown menus to explore, no fun animations to enjoy, and no validations on form submissions.&lt;/p&gt;
&lt;p&gt;Basically, a &lt;em&gt;lifeless piece of the internet&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That's what the web would look like without Javascript. &lt;/p&gt;
&lt;h2 id=&quot;what-is-javascript-&quot;&gt;What is Javascript?&lt;/h2&gt;
&lt;p&gt;Javascript, often abbreviated as &quot;JS&quot;, is the wacky genius of modern web development.&lt;/p&gt;
&lt;p&gt;It's the magic wand  that transforms static, boring HTML and CSS websites into lively, interactive, and engaging experiences that are hard to stop scrolling through.&lt;/p&gt;
&lt;p&gt;Simply put, Javascript is a programming language that adds &lt;em&gt;interactivity, animations, and dynamic features&lt;/em&gt; to websites. Whether it's &lt;em&gt;a pop-up&lt;/em&gt; (), &lt;em&gt;a dropdown menu&lt;/em&gt; (), or &lt;em&gt;an animation that dances across your screen&lt;/em&gt;—&lt;strong&gt;Javascript is behind the curtain pulling the strings&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;It's one of the &lt;strong&gt;holy trinity of web development&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;HTML – gives structure&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;CSS – makes it pretty&lt;/em&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Javascript – brings it to life&lt;/em&gt;&lt;/strong&gt; ⚡&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's primarily a &lt;strong&gt;&lt;em&gt;client-side language&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;event-driven&lt;/em&gt;&lt;/strong&gt;, and runs directly in your browser without requiring installation. Magic? Nope—just good old scripting.&lt;/p&gt;
&lt;p&gt;Technically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It's &lt;strong&gt;interpreted&lt;/strong&gt; (runs directly, no compiling)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's &lt;strong&gt;dynamically typed&lt;/strong&gt; (you don't have to declare types — more on this in a later article)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It uses &lt;strong&gt;prototypal inheritance&lt;/strong&gt; instead of classical OOP (we'll unpack this later — no stress if that sounds unfamiliar!)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It runs using something called a &lt;strong&gt;Javascript engine&lt;/strong&gt; inside your browser (don't worry, we'll explain what that means soon)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oh, and it also works on the server side, but we'll dive into that later.&lt;/p&gt;
&lt;h2 id=&quot;-a-brief-history-of-javascript&quot;&gt;&lt;strong&gt; A Brief History of Javascript&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Back in &lt;strong&gt;&lt;em&gt;1995&lt;/em&gt;, Brendan Eich&lt;/strong&gt; developed Javascript in just &lt;strong&gt;10 days&lt;/strong&gt;. Yes, that's faster than most of us write a to-do list .&lt;/p&gt;
&lt;p&gt;Originally called &lt;strong&gt;Mocha&lt;/strong&gt; (mmm, coffee), then &lt;strong&gt;Live Script&lt;/strong&gt;, it was finally &lt;strong&gt;rebranded as Javascript&lt;/strong&gt; because, hey, Java was trendy at the time ☕.&lt;/p&gt;
&lt;p&gt;Despite the misleading name, &lt;strong&gt;Java ≠ Javascript&lt;/strong&gt;—that's like comparing ham to a hamster.&lt;/p&gt;
&lt;p&gt;Fast-forward to today. Javascript has grown from a toy language into one of the web's core technologies, alongside HTML and CSS. It is now &lt;strong&gt;&lt;em&gt;standardised under ECMAScript&lt;/em&gt;&lt;/strong&gt; and powers everything on the web except your morning coffee .&lt;/p&gt;
&lt;h2 id=&quot;-core-features-of-javascript&quot;&gt;&lt;strong&gt;✨ Core Features of Javascript&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Javascript isn't just pretty code—it's flexible, feisty, and full of surprises.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamically Typed&lt;/strong&gt; – like, whatever &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Event-Driven&lt;/strong&gt; – reacts to user clicks, scrolls, and tantrums .&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast&lt;/strong&gt; – thanks to powerful browser engines ⚡&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versatile&lt;/strong&gt; – works on browsers, servers, phones, fridges (not kidding !)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It Has Superpowers (via Ecosystem) -&lt;/strong&gt; There's a massive library of tools and frameworks. React, Vue, D3, Express, Socket.io — you're never alone in Javascript land .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's like that colleague who can debug complex code with ease, seamlessly integrate APIs, and always finds time to collaborate on projects. &lt;/p&gt;
&lt;h2 id=&quot;how-to-run-javascript-in-a-browser&quot;&gt;&lt;strong&gt;How to Run Javascript in a Browser&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Javascript is &lt;strong&gt;built right into all major browsers&lt;/strong&gt; (&lt;em&gt;Chrome, Firefox, Safari, Edge&lt;/em&gt;), like a secret snack drawer .&lt;/p&gt;
&lt;p&gt;You can run Javascript in the browser in a few simple ways:&lt;/p&gt;
&lt;h4 id=&quot;1-the-developer-console-for-quick-testing-&quot;&gt;&lt;strong&gt;1. The Developer Console (For Quick Testing)&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open &lt;em&gt;Chrome&lt;/em&gt; (or any browser).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press &lt;code&gt;F12&lt;/code&gt; or &lt;strong&gt;right-click → Inspect&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The browser's &lt;strong&gt;developer tools&lt;/strong&gt; will open up. Go to the &lt;strong&gt;Console Tab&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Type this, Hit Enter and watch the magic unfold ✨&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;console.log(&quot;Hello, World! &quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=12213951383119350445&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h4 id=&quot;2-add-it-directly-to-html&quot;&gt;&lt;strong&gt;2. Add it directly to HTML&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Use the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag inside your HTML file - &lt;code&gt;index.html&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
    &amp;lt;body&amp;gt;
        &amp;lt;h1&amp;gt;Javascript Test&amp;lt;/h1&amp;gt;

        &amp;lt;script&amp;gt;
            alert(&quot;Hello, World! &quot;);
        &amp;lt;/script&amp;gt;
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the &lt;code&gt;index.html&lt;/code&gt; file in your favorite browser.&lt;/p&gt;
&lt;p&gt;Boom! JS is live and will greet you like a chatty bot!.&lt;/p&gt;
&lt;h2 id=&quot;how-javascript-gets-executed&quot;&gt;&lt;strong&gt;How Javascript gets executed&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Before getting our hands dirty with Javascript code, it is better to have a basic understanding of how Javascript gets executed. ☄️&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Javascript alone is just syntax and logic&lt;/em&gt;; just like any other programming language, &lt;strong&gt;&lt;em&gt;a compiler or an interpreter is needed to execute Javascript&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Well, there are still ongoing debates about whether Javascript is a compiled language or an interpreted language. It would be &lt;strong&gt;&lt;em&gt;more accurate to say that Javascript in modern times is both compiled and interpreted, specifically through JIT (Just-In-Time) Compilation&lt;/em&gt;&lt;/strong&gt;. More on this later.&lt;/p&gt;
&lt;p&gt;To interact with web pages, forms, user events, or fetch data, it requires &lt;strong&gt;&lt;em&gt;a host&lt;/em&gt;&lt;/strong&gt; where &lt;strong&gt;&lt;em&gt;this JIT Compiler (a Javascript engine) is embedded&lt;/em&gt;&lt;/strong&gt;, much like the engine of a car—essential for driving the experience forward and making everything run smoothly. &lt;/p&gt;
&lt;h3 id=&quot;what-is-a-hosted-environment-&quot;&gt;&lt;strong&gt;What Is a Hosted Environment? ⚙️&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A hosted environment — or, as seasoned developers call it, &lt;strong&gt;the runtime environment&lt;/strong&gt; — is the setup provided by the host system, &lt;strong&gt;&lt;em&gt;such as a web browser or Node.js&lt;/em&gt;&lt;/strong&gt;, that embeds and interacts with the &lt;strong&gt;&lt;em&gt;Javascript engine&lt;/em&gt;&lt;/strong&gt;. This environment offers some juicy extras — such as &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;document&lt;/code&gt;, and &lt;code&gt;setTimeout&lt;/code&gt; — that the core Javascript language doesn't include.&lt;/p&gt;
&lt;h4 id=&quot;key-examples-of-hosted-environments-for-javascript&quot;&gt;&lt;strong&gt;Key Examples of Hosted Environments for Javascript&lt;/strong&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Browsers (Client-side Hosted Environment)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DOM access&lt;/strong&gt;: via &lt;code&gt;document&lt;/code&gt;, &lt;code&gt;window&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser APIs&lt;/strong&gt;: like &lt;code&gt;fetch()&lt;/code&gt;, &lt;code&gt;alert()&lt;/code&gt;, &lt;code&gt;console.log()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Timers&lt;/strong&gt;: &lt;code&gt;setTimeout&lt;/code&gt;, &lt;code&gt;setInterval&lt;/code&gt;. etc&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code runs in the &lt;strong&gt;&lt;em&gt;context of a webpage&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Controlled by the &lt;strong&gt;&lt;em&gt;browser's security and event loop&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can access and manipulate the &lt;strong&gt;&lt;em&gt;DOM&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node.js (Server-side Hosted Environment)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File System:&lt;/strong&gt; via &lt;code&gt;fs&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network:&lt;/strong&gt; &lt;code&gt;http&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Other APIs:&lt;/strong&gt; &lt;code&gt;process&lt;/code&gt;, &lt;code&gt;require&lt;/code&gt;, etc.&lt;/p&gt;
&lt;p&gt;  &lt;strong&gt;Characteristics:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code runs &lt;strong&gt;&lt;em&gt;on a server&lt;/em&gt;&lt;/strong&gt;, often with access to the filesystem and network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No DOM or browser-specific features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Includes an &lt;strong&gt;&lt;em&gt;event-driven, non-blocking I/O model&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Other Examples&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deno:&lt;/strong&gt; Secure TypeScript/Javascript runtime with modern APIs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Edge Functions / Serverless Platforms:&lt;/strong&gt; Cloud-hosted Javascript executed in response to HTTP requests.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All major browsers have &lt;strong&gt;&lt;em&gt;Javascript engines built into them&lt;/em&gt;&lt;/strong&gt; (Chrome, Firefox, Safari, Edge)&lt;/p&gt;
&lt;p&gt;Some well-known JS engines are,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Chrome&lt;/strong&gt; → V8 Engine &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Firefox&lt;/strong&gt; → SpiderMonkey &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Safari&lt;/strong&gt; → JavaScriptCore &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-happens-when-you-load-a-web-page-&quot;&gt;&lt;strong&gt;What happens when you load a web page?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;So, how exactly does Javascript run when you load a web page? &lt;/p&gt;
&lt;p&gt;Here's a simplified overview that doesn't require a PhD:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You load a page&lt;/strong&gt; – Browser reads the HTML and finds a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Javascript engine&lt;/strong&gt; (like V8 in Chrome or SpiderMonkey in Firefox) kicks in.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The engine parses the code&lt;/strong&gt;, converts it into something called bytecode or machine code.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It executes the code line by line&lt;/strong&gt;, handling events, functions, loops, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It interacts with the browser's APIs, including the Document Object Model (DOM) and the Browser Object Model (BOM), to enable engaging functionality on the screen.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The way everything unfolds within the browser and our Javascript engine is a fascinating process, which we will explore in more detail in a future article.&lt;/p&gt;
&lt;h2 id=&quot;-how-to-add-javascript-to-a-website&quot;&gt;&lt;strong&gt; How to Add Javascript to a Website&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;There are three classic ways to add Javascript:&lt;/p&gt;
&lt;h4 id=&quot;-1-inline-javascript&quot;&gt;&lt;strong&gt; 1. Inline Javascript&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Directly inside HTML elements.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;button onclick=&quot;alert('You clicked!')&quot;&amp;gt;Click me&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;✅ &lt;em&gt;Easy to test. ❌ Not scalable or maintainable&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;-2-internal-scripts-in-tags&quot;&gt;&lt;strong&gt; 2. Internal Scripts in  Tags&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;In a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; in the HTML.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&amp;lt;script&amp;gt;
    console.log(&quot;This runs when the page loads.&quot;);
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Great for small scripts during development.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;-3-external-javascript-files&quot;&gt;&lt;strong&gt; 3. External Javascript Files&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;In a separate HTML file - &lt;code&gt;index.html&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- In index.html - Withing &amp;lt;body&amp;gt; tag --&amp;gt;
&amp;lt;script src=&quot;script.js&quot; defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Inside&lt;/strong&gt; &lt;code&gt;script.js&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// script.js
console.log(&quot;This is coming from an external file.&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Use defer to make sure the script runs &lt;em&gt;after&lt;/em&gt; the HTML has loaded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Best practice&lt;/strong&gt;: Keeping your Javascript in a separate &lt;code&gt;.js&lt;/code&gt; file helps to create cleaner and easier-to-manage code. No one likes spaghetti code. &lt;/p&gt;
&lt;h2 id=&quot;-how-javascript-powers-modern-websites&quot;&gt;&lt;strong&gt;⚡ How Javascript Powers Modern Websites&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Javascript is &lt;em&gt;the heartthrob of modern web design&lt;/em&gt; ❤️. Well, yeah, no second thoughts on that.&lt;/p&gt;
&lt;p&gt;It's everywhere, like the air we breathe , and it's lightning-fast ⚡.&lt;/p&gt;
&lt;p&gt;It transforms static pages into &lt;strong&gt;&lt;em&gt;dynamic, interactive experiences&lt;/em&gt;&lt;/strong&gt;. From simple interactions like button clicks to full-scale SPAs (Single-Page Applications) that feel like native apps, Javascript is the engine driving modern UX.&lt;/p&gt;
&lt;p&gt;With powerful frameworks like &lt;em&gt;React, Vue, and Svelte&lt;/em&gt;, and back-end tools like &lt;em&gt;Node.js&lt;/em&gt;, Javascript isn't just hanging out in the browser anymore—it's running the whole show, front to back. There's literally a JS tool for everything.&lt;/p&gt;
&lt;p&gt;If modern web design were a kitchen, HTML would be the recipe, CSS the presentation on the plate, and Javascript the chef, making the magic happen in real-time. &lt;/p&gt;
&lt;h2 id=&quot;-client-side-vs-server-side-javascript&quot;&gt;&lt;strong&gt; Client-side vs Server-side Javascript&lt;/strong&gt;&lt;/h2&gt;
&lt;h3 id=&quot;client-side-browser-&quot;&gt;&lt;strong&gt;Client-Side (Browser)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;It runs on your Devices . It controls UI and responds to events.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt; - React, Vue, Angular, etc&lt;/p&gt;
&lt;h3 id=&quot;server-side-node-js-&quot;&gt;&lt;strong&gt;Server-Side (Node.js)&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;It runs on a remote server ️. It handles data, APIs and back-end logic.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt; - Express, NestJS, etc&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Core Javascript  lays the foundation, and all the frameworks and libraries ️ build on top of it.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;-challenges-and-limitations&quot;&gt;&lt;strong&gt;⚠️ Challenges and Limitations&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;It's not all sunshine and syntax.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt; – Cross-site scripting can be nasty ️&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Browser quirks&lt;/strong&gt; – Some browsers love being &lt;em&gt;extra&lt;/em&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Messy code&lt;/strong&gt; – Write it clean or watch your app turn into spaghetti &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance issues:&lt;/strong&gt; Heavy scripts can slow your site down to turtle speed &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Debugging hell:&lt;/strong&gt; Sometimes finding that one missing semicolon feels like searching for a needle in a haystack &lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But hey, every hero has their flaws—Javascript's just keeping things spicy ️.&lt;/p&gt;
&lt;h2 id=&quot;-the-future-of-javascript&quot;&gt;&lt;strong&gt; The Future of Javascript&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Javascript isn't going anywhere except everywhere&lt;/em&gt;&lt;/strong&gt;. It's growing wiser, faster, and maybe just a little weirder (in a good way). Here's what's cooking:&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Web Assembly (Wasm):&lt;/strong&gt; Javascript's hitting the gym. With Wasm, it's teaming up with languages like Rust and C++ to tackle tasks it was never built for, such as hardcore gaming, video editing, and heavy-duty number crunching — all in your browser. JS + Wasm = power couple of the web.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;TypeScript:&lt;/strong&gt; Javascript's awkward teen years are over. TypeScript is helping it adult properly, giving it types, better tooling, and fewer &quot;undefined is not a function&quot; moments.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;AI and Smart Tooling:&lt;/strong&gt; Development tools are becoming increasingly intelligent. Imagine writing code and your editor gently whispering, &quot;Hey, you forgot a semicolon… again.&quot; AI-assisted coding (hello, Copilot and beyond) is making Javascript dev life faster, easier, and slightly creepier.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Framework Wars 2.0:&lt;/strong&gt; React, Vue, Svelte, Solid, Qwik, and friends are all pushing the boundaries of fast, reactive UI. The future is about smarter rendering, less Javascript shipped to the browser, and fewer &quot;why is my page load 3MB&quot; moments.&lt;/p&gt;
&lt;p&gt;⚙️ &lt;strong&gt;Server-side Evolution:&lt;/strong&gt; Node.js, Deno, Bun — everyone's racing to make server-side Javascript faster, leaner, and cooler. Serverless functions and edge computing are making it possible to run Javascript anywhere... even on a fridge (probably).&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Universal Everything:&lt;/strong&gt; Full-stack Javascript is now the norm. Front-end, back-end, mobile apps, desktop apps, even IoT — all running Javascript. Pretty soon, your toaster  might be sending JSON logs  straight to your console ️—because even breakfast needs debugging .&lt;/p&gt;
&lt;h2 id=&quot;-conclusion&quot;&gt;&lt;strong&gt; Conclusion&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Javascript isn't just code&lt;/em&gt;&lt;/strong&gt;—it's the spark that makes the web come alive ⚡. Without it, your site is basically a mannequin in a shop window . But with Javascript? Boom—now you've got Iron Man flying across your screen .&lt;/p&gt;
&lt;p&gt;So go ahead, crack open that browser console .&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Build stuff ️. Break stuff . Fix stuff . Repeat .&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That's the Javascript way .&lt;/p&gt;
</description>
<category>Getting Started</category>
<guid isPermaLink="true">https://coderlegion.com/4623/what-is-javascript-and-how-it-powers-modern-websites</guid>
<pubDate>Tue, 12 Aug 2025 12:21:13 +0000</pubDate>
</item>
<item>
<title>From Vanilla Template to Still.js Components: A Full Build and Deployment Guide</title>
<link>https://coderlegion.com/4567/from-vanilla-template-to-still-js-components-a-full-build-and-deployment-guide</link>
<description>&lt;h3 id=&quot;a-full-still-js-build-from-raw-html-to-deployment-with-zero-dependencies-&quot;&gt;A full Still.js build from raw HTML to deployment — with zero dependencies.&lt;/h3&gt;
&lt;p&gt;A few days ago, I was asked about migrating a project to Still.js, this article is accompanied by a &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/tnEJ3GzaJRU&quot;&gt;video&lt;/a&gt; demonstrating it.&lt;/p&gt;
&lt;p&gt;Because it’s built in Vanilla JavaScript, Still.js combines perfectly with a template that is based with pure/raw HTML, CSS and JavaScript, even if some library (e.g. jQuery, Bootstrap) was used, Still.js helps you to ease separate things into components, as show cased in &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/tnEJ3GzaJRU&quot;&gt;this video&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What will be covered:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Migrating a Vanilla web template to Still.js&lt;/li&gt;
&lt;li&gt;Back down the template into components conveniently&lt;/li&gt;
&lt;li&gt;Load template’s JavaScript code properly according to Still.js architecture&lt;/li&gt;
&lt;li&gt;Deploy to the cloud&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Key Considerations:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When using templates with a lot animations, or that depends on different javaScript library to load, it’s important to deeply understand it (the template) so to orchestrate each&lt;br&gt;
Script dependency just the same way it happens with raw HTML, CSS and JavaScript.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Minimalist third party Script dependency approach:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now a days a lot of features like animation and more (e.g. parallax, singlePageNav, dialog, IntersectionObserver - Lazy animation) are browser native, hence, this would impact a lot in the choosing on what/when to use libraries especially when it comes to animation which some web pages are depending a lot.&lt;/p&gt;
&lt;p&gt;Vanilla JavaScript is one of the core philosophy of Still.js, hence you can use everything as natural as possible from Web Semantic to straight DOM manipulation.&lt;/p&gt;
&lt;p&gt;We’ll use &lt;a rel=&quot;nofollow&quot; href=&quot;https://templatemo.com/tm-593_personal_shape#google_vignette&quot;&gt;this template&lt;/a&gt;, and we’ll be deploying our page to Render which will provide us with a custom domain.&lt;/p&gt;
&lt;p&gt;In summary, on the coding and structure side of things the steps will be as follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the HTML code will be moved to the Still.js template/template file (.html)&lt;/li&gt;
&lt;li&gt;Run template JavaScript animation in the stAfterInit hook, ensuring it executes after component load&lt;/li&gt;
&lt;li&gt;Convert sections into autonomous components &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Still.js helps turn vanilla templates into fast, modular, and lightweight sites with zero dependencies, giving you full control using pure JavaScript. Proper code organization is key to avoid issues like bloating or conflicts, and a vanilla-first approach is recommended, external libraries should only be used when necessary. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What’s Next?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Don't forget to follow the &lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/tnEJ3GzaJRU&quot;&gt;hands-on video&lt;/a&gt; till the end so we can make the deploy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Expand Your Still.js Skills&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Explore advanced Still.js features like state management, routing, or&lt;br&gt;
integrating APIs. &lt;/li&gt;
&lt;li&gt;Try building a small SPA or dashboard using&lt;br&gt;
Still.js components capabilities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Contribute to Still.js&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Still.js is open-source, consider contributing or helping improve documentation. &lt;/li&gt;
&lt;li&gt;Join the &lt;a rel=&quot;nofollow&quot; href=&quot;https://discord.com/invite/fUVJRTmQ9f&quot;&gt;discord channel&lt;/a&gt; to get fast updates and follow the discussions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Ask more if needed&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Share any topic you want to see cover so content (e.g. video, article) can be produced.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Se ya in the next one &lt;/p&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/4567/from-vanilla-template-to-still-js-components-a-full-build-and-deployment-guide</guid>
<pubDate>Mon, 11 Aug 2025 02:56:47 +0000</pubDate>
</item>
<item>
<title>VSCode vs IntelliJ: Where VSCode Still Struggles, and How to Push It Further</title>
<link>https://coderlegion.com/4179/vscode-vs-intellij-where-vscode-still-struggles-and-how-to-push-it-further</link>
<description>&lt;p&gt;Over the past few years, &lt;strong&gt;VSCode has eaten the developer world&lt;/strong&gt;. Lightweight, fast, deeply customizable—it feels like the ideal coding companion. On the other side sits &lt;strong&gt;IntelliJ&lt;/strong&gt;: powerful, heavy, feature-packed, and—for some—overkill.&lt;/p&gt;
&lt;p&gt;But let’s cut through the hype. If you’re building anything more complex than a quick script, &lt;strong&gt;IntelliJ isn’t just &quot;heavier&quot;—it’s smarter&lt;/strong&gt;. It understands your code, your project, and your dependencies in a way that VSCode simply doesn’t.&lt;/p&gt;
&lt;p&gt;Here’s a brutally honest breakdown of &lt;strong&gt;where VSCode is behind&lt;/strong&gt;, backed with real examples—and how some of those gaps can be patched, including with tools like &lt;strong&gt;Depramanager&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;1-project-awareness-a-real-ide-vs-a-fancy-text-editor&quot;&gt;1. Project Awareness: A Real IDE vs a Fancy Text Editor&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;IntelliJ&lt;/strong&gt; knows what your project is. Whether it’s a Java Maven multi-module app, a Python virtual environment, or a full-stack Node.js + Docker + PostgreSQL repo, IntelliJ parses it top-down. It indexes your files, understands your build system, configures environments, and tracks project-wide issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VSCode?&lt;/strong&gt; It sees folders. Just folders.&lt;/p&gt;
&lt;p&gt;You might:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Manually configure Python interpreters&lt;/li&gt;
&lt;li&gt;Hope your &lt;code&gt;settings.json&lt;/code&gt; doesn’t get out of sync&lt;/li&gt;
&lt;li&gt;Wrestle with 4–5 extensions just to handle testing, linting, formatting, and debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;example-&quot;&gt;Example:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Open a Python project in IntelliJ? You get immediate virtualenv detection, test runner config, linting, and code inspections.&lt;/li&gt;
&lt;li&gt;In VSCode? You manually point to your &lt;code&gt;.venv&lt;/code&gt;, tweak launch configs, and guess why &lt;code&gt;pylint&lt;/code&gt; isn't catching anything.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-dependency-management-missing-misconfigured-or-just-invisible&quot;&gt;2. Dependency Management: Missing, Misconfigured, or Just Invisible&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;IntelliJ shows you&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real-time dependency graphs&lt;/li&gt;
&lt;li&gt;Conflicts between transitive and direct dependencies&lt;/li&gt;
&lt;li&gt;Recommendations to remove unused packages&lt;/li&gt;
&lt;li&gt;One-click updates&lt;/li&gt;
&lt;li&gt;Vulnerability scanning (Ultimate edition)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;VSCode gives you&lt;/strong&gt;… the raw &lt;code&gt;package.json&lt;/code&gt;, and maybe a terminal.&lt;/p&gt;
&lt;p&gt;Need to find out if you’re using an outdated version of &lt;code&gt;express&lt;/code&gt;, or if that &lt;code&gt;left-pad&lt;/code&gt; package is still floating around doing nothing? You’ll need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install some extensions (maybe)&lt;/li&gt;
&lt;li&gt;Run CLI tools (probably)&lt;/li&gt;
&lt;li&gt;Google half the errors when they break&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It’s 2025, and &lt;strong&gt;managing dependencies in VSCode still feels like reading a &lt;code&gt;package.json&lt;/code&gt; in Notepad&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-testing-painfully-manual-vs-seamless-integration&quot;&gt;3. Testing: Painfully Manual vs Seamless Integration&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;IntelliJ&lt;/strong&gt;: You write tests. It discovers them. You click the green triangle. It shows test results with stack traces, variable values, and test history—all inline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;VSCode&lt;/strong&gt;: Hope your language extension supports test discovery. Hope it integrates with your debugger. Hope it even knows what a &quot;test&quot; looks like. Otherwise, it’s back to terminal + &lt;code&gt;npm test&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-code-intelligence-and-refactoring&quot;&gt;4. Code Intelligence and Refactoring&lt;/h3&gt;
&lt;p&gt;IntelliJ gives you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rename that works across files and modules&lt;/li&gt;
&lt;li&gt;Safe refactoring with usage previews&lt;/li&gt;
&lt;li&gt;Automatic method extraction&lt;/li&gt;
&lt;li&gt;Inline documentation with type resolution&lt;/li&gt;
&lt;li&gt;Semantic code search (e.g., “find all functions using X param pattern”)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;VSCode? You can rename a variable. Most of the time.&lt;/p&gt;
&lt;p&gt;Even with LSP-based extensions like Pyright or TS Server, you &lt;strong&gt;don’t get full project-wide understanding&lt;/strong&gt;. IntelliJ is using a custom compiler per language to truly understand your project, not just parse symbols.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-debugging-and-tooling-integration&quot;&gt;5. Debugging and Tooling Integration&lt;/h3&gt;
&lt;p&gt;IntelliJ has built-in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interactive debuggers&lt;/li&gt;
&lt;li&gt;Coverage reports&lt;/li&gt;
&lt;li&gt;Profiler&lt;/li&gt;
&lt;li&gt;Local history (like git—but local and auto-saved)&lt;/li&gt;
&lt;li&gt;Integration with Maven, Gradle, Docker, Kubernetes, Git, and more&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;VSCode can do some of this—but only with extensions, manual configuration, and in many cases, with &lt;em&gt;a fraction of the stability&lt;/em&gt;. You’re building the tooling chain yourself—and it often breaks with updates.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;so-why-do-we-still-use-vscode-&quot;&gt;So Why Do We Still Use VSCode?&lt;/h3&gt;
&lt;p&gt;Because it’s:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fast&lt;/li&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Highly customizable&lt;/li&gt;
&lt;li&gt;Open-source&lt;/li&gt;
&lt;li&gt;Has great community support&lt;/li&gt;
&lt;li&gt;Easier to onboard juniors with&lt;/li&gt;
&lt;li&gt;Doesn't need a beefy machine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But if you're working in &lt;strong&gt;real-world, multi-dependency, multi-environment projects&lt;/strong&gt;—VSCode leaves a lot of heavy lifting to you. Especially when it comes to &lt;strong&gt;dependency and configuration intelligence&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;bridging-the-gap-introducing-depramanager&quot;&gt;Bridging the Gap: Introducing &lt;a rel=&quot;nofollow&quot; href=&quot;https://marketplace.visualstudio.com/items?itemName=Okerew.depramanger&quot;&gt;&lt;strong&gt;Depramanager&lt;/strong&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;Bringing real dependency management to VSCode—without needing IntelliJ.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Depramanager&lt;/strong&gt; is a free, open-source VSCode extension that adds actual dependency intelligence to your workflow.&lt;/p&gt;
&lt;h4 id=&quot;features-&quot;&gt;Features:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependency Graphs&lt;/strong&gt;&lt;br&gt;
See what’s installed, declared, missing, or unused—at a glance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sync &amp;amp; Install&lt;/strong&gt;&lt;br&gt;
Automatically sync missing dependencies to your &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, etc., or install manually from the editor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update Checker&lt;/strong&gt;&lt;br&gt;
Flags outdated packages and lets you update them with a click.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Scanning&lt;/strong&gt;&lt;br&gt;
Checks for known vulnerabilities across popular ecosystems.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inline Highlights&lt;/strong&gt;&lt;br&gt;
Shows outdated or broken dependencies right inside the code editor.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Language-Aware Suggestions&lt;/strong&gt;&lt;br&gt;
Recommends VSCode extensions relevant to your project’s stack.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Okerew/depramanager/tree/main&quot;&gt;GitHub&lt;/a&gt;&lt;br&gt;
 &lt;a rel=&quot;nofollow&quot; href=&quot;https://marketplace.visualstudio.com/items?itemName=Okerew.depramanger&quot;&gt;Marketplace&lt;/a&gt;&lt;br&gt;
 &lt;a rel=&quot;nofollow&quot; href=&quot;https://open-vsx.org/extension/Okerew/depramanger&quot;&gt;Open vsix&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Depramanager doesn’t try to make VSCode IntelliJ. It just &lt;strong&gt;fixes one of its most painful weaknesses&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;final-thoughts-10&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;VSCode is a beautiful tool. But let’s be honest—it’s not a full IDE. It can’t compete with IntelliJ on deep insight, project understanding, or smart refactoring out of the box.&lt;/p&gt;
&lt;p&gt;But with the right tooling and extensions, you can bring some of that power to your daily workflow.&lt;/p&gt;
&lt;p&gt;Use VSCode for what it does best. Use &lt;strong&gt;Depramanager&lt;/strong&gt; to patch its biggest blind spot. And when you really need that fully-integrated IDE experience—don’t feel guilty booting up IntelliJ.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/4179/vscode-vs-intellij-where-vscode-still-struggles-and-how-to-push-it-further</guid>
<pubDate>Sun, 20 Jul 2025 12:26:39 +0000</pubDate>
</item>
<item>
<title>Animate Like a Pro: Build a Modern Scroll-Triggered Website with GSAP</title>
<link>https://coderlegion.com/3647/animate-like-a-pro-build-a-modern-scroll-triggered-website-with-gsap</link>
<description>&lt;p&gt; Introduction&lt;/p&gt;
&lt;p&gt;Modern websites aren’t just static layouts—they breathe, respond, and tell stories. In this guide, we’ll walk through how to build a modern, scroll-triggered, animation-rich website using GSAP (GreenSock Animation Platform).&lt;/p&gt;
&lt;p&gt;Inspired by top-tier Awwwards websites, this post teaches you how to:&lt;/p&gt;
&lt;p&gt;Animate text on page load&lt;/p&gt;
&lt;p&gt;Trigger elements on scroll&lt;/p&gt;
&lt;p&gt;Create parallax effects&lt;/p&gt;
&lt;p&gt;Add interactive hover animations&lt;/p&gt;
&lt;p&gt;Optimize for performance and responsiveness&lt;/p&gt;
&lt;p&gt;All with clean code and professional structure.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Setting Up Your Project&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Create your basic folder structure:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;project/
├── index.html
├── styles.css
└── script.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;index.html&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;section class=&quot;hero&quot;&amp;gt;
  &amp;lt;h1 class=&quot;headline&quot;&amp;gt;We Design for Impact&amp;lt;/h1&amp;gt;
  &amp;lt;button class=&quot;cta&quot;&amp;gt;Discover More&amp;lt;/button&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;styles.css&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;body {
  margin: 0;
  font-family: 'Poppins', sans-serif;
  background: #121212;
  color: #fff;
}

.hero {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Include GSAP via CDN in your HTML:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/gsap@3/dist/ScrollTrigger.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Animate Hero Section with GSAP Timeline&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s animate the headline and button on page load using gsap.timeline():&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const tl = gsap.timeline();

tl.from(&quot;.headline&quot;, {
  y: 100,
  opacity: 0,
  duration: 1.2,
  ease: &quot;power4.out&quot;
})
.from(&quot;.cta&quot;, {
  y: 20,
  opacity: 0,
  duration: 1,
  ease: &quot;back.out(1.7)&quot;
}, &quot;-=0.5&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Result: Smooth fade-in entrance animation with professional timing and bounce.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ScrollTrigger Section Animations&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Create reusable section reveals using ScrollTrigger:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;section class=&quot;section&quot;&amp;gt;About&amp;lt;/section&amp;gt;
&amp;lt;section class=&quot;section&quot;&amp;gt;Projects&amp;lt;/section&amp;gt;
&amp;lt;section class=&quot;section&quot;&amp;gt;Contact&amp;lt;/section&amp;gt;

gsap.utils.toArray(&quot;.section&quot;).forEach(section =&amp;gt; {
  gsap.from(section, {
    scrollTrigger: {
      trigger: section,
      start: &quot;top 85%&quot;,
      toggleActions: &quot;play none none reverse&quot;
    },
    y: 100,
    opacity: 0,
    duration: 1
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Result: Each section fades and slides in when scrolled into view.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a Parallax Effect&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use a parallax background for depth:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;parallax-wrapper&quot;&amp;gt;
  &amp;lt;img src=&quot;bg.jpg&quot; class=&quot;bg-image&quot; /&amp;gt;
&amp;lt;/div&amp;gt;

.parallax-wrapper {
  position: relative;
  height: 100vh;
  overflow: hidden;
}
.bg-image {
  position: absolute;
  width: 100%;
  top: 0;
  z-index: -1;
}

gsap.to(&quot;.bg-image&quot;, {
  scrollTrigger: {
    trigger: &quot;.parallax-wrapper&quot;,
    scrub: true,
  },
  y: &quot;-30%&quot;,
  ease: &quot;none&quot;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Result: Smooth scroll-linked background motion—eye-catching and modern.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add Hover Animation to Elements&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Create hover-based animations for interactive elements:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;div class=&quot;card&quot;&amp;gt;Hover me&amp;lt;/div&amp;gt;

.card {
  width: 200px;
  height: 200px;
  background: #1e1e1e;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s;
}

document.querySelectorAll(&quot;.card&quot;).forEach(card =&amp;gt; {
  card.addEventListener(&quot;mouseenter&quot;, () =&amp;gt; {
    gsap.to(card, { scale: 1.05, duration: 0.3 });
  });
  card.addEventListener(&quot;mouseleave&quot;, () =&amp;gt; {
    gsap.to(card, { scale: 1, duration: 0.3 });
  });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Result: Subtle interactivity that improves UX without overwhelming.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Responsive &amp;amp; Mobile Optimization&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use ScrollTrigger.matchMedia() to conditionally control animations based on screen size:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ScrollTrigger.matchMedia({
  &quot;(min-width: 768px)&quot;: function() {
    gsap.from(&quot;.cta&quot;, {
      y: 50,
      opacity: 0,
      duration: 1,
      scrollTrigger: {
        trigger: &quot;.cta&quot;,
        start: &quot;top 80%&quot;
      }
    });
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt; Pro Tip: Disable or simplify animations for low-powered mobile devices.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Final Touches &amp;amp; Best Practices&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use performance-friendly easing like &quot;power2.out&quot; or &quot;none&quot; for scroll-linked effects&lt;/p&gt;
&lt;p&gt;Use will-change CSS property for elements that animate&lt;/p&gt;
&lt;p&gt;Avoid layout jank: Animate transform, not top/left&lt;/p&gt;
&lt;p&gt; Bonus: What Makes It Awwwards-Worthy?&lt;/p&gt;
&lt;p&gt;Consistent motion rhythm&lt;/p&gt;
&lt;p&gt;Smooth easing and microinteractions&lt;/p&gt;
&lt;p&gt;Strategic use of white space and bold type&lt;/p&gt;
&lt;p&gt;Layered visual depth (z-index, parallax, lighting)&lt;/p&gt;
&lt;p&gt;✅ Conclusion&lt;/p&gt;
&lt;p&gt;This step-by-step journey demonstrates how to transform basic markup into a sophisticated, animated web experience using GSAP. Whether you're enhancing a portfolio, creating a product landing page, or experimenting with scroll-based storytelling, GSAP and ScrollTrigger give you the control and fluidity needed to stand out.&lt;/p&gt;
</description>
<category>Frontend Dev</category>
<guid isPermaLink="true">https://coderlegion.com/3647/animate-like-a-pro-build-a-modern-scroll-triggered-website-with-gsap</guid>
<pubDate>Mon, 30 Jun 2025 06:17:22 +0000</pubDate>
</item>
<item>
<title>Still.js - A way to leverage Vanilla JavaScript for Complex and Enterprise Level Web Development</title>
<link>https://coderlegion.com/3640/still-way-leverage-vanilla-javascript-for-complex-and-enterprise-level-web-development</link>
<description>&lt;p&gt;When it comes to complex web application development on the frontend, we often encounter the need to implement features using vanilla JavaScript—whether it’s for direct DOM manipulation or integrating a specific jQuery plugin. Sometimes, a from-scratch implementation using plain HTML, CSS, and vanilla JavaScript is the best (or only) choice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is Still.js&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;Still.js is a modern Open Source framework that offers the same capabilities as Angular, React, and Vue—without abandoning vanilla JavaScript.&lt;/p&gt;
&lt;p&gt;Because of its pure JS approach, Still.js:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Does not require preprocessing &lt;/li&gt;
&lt;li&gt;Does not depend on bundlers like Webpack or Vite &lt;/li&gt;
&lt;li&gt;Is ideal for teams and developers who prefer direct, no-compromise access to native web technologies in addition to those modern features a Web Framework provides.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Check it up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visit &lt;a rel=&quot;nofollow&quot; href=&quot;https://stilljs.dev/&quot;&gt;stilljs.dev&lt;/a&gt; or the &lt;a rel=&quot;nofollow&quot; href=&quot;https://still-js.github.io/stilljs-site/&quot;&gt;github page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;See &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/playlist?list=PLgMBuN68Pdks-lU0R95LRzXJWgpXL48Vn&quot;&gt;youtube playlist&lt;/a&gt;&lt;br&gt;
Join and discuss on &lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://discord.com/invite/fUVJRTmQ9f&quot;&gt;Discord channel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Still.js is an Open Source, contributions are welcomed, check the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/still-js/core&quot;&gt;Github Repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Suitable for complex and enterprise applications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Enterprise-grade web applications need more than just rich UI features. They require: &lt;code&gt;modularization&lt;/code&gt;, &lt;code&gt;user permission management&lt;/code&gt;, &lt;code&gt;component routing&lt;/code&gt;, &lt;code&gt;validation&lt;/code&gt;, &lt;code&gt;separation of concern&lt;/code&gt;, &lt;code&gt;communication management&lt;/code&gt;, &lt;code&gt;Micro-frontend architecture&lt;/code&gt; (e.g. Frontend embedding and interaction), and more.&lt;/p&gt;
&lt;p&gt;Still.js supports all of this features natively without the burden of a bundler increasing build time and potential complexity or even tooling overhead.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Some code samples&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Note: Those will only work within a Still.js project with the correct setup, which is thoroughly explained in the official documentation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basic component&lt;/strong&gt;:&lt;br&gt;
Bellow is a simple component implementing a counter, inspite the template is placed inside the class, it can be moved to a .html file which is appropriate in complex apps.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { ViewComponent } from &quot;../../../@still/component/super/ViewComponent.js&quot;;

export class CounterComponent extends ViewComponent {

    isPublic = true;
    count = 0;

    template = `
    &amp;lt;div&amp;gt;
        &amp;lt;p&amp;gt;My counter state is @count&amp;lt;/p&amp;gt;
        &amp;lt;button (click)=&quot;increment()&quot;&amp;gt;Increment (@count)&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
    `;

    increment() {
        this.count = this.count.value + 1;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Basic User authorization management&lt;/strong&gt;:&lt;br&gt;
In the bellow implementation we're stating that some components won't be accessible by the user, this can be done with proper business logic according to the user role checking.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { StillAppMixin } from &quot;./@still/component/super/AppMixin.js&quot;;
import { Components } from &quot;./@still/setup/components.js&quot;;
import { AppTemplate } from &quot;./app-template.js&quot;;
import { CheckingAccount } from &quot;./app/components/BankAccount/CheckingAccount.js&quot;;
import { NewAccountForm } from &quot;./app/components/BankAccount/NewAccountForm.js&quot;;
import { SavingAccount } from &quot;./app/components/BankAccount/SavingAccount.js&quot;;

export class StillAppSetup extends StillAppMixin(Components) {

    constructor() {
        super();
        //Bellow the entry point component is being set
        this.setHomeComponent(NewAccountForm);
        const blackListComponents = [SavingAccount, CheckingAccount];
        //Make components black-listed by passing it to setBlackList App configuration
        this.setBlackList(blackListComponents);
    }

    async init() {
        return await AppTemplate.newApp();
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Basic Form validation&lt;/strong&gt;&lt;br&gt;
Still.js provides built-in validators, but custom ones can be implemented effortlessly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { ViewComponent } from &quot;../../../@still/component/super/ViewComponent.js&quot;;

export class BasicForm extends ViewComponent {

    isPublic = true;
    firstName = '';
    shoeSize;

    template = `
    &amp;lt;div&amp;gt;
        &amp;lt;form&amp;gt;
            &amp;lt;div class=&quot;form-group&quot;&amp;gt;
                &amp;lt;label&amp;gt;Shoe Size&amp;lt;/label&amp;gt;
                &amp;lt;input 
                    (value)=&quot;shoeSize&quot; 
                    (validator)=&quot;number&quot; 
                    (validator-warn)=&quot;Invalid shoe size, number is required&quot;
                    placeholder=&quot;Enter valid shoe size&quot;
                &amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
    `;

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Global State management&lt;/strong&gt;:&lt;br&gt;
A service serves for both Global reactive storage and data flow (e.g. HTTP requests) implementations. Services path can be set in the application level, and we can overriden for specific service with &lt;code&gt;@Path&lt;/code&gt; annotation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { ViewComponent } from &quot;../../../@still/component/super/ViewComponent.js&quot;;
import { CustomersService } from &quot;../../service/api/CustomersService.js&quot;;

export class BiddingDisplay extends ViewComponent {

    isPublic = true;

    /** Service declaration, will get injected automatically due to Inject anottation
     *  from the specified Path path due to the annotation
     * @Inject
     * @Path service/api/
     * @type { CustomersService } */
    custService;

    template = `&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;`;

    /** Component Hook which takes place when it's completly render and startder */
    stAfterInit() {

        this.custService.customerList.onChange((newValue) =&amp;gt; { 
            console.log('Ths customerList store got updated with: ', newValue);
        });

    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Hurry up, get yourself started with Still.js&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Contribute for the project as you can, check the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/still-js/core&quot;&gt;GitHub repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Still.js is available through NPM on @stilljs/cli. Watch the &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/playlist?list=PLgMBuN68Pdks-lU0R95LRzXJWgpXL48Vn&quot;&gt;Youtube ▶️ playlist&lt;/a&gt; and bear for more coming ones.&lt;/p&gt;
&lt;p&gt;Watch this &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=Q7mQYGnjAX8&amp;amp;list=PLgMBuN68Pdks-lU0R95LRzXJWgpXL48Vn&amp;amp;index=3&quot;&gt;Tudo App tutorial on Youtube ▶️&lt;/a&gt;, clone or download the provided &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/still-js/samples/tree/main/todo-app&quot;&gt;GitHub Todo app project&lt;/a&gt; and run locally. It demonstrates key concepts like &lt;code&gt;component communication&lt;/code&gt;, &lt;code&gt;event and state binding&lt;/code&gt;, &lt;code&gt;reactive updates&lt;/code&gt;, &lt;code&gt;@Proxy&lt;/code&gt;, and &lt;code&gt;component styling&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Connect and share your feedback on the &lt;a rel=&quot;nofollow&quot; href=&quot;https://discord.com/invite/fUVJRTmQ9f&quot;&gt;Discord channel&lt;/a&gt;.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/3640/still-way-leverage-vanilla-javascript-for-complex-and-enterprise-level-web-development</guid>
<pubDate>Mon, 30 Jun 2025 00:03:03 +0000</pubDate>
</item>
<item>
<title>Understanding JavaScript Prototypes: How Inheritance Works</title>
<link>https://coderlegion.com/3567/understanding-javascript-prototypes-how-inheritance-works</link>
<description>&lt;h3 id=&quot;why-you-should-understand-prototypes&quot;&gt;Why You Should Understand Prototypes&lt;/h3&gt;
&lt;p&gt;When you start learning JavaScript, you’ll often hear this phrase:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;In JavaScript, everything is an object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But what’s often left out is how JavaScript handles inheritance not through classes (traditionally), but through &lt;strong&gt;prototypes&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;in-this-post-we-ll-explore-&quot;&gt;In this post, we’ll explore:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;What prototypes are &lt;/li&gt;
&lt;li&gt;How the prototype chain works  &lt;/li&gt;
&lt;li&gt;&lt;code&gt;__proto__&lt;/code&gt; vs &lt;code&gt;prototype&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;How JavaScript uses prototypes for inheritance  &lt;/li&gt;
&lt;li&gt;How ES6 classes relate to prototypes &lt;/li&gt;
&lt;li&gt;When and why you should care &lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;what-is-a-prototype-&quot;&gt;What Is a Prototype?&lt;/h3&gt;
&lt;p&gt;In JavaScript, every object has an internal link to another object called its &lt;strong&gt;prototype&lt;/strong&gt;.&lt;br&gt;
This prototype object can have its own prototype, forming a &lt;strong&gt;prototype chain&lt;/strong&gt;. The chain ends when a prototype is &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt; &lt;strong&gt;Think of it like a fallback mechanism&lt;/strong&gt; — if a property or method isn’t found on an object, JavaScript looks up the chain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;example&quot;&gt;Example&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;const person = {
  greet() {
    return &quot;Hello!&quot;;
  }
};

const student = Object.create(person);
student.name = &quot;Toni&quot;;

console.log(student.name);      // &quot;Toni&quot;
console.log(student.greet());  // &quot;Hello!&quot; (inherited from `person`)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;explanation&quot;&gt;Explanation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;student doesn’t have greet()&lt;/li&gt;
&lt;li&gt;JavaScript looks up the prototype chain (to person) and finds it there&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-prototype-chain-in-javascript&quot;&gt;The Prototype Chain in JavaScript&lt;/h3&gt;
&lt;p&gt;Every object in JavaScript has a hidden property [[Prototype]] (accessible via &lt;strong&gt;proto&lt;/strong&gt;) that points to its prototype.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const obj = {};
console.log(obj.__proto__);             // Same as Object.prototype
console.log(obj.__proto__.__proto__);  // null (end of chain)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;diagram&quot;&gt;Diagram&lt;/h3&gt;
&lt;p&gt;student → person → Object.prototype → null&lt;/p&gt;
&lt;p&gt;When you access student.greet(), JS will:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look for greet in student&lt;/li&gt;
&lt;li&gt;Not found? Check student.&lt;strong&gt;proto&lt;/strong&gt; (which is person)&lt;/li&gt;
&lt;li&gt;Still not found? Go up again (to Object.prototype)&lt;/li&gt;
&lt;li&gt;If nowhere to be found → undefined&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;-proto-vs-prototype-what-s-the-difference-&quot;&gt;&lt;code&gt;__proto__&lt;/code&gt; vs &lt;code&gt;prototype&lt;/code&gt; : What’s the Difference?&lt;/h3&gt;
&lt;p&gt;This is a common confusion for new developers.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;__proto__&lt;/code&gt; The internal prototype of an instance&lt;/p&gt;
&lt;p&gt;&lt;code&gt;prototype&lt;/code&gt; A property on constructor functions used to create new instances&lt;/p&gt;
&lt;h3 id=&quot;example-with-constructor&quot;&gt;Example with Constructor&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function () {
  return `${this.name} makes a noise.`;
};

const dog = new Animal(&quot;Rex&quot;);

console.log(dog.speak()); // &quot;Rex makes a noise.&quot;
console.log(dog.__proto__ === Animal.prototype); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;dog.&lt;code&gt;__proto__&lt;/code&gt;  points to Animal.prototype, where speak() is defined.&lt;/p&gt;
&lt;h3 id=&quot;es6-classes-amp-prototypes&quot;&gt;ES6 Classes &amp;amp; Prototypes&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class Vehicle {
  drive() {
    console.log(&quot;Vroom!&quot;);
  }
}

const car = new Vehicle();
car.drive(); // &quot;Vroom!&quot;

console.log(Object.getPrototypeOf(car) === Vehicle.prototype); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even with class, JavaScript uses prototypes behind the scenes.&lt;/p&gt;
&lt;h3 id=&quot;why-use-prototypes-&quot;&gt;Why Use Prototypes?&lt;/h3&gt;
&lt;p&gt;Using prototypes provides several advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Memory efficiency — methods are shared across instances&lt;/li&gt;
&lt;li&gt;Performance — avoids recreating functions for every object&lt;/li&gt;
&lt;li&gt;Structure — clear inheritance paths&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;anti-pattern-example&quot;&gt;Anti-pattern Example&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function User() {
  this.sayHi = function () {
    console.log(&quot;Hi!&quot;);
  };
}

const u1 = new User();
const u2 = new User();

console.log(u1.sayHi === u2.sayHi); // false 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each sayHi is a separate function. That’s inefficient.&lt;/p&gt;
&lt;h3 id=&quot;recommended-prototype-approach&quot;&gt;Recommended Prototype Approach&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;function User() {}
User.prototype.sayHi = function () {
  console.log(&quot;Hi!&quot;);
};

const u1 = new User();
const u2 = new User();

console.log(u1.sayHi === u2.sayHi); // true 
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;common-pitfalls-when-using-prototypes&quot;&gt;Common Pitfalls When Using Prototypes&lt;/h3&gt;
&lt;p&gt;Avoid these mistakes when working with prototypes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Don’t manually set &lt;code&gt;__proto__&lt;/code&gt; — use Object.create() or a proper constructor&lt;/li&gt;
&lt;li&gt;Don’t overuse inheritance — favor composition where possible&lt;/li&gt;
&lt;li&gt;Prototype chain lookups are slower than direct property access&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;helpful-built-in-methods-for-working-with-prototypes&quot;&gt;Helpful Built-in Methods for Working with Prototypes&lt;/h3&gt;
&lt;p&gt;Object.create(proto)Creates a new object with a given prototype&lt;/p&gt;
&lt;p&gt;Object.getPrototypeOf(obj)Returns the prototype of obj&lt;/p&gt;
&lt;p&gt;Object.setPrototypeOf(obj, proto)Sets the prototype (avoid for performance reasons)&lt;/p&gt;
&lt;p&gt;instanceofChecks if proto exists in the object’s prototype chain&lt;/p&gt;
&lt;p&gt;hasOwnProperty()Checks if the property exists on the object itself, not its prototype&lt;/p&gt;
&lt;h3 id=&quot;debugging-prototype-issues&quot;&gt;Debugging Prototype Issues&lt;/h3&gt;
&lt;p&gt;Use DevTools in your browser to inspect prototype chains.&lt;/p&gt;
&lt;p&gt;Try these in the console:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Object.getPrototypeOf(obj);
obj.hasOwnProperty('prop');
console.dir(obj);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;conclusion-2&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Understanding how JavaScript handles prototypes gives you the power to write clean, reusable, and performant code.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every object in JS has a prototype, forming a chain&lt;/li&gt;
&lt;li&gt;Inheritance flows up the prototype chain&lt;/li&gt;
&lt;li&gt;Constructor functions and class use prototypes&lt;/li&gt;
&lt;li&gt;Prototypes help reduce memory usage and improve structure&lt;/li&gt;
&lt;li&gt;Don’t manually tinker with &lt;code&gt;__proto__&lt;/code&gt; — use proper patterns&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re still thinking only in classes, you’re missing JavaScript’s true inheritance model.&lt;/p&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/3567/understanding-javascript-prototypes-how-inheritance-works</guid>
<pubDate>Sat, 28 Jun 2025 10:38:24 +0000</pubDate>
</item>
<item>
<title>Turn Your Vue Web App into a Mobile App (Android &amp; iOS) in Just 5 Minutes</title>
<link>https://coderlegion.com/3431/turn-your-vue-web-app-into-a-mobile-app-android-ios-in-just-5-minutes</link>
<description>&lt;p&gt;In this quick tutorial, I’ll show you how to use CapacitorJS to convert your existing Vue.js web app into a fully functional mobile app for Android and iOS — without rewriting your codebase.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://youtu.be/ursT2sV3Hq8?si=BkmVvXcsWxGe0-Ph&quot;&gt;▶️ Watch the full tutorial here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This method is the fastest way to bring your frontend skills to mobile platforms using tools you already know.&lt;/p&gt;
&lt;p&gt;Commands Used in This Video:&lt;br&gt;
Install the Capacitor CLI locally&lt;/p&gt;
&lt;p&gt;npm install -D @capacitor/cli&lt;br&gt;
Initialize Capacitor in your Vue project&lt;/p&gt;
&lt;p&gt;npx cap init&lt;br&gt;
Install the required packages&lt;/p&gt;
&lt;p&gt;npm install @capacitor/core @capacitor/ios @capacitor/android&lt;br&gt;
Add native platforms&lt;/p&gt;
&lt;p&gt;npx cap add ios&lt;br&gt;
npx cap add android&lt;br&gt;
Build and sync your app&lt;/p&gt;
&lt;p&gt;npm run build&lt;br&gt;
npx cap sync&lt;br&gt;
Open the native projects in your IDE&lt;/p&gt;
&lt;p&gt;npx cap open ios&lt;br&gt;
npx cap open android&lt;br&gt;
What is CapacitorJS and Why Use It?&lt;br&gt;
CapacitorJS is a modern open-source native runtime developed by the Ionic team. It allows developers to build cross-platform mobile apps using web technologies like HTML, CSS, and JavaScript — without needing to rewrite your app in native languages such as Swift or Kotlin.&lt;/p&gt;
&lt;p&gt;With Capacitor, your web app runs inside a native WebView container, enabling it to function like a true mobile app. Beyond just wrapping your app, Capacitor provides easy access to native device features like the camera, filesystem, geolocation, push notifications, and more through a rich plugin ecosystem.&lt;/p&gt;
&lt;p&gt;Cross-Framework Compatibility&lt;br&gt;
One of Capacitor’s biggest strengths is that it works with any modern JavaScript framework. Whether you are using:&lt;/p&gt;
&lt;p&gt;Vue.js (like in this tutorial)&lt;br&gt;
React&lt;br&gt;
Angular&lt;br&gt;
Svelte&lt;br&gt;
Or even plain vanilla JavaScript&lt;br&gt;
Capacitor can seamlessly integrate with your existing project. This flexibility means you don’t need to change your frontend framework or rewrite your codebase to build mobile apps — just add Capacitor and you’re good to go.&lt;/p&gt;
&lt;p&gt;Why Choose Capacitor Over Other Solutions?&lt;br&gt;
Compared to alternatives like Cordova, Capacitor is:&lt;/p&gt;
&lt;p&gt;More modern and lightweight, built with a focus on web standards and developer experience&lt;br&gt;
Better integrated with native SDKs, giving you easier access to device APIs&lt;br&gt;
Supports live reload and faster development cycles&lt;br&gt;
Actively maintained and backed by the Ionic team, ensuring ongoing support and improvements&lt;br&gt;
How Capacitor Works Under the Hood&lt;br&gt;
Capacitor takes your built web app (the static files you generate when you run npm run build) and packages it inside a native project shell for iOS and Android. This native shell includes:&lt;/p&gt;
&lt;p&gt;A WebView component that loads your web app&lt;br&gt;
A bridge that connects JavaScript code to native device APIs&lt;br&gt;
Native projects that you can open and customize in Xcode (for iOS) or Android Studio (for Android)&lt;br&gt;
This means your app behaves just like a native app on mobile devices but allows you to write your entire UI and logic in web languages.&lt;/p&gt;
&lt;p&gt;What You Need to Get Started&lt;br&gt;
Your web app ready to build (Vue, React, Angular, or vanilla JS)&lt;br&gt;
Node.js and npm installed on your system&lt;br&gt;
Android Studio and/or Xcode installed for running native projects&lt;br&gt;
Basic familiarity with command-line tools&lt;br&gt;
Wrapping Up&lt;br&gt;
Using CapacitorJS, you can quickly turn your existing web app into a mobile app without the overhead of learning native development. This is a huge advantage for web developers looking to expand their reach to mobile users efficiently.&lt;/p&gt;
&lt;p&gt;If you’re comfortable building with Vue (or any JavaScript framework), adding Capacitor to your workflow will open up new possibilities for app distribution on mobile platforms — faster and easier than ever before.&lt;/p&gt;
</description>
<category>Vue Components</category>
<guid isPermaLink="true">https://coderlegion.com/3431/turn-your-vue-web-app-into-a-mobile-app-android-ios-in-just-5-minutes</guid>
<pubDate>Mon, 23 Jun 2025 15:49:53 +0000</pubDate>
</item>
<item>
<title>The Ultimate Front-end Challenge Is Live ON AquaScript</title>
<link>https://coderlegion.com/3396/the-ultimate-front-end-challenge-is-live-on-aquascript</link>
<description>&lt;h4 id=&quot;-design-innovate-amaze-become-the-next-aquascript-champion-&quot;&gt;✨ &lt;strong&gt;Design. Innovate. Amaze. Become the Next AquaScript Champion.&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt; &lt;strong&gt;Frontend Legends, Assemble!&lt;/strong&gt;&lt;br&gt;
The world of AquaScript just dropped a blazing new developer challenge – and this one’s all about bringing movies to life on the web. Get ready to dive into &lt;strong&gt;real API data&lt;/strong&gt;, push your frontend limits, and build a &lt;strong&gt;mind-blowingly modern, fully responsive Movies Web App&lt;/strong&gt; using &lt;strong&gt;AquaScript Movies Data APIs&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt; This is &lt;strong&gt;&lt;em&gt;not just a challenge&lt;/em&gt;&lt;/strong&gt; – it’s your gateway to &lt;strong&gt;dev stardom&lt;/strong&gt;, &lt;strong&gt;portfolio power-ups&lt;/strong&gt;, and &lt;strong&gt;a place in the AquaScript Hall of Fame&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-s-the-challenge-&quot;&gt;What’s the Challenge?&lt;/h3&gt;
&lt;p&gt;Build a &lt;strong&gt;visually stunning, ultra-clean, and fully responsive Movies Website&lt;/strong&gt; using &lt;strong&gt;AquaScript’s official Movies API or Movies+ API&lt;/strong&gt;.&lt;br&gt;
Your job? Create a masterpiece that makes users go &lt;em&gt;“WOW!”&lt;/em&gt; the moment they land.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;Use AquaScript API to pull live movie data&lt;/strong&gt; and present it like a true frontend artist. We’re talking:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grid-based movie layouts ️&lt;/li&gt;
&lt;li&gt;Hover interactions &amp;amp; animations ✨&lt;/li&gt;
&lt;li&gt;Mobile-first responsive magic &lt;/li&gt;
&lt;li&gt;Custom fonts, AquaScript vibes, pro design &lt;/li&gt;
&lt;li&gt;UI polish worthy of Dribbble &lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;you-ve-got-the-tools-&quot;&gt;You’ve Got the Tools:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;AquaScript Movies API&lt;/strong&gt; or &lt;strong&gt;Movies+ API&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;✅ Any frontend stack: HTML, CSS, JavaScript, Bootstrap, jQuery, Tailwind, etc.&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;NO AI-generated code allowed&lt;/strong&gt; – this is about &lt;strong&gt;your real skill&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Pure creativity, real logic, responsive coding&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;the-rules-you-must-follow-&quot;&gt;The Rules You MUST Follow:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Your code must be &lt;strong&gt;clean, readable, and well-structured&lt;/strong&gt; ✅&lt;/li&gt;
&lt;li&gt;Design must be &lt;strong&gt;responsive across all screen sizes&lt;/strong&gt; ✅&lt;/li&gt;
&lt;li&gt;Use only &lt;strong&gt;AquaScript’s API&lt;/strong&gt; (Movies or Movies+) ❗&lt;/li&gt;
&lt;li&gt;Submit your entry via &lt;strong&gt;GitHub repository&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple submissions allowed&lt;/strong&gt; – show us your full potential &lt;/li&gt;
&lt;li&gt;Submit using the official &lt;strong&gt;Challenge Submission Form&lt;/strong&gt; (on AquaScript) &lt;/li&gt;
&lt;li&gt;No late entries will be accepted after the deadline is announced. ⏰&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt; Note: The &lt;strong&gt;submission deadline &amp;amp; winner announcement date&lt;/strong&gt; will be shared soon. Start building now!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;prizes-that-level-you-up-like-crazy-&quot;&gt;Prizes That Level You Up Like Crazy:&lt;/h3&gt;
&lt;h4 id=&quot;first-place-winner-&quot;&gt;&lt;strong&gt;First Place Winner:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Custom Domain – Own your dev identity&lt;/li&gt;
&lt;li&gt;Free Promotion on AquaScript Platform&lt;/li&gt;
&lt;li&gt;10 Pro Web Templates&lt;/li&gt;
&lt;li&gt;Personalized Dev Portfolio&lt;/li&gt;
&lt;li&gt;Hackathon Time Capsule Feature&lt;/li&gt;
&lt;li&gt;Mini Workshop Hosting Opportunity&lt;/li&gt;
&lt;li&gt;⚡ AquaScript Dev Boost Pack&lt;/li&gt;
&lt;li&gt;Official “AquaScript Champion” Badge (PNG + HTML Embed)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;second-place-&quot;&gt;&lt;strong&gt;Second Place:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Free Promotion on AquaScript&lt;/li&gt;
&lt;li&gt;10 Pro Web Templates&lt;/li&gt;
&lt;li&gt;Personalized Portfolio&lt;/li&gt;
&lt;li&gt;Hackathon Time Capsule Feature&lt;/li&gt;
&lt;li&gt;⚡ AquaScript Dev Boost Pack&lt;/li&gt;
&lt;li&gt;Official Badge&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h4 id=&quot;third-place-&quot;&gt;&lt;strong&gt;Third Place:&lt;/strong&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Free Promotion&lt;/li&gt;
&lt;li&gt;10 Pro Web Templates&lt;/li&gt;
&lt;li&gt;Personalized Portfolio&lt;/li&gt;
&lt;li&gt;Hackathon Time Capsule Entry&lt;/li&gt;
&lt;li&gt;Official Badge&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;submission-portal-&quot;&gt;Submission Portal:&lt;/h3&gt;
&lt;p&gt;Head to &lt;a rel=&quot;nofollow&quot; href=&quot;https://aquascript.xyz&quot;&gt; https://aquascript.xyz&lt;/a&gt; → Find the &lt;strong&gt;Submission Form&lt;/strong&gt;&lt;br&gt;
Make sure your GitHub repo is clean, public, and includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Live Preview Link (if deployed)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt; with clear instructions&lt;/li&gt;
&lt;li&gt;Technologies Used&lt;/li&gt;
&lt;li&gt;Screenshots (optional but impressive)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;questions-&quot;&gt;Questions?&lt;/h3&gt;
&lt;p&gt;Need help understanding the APIs or how to get started? Want to partner or collaborate?&lt;br&gt;
 Contact the AquaScript Team directly via the site or social platforms.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;are-you-the-next-frontend-icon-&quot;&gt;Are You the Next Frontend Icon?&lt;/h3&gt;
&lt;p&gt;Whether you’re a beginner looking to rise, or a pro dev ready to dominate – this is your moment.&lt;br&gt;
Push pixels. Fetch data. Animate interfaces.&lt;br&gt;
&lt;strong&gt;Build the Movies Experience the world hasn’t seen yet.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt; Challenge is officially live – &lt;strong&gt;Start Now. Build Bold. Win Big.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;Shine bright, AquaScript Champion &lt;br&gt;
— &lt;em&gt;Team AquaScript&lt;/em&gt;&lt;/p&gt;
</description>
<category>Personal Branding</category>
<guid isPermaLink="true">https://coderlegion.com/3396/the-ultimate-front-end-challenge-is-live-on-aquascript</guid>
<pubDate>Sun, 22 Jun 2025 09:21:43 +0000</pubDate>
</item>
<item>
<title>Code Rain’s Revelation: Embracing Existence Before Perfection</title>
<link>https://coderlegion.com/3170/code-rains-revelation-embracing-existence-before-perfection</link>
<description>&lt;p&gt;I would like to start this article by thanking the editorial team of &lt;a rel=&quot;nofollow&quot; href=&quot;https://javascript.plainenglish.io/&quot;&gt;JavaScript in Plain English&lt;/a&gt; for &lt;a rel=&quot;nofollow&quot; href=&quot;https://medium.com/p/99f68dd05f09&quot;&gt;featuring my previous article&lt;/a&gt; on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/jeffrey04/vibe-coding-storytelling-and-llms-a-collaborative-approach-2l4h&quot;&gt;setting up a LLM chatbot as my editor&lt;/a&gt;. Within the article I mentioned turning the final draft into a script for video production, and I am in the process of finally taking the plunge. Now that I have the script done, what else is needed? Let’s start by building a short intro animation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*WnCDxQARlXzYPYXi79f-ZA.png&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;em&gt;A cute illustration from Copilot on the topic&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;my-unexpected-journey-why-a-video-intro-&quot;&gt;My Unexpected Journey: Why a Video Intro?&lt;/h4&gt;
&lt;p&gt;Despite hearing the suggestion numerous times, I never really considered going the video production route. The main reason was stated in the featured article — I am not ready to commit to a periodic release. Fast-forward to last weekend, I decided to publish &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/jeffrey04/dao-of-functional-programming-chapter-1-clean-state-n98&quot;&gt;my study notes&lt;/a&gt; on the book titled &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/BartoszMilewski/DaoFP&quot;&gt;Dao of Functional Programming&lt;/a&gt;. Due to the complexity, I could only do it on an irregular basis. After publishing the first chapter, the implication became a big “Why not?” hovering in my mind.&lt;/p&gt;
&lt;p&gt;Most of my recent articles are structured as a story writing project, including &lt;a rel=&quot;nofollow&quot; href=&quot;https://kitfucoda.medium.com/the-unchaining-my-personal-journey-graduating-from-jquery-to-modern-javascript-ca74a93a7b33&quot;&gt;the one published last week&lt;/a&gt;. After publishing the article, I had the LLM chatbot assemble a video script out of the final draft. The proposed script, just as my previous attempts, appeared very actionable. After giving it a thought, I decided to bite the bullet.&lt;/p&gt;
&lt;p&gt;As a sidenote, I definitely can see the appeal of the LLM especially for people working solo.&lt;/p&gt;
&lt;p&gt;Though I may not be able to finish the video in time, I read through the script to figure out the needed components for a video. First thing I noticed is a short intro sequence. Shouldn’t be too difficult, I figured, there should be a generator somewhere over the Internet. Let’s quickly make one and be done with it. However, after some failed attempts with the LLM video generator, I decided to just make a simple animated sequence myself.&lt;/p&gt;
&lt;p&gt;A code raining effect inspired by The Matrix, how hard can it be, right?&lt;/p&gt;
&lt;p&gt;After checking through my weekly TODO, I only had one take-home assignment for a job application. Considering I did not have much idea on how to do it, I allocated a day for that. The point was getting a usable version out anyway. Fortunately, it was not that difficult, I managed to whip out a version with &lt;a rel=&quot;nofollow&quot; href=&quot;https://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://lodash.com/&quot;&gt;lodash&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; href=&quot;https://chancejs.com/&quot;&gt;Chance.js&lt;/a&gt; within a day.&lt;/p&gt;
&lt;p&gt;Yes, it is a simple web application.&lt;/p&gt;
&lt;p&gt;On the other hand, I find the project more interesting than the coding take-home assignment I did the next day. Most of these assignments are about creating a prototype website involving a variation of CRUD (Create, Retrieve, Update, Delete) operations from scratch. Usually that would take 2–3 days end-to-end but I often allocate at most a day and a half for them.&lt;/p&gt;
&lt;p&gt;On the other end of the spectrum, we have overly extensive assignments that even the hiring company would expect more than a day of work. Job applicants are often not being paid for the work (hence my 1 day allocation), but in this climate many would still submit their work without compensation. Alongside other problems shared by many fellow engineers when applying jobs, it prompted me to rethink my strategy.&lt;/p&gt;
&lt;p&gt;This blog &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/jeffrey04/beyond-the-code-a-lunar-new-year-reflection-on-career-recovery-and-new-beginnings-l77&quot;&gt;was started&lt;/a&gt; as my part of a longer-term plan, exploring options outside software engineering. Recently it turned into an instrument I use to improve my visibility in the job market, showcasing my ability to hopefully avoid take-home assignment in future applications. Being featured in a well-established article is a very unexpected confidence boost, and I can’t express my gratitude enough for that.&lt;/p&gt;
&lt;p&gt;Though it is equally important to acknowledge oneself internally.&lt;/p&gt;
&lt;p&gt;While I still send out applications and meet folks for the possibility of collaboration, publishing content regularly is becoming a complement to my job hunting strategy. Producing video, in a way can be seen as an extension to all the technical writing I am doing here in this blog. A friend calls this “signalling”, but to me it is more an attempt to adapt.&lt;/p&gt;
&lt;h4 id=&quot;the-good-enough-code-rain-starting-the-build&quot;&gt;The “Good Enough” Code Rain: Starting the Build&lt;/h4&gt;
&lt;p&gt;One common problem I often observe in life is that people often ask the wrong question “is it good?”, when there is nothing to improve on. This could be an oversimplification of life problems, but in my point of view, most things in life often boils down to either &lt;em&gt;“does it exist”&lt;/em&gt; or &lt;em&gt;“is it good?”&lt;/em&gt;. Both these questions are distinct from each other, but apparently enough people have a problem differentiating the two.&lt;/p&gt;
&lt;p&gt;If there is one thing I learn, after meeting all the people approaching for project collaboration, that would be that ideas are worthless unless executed. There is never a shortage of brilliant ideas, the thing that is lacking is the will to bring them to reality. A conceived idea will inevitably grow over time and gets so ambitious such that it is close to impossible to begin working on it.&lt;/p&gt;
&lt;p&gt;We do have a different name for this phenomenon — daydreaming.&lt;/p&gt;
&lt;p&gt;The right question to start asking, in my humble opinion, is always “does it exist?”. In the case we are discussing today, it would be about the components of a video. There is none at the moment, so let’s start the collection and building. If the generator is not giving me the intro animation I wanted, then just build one myself, answer the existential question first.&lt;/p&gt;
&lt;p&gt;And I did.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*1LtNHl9dxBww6n-4bNLEBw.gif&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;em&gt;The crude initial version&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It was a fairly simple animation featuring the code rain, ending with a display of the name of the channel. As mentioned earlier, it worked right away, which was good enough as a quick and dirty hack. Next the clip was uploaded t̶o̶ ̶s̶h̶o̶w̶ ̶o̶f̶f̶ ̶m̶y̶ ̶1̶3̶3̶7̶ ̶h̶a̶c̶k̶i̶n̶g̶ ̶s̶k̶i̶l̶l̶ to collect feedback from peers.&lt;/p&gt;
&lt;p&gt;“Is it good enough?” should usually be asked, after answering the first “does it exist?” question. I fully expected to revisit the animation, addressing this question much later. In spite of that, Meta threw me a curveball after it ate my clips, returning an error saying I violate some rules. The linked help topic was a generic document on how to post videos.&lt;/p&gt;
&lt;p&gt;Typical Meta, surprise surprise.&lt;/p&gt;
&lt;p&gt;That prompted an immediate revision to the animation. If Meta doesn’t like the short clip, it means any uploaded videos containing the clip would be banned as well. To a certain extent, this is a blessing in disguise, I did receive feedback, though in the most unexpected way. Imagine how devastating this could be if I spent my whole life planning for it, only to find the work banned right away.&lt;/p&gt;
&lt;p&gt;There are indeed rare occasions where these two should be considered in parallel. Yet, for most cases, where time and resources are limited, the two questions should be addressed separately, in the right order. We can spend our lifetime pondering how things can be perfected, but it changes nothing if no work is being laid out.&lt;/p&gt;
&lt;p&gt;Existence != Perfection&lt;/p&gt;
&lt;h4 id=&quot;crafting-the-rain-modules-events-and-iteration&quot;&gt;Crafting the Rain: Modules, Events, and Iteration&lt;/h4&gt;
&lt;p&gt;This is the meta-approved (for now) version.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*1pzpqDBBPV-it6b2fToQtQ.gif&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;em&gt;Meta-approved revision&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Still based on the same code rain animation, but I am turning the channel name display into an ASCII art, and including the display of a video title. An outro is also added so it doesn’t end abruptly. Let’s discuss the implementation a little bit.&lt;/p&gt;
&lt;p&gt;Coders writing for Node.js should be familiar with the &lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules&quot;&gt;module syntax&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules&quot;&gt;,&lt;/a&gt;,) shown below:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import defaultExport from './someModule';
import { otherExport } from './someModule';

const bar = 'bar';

export function foo() {
    ...
}

export default bar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Frontend development gets increasingly more complex over time. Gone are the days where all the frontend logic is expressed within one script alone. As the complexity grows, the amount of code also increases. Separating them into smaller parts eventually becomes a necessity.&lt;/p&gt;
&lt;p&gt;So the module syntax is a welcome change, though I only knew the support was ported to the browser while I was porting grid-maker last week. All it needs is to change the  tag’s type attribute to module.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;module&quot; src=&quot;./someModule.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, you can just put the code inline&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;script type=&quot;module&quot;&amp;gt;
import defaultExport from './someModule`;
import { otherExport } from './someModule';

const bar = 'bar';
export function foo() {
    ...
}
export default bar
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No more multiple  tags just to import different libaries, we now do it with the import statements, as it also supports importing from a URL. For example, to import functions from lodash, we write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import {
range,
reverse,
} from &quot;https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/lodash.min.js&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The intro animation script was largely &lt;a rel=&quot;nofollow&quot; href=&quot;https://kitfucoda.medium.com/the-unchaining-my-personal-journey-graduating-from-jquery-to-modern-javascript-ca74a93a7b33&quot;&gt;inspired by the&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://kitfucoda.medium.com/the-unchaining-my-personal-journey-graduating-from-jquery-to-modern-javascript-ca74a93a7b33&quot;&gt;grid-maker remake&lt;/a&gt;. Any changes to the DOM would be initiated by event triggerings. So we are making a rather simple code rain animation in a 2D grid of monospaced characters. A “raindrop” effect is just a column of characters in the grid “activated” (fading in and out) one after another. We could chain all these activations together in a sequence of nested recursive function calls, risking blowing the stack if the number of rows increases.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function activate_rain(char_in_grid) {
  const downstair_char = find_downstair_char(char_in_grid)

  do_the_animation(char_in_grid)

  if (downstair_char) {
    activate(downstair_char)
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, we could let each activation trigger another activation below it by dispatching an event.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function activate_rain(event) {
  const elem = $(event.target);

  do_the_animation(elem);

  find_downstair_char(elem).trigger(&quot;block:activate:rain&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I did this in jQuery despite last week’s article, mainly because this is not meant to be deployed in a production environment. The function activate_rain was registered as a listener to the block:activate:rain, therefore firing the same event (after a delay) for the neighbour. The function exits after the dispatching of event, removing the risk of stack overflow. In the actual implementation, I also added a delay through setTimeout to the event dispatching to adjust the downward speed of a raindrop.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;setTimeout(() =&amp;gt; find_downstair_char(elem).trigger(&quot;block:activate:rain&quot;), 100);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The full implementation can be &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Jeffrey04/kitfucoda-intro&quot;&gt;reviewed at my GitHub repository&lt;/a&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Jeffrey04/kitfucoda-intro&quot;&gt;.&lt;/a&gt;.) Feel free to adapt and play with it. You may want to find a way to start a web server to serve the page to test it in your browser.&lt;/p&gt;
&lt;h4 id=&quot;the-code-rain-s-enduring-lesson-execute-first-then-refine&quot;&gt;The Code Rain’s Enduring Lesson: Execute First, Then Refine&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/1024/1*1pzpqDBBPV-it6b2fToQtQ.gif&quot; alt=&quot;&quot;&gt;&lt;br&gt;
&lt;em&gt;My editor insisted this is needed again here.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Initially I intended this to be a quick article on the making of the animation for the video production side-project. However the scope of the article grew when I was organizing my thoughts. For some reason it reminded me of a quick exchange on the two questions “does it exist?” and “is it good?” with my mentor not too long ago.&lt;/p&gt;
&lt;p&gt;We live in a very short-tempered world, where we expect things out fast and good. Sometimes it gets really easy to forget the difference between the two, especially when deadlines are approaching. Mixing the two up in such cases would inevitably generate a huge amount of stress. Even I find myself caught in situations like this before.&lt;/p&gt;
&lt;p&gt;The unexpected connection between my simplistic problem-solving view and the animation-making process was a surprising discovery. If the banning accident did not happen, I wouldn’t be able to make the connection, and we would read a very different article this week. Despite a round of revision, there are still numerous improvements I hope to achieve with it. Still, having it done checks an item of my TODO for a final video.&lt;/p&gt;
&lt;p&gt;I will pick an older article, and produce a video out of it with the help of LLM drafting the script. As it is going to be irregular, the review will come a little bit later, perhaps until I am more comfortable with the workflow. For now stay tuned, and thanks for reading this far. I shall meet you in my writing again, next week.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;While an AI editorial assistant helped refine this article’s language and structure, please know that my voice, ideas, and all code are entirely my own work. If &lt;a rel=&quot;nofollow&quot; href=&quot;https://kitfucoda.medium.com/&quot;&gt;KitFu Coda&lt;/a&gt; sparks your interest, feel free to reach out for job opportunities or project collaborations directly on &lt;a rel=&quot;nofollow&quot; href=&quot;https://kitfucoda.medium.com/&quot;&gt;Medium&lt;/a&gt; or via &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.linkedin.com/in/jeffrey04/&quot;&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;
</description>
<category>JavaScript</category>
<guid isPermaLink="true">https://coderlegion.com/3170/code-rains-revelation-embracing-existence-before-perfection</guid>
<pubDate>Tue, 27 May 2025 06:39:56 +0000</pubDate>
</item>
</channel>
</rss>