<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Victor Williams — Blog]]></title><description><![CDATA[Tech-savvy front-end engineer and product designer with 1+ years of experience. Always learning new skills and exploring the latest tech trends. In my free time, I enjoy listening to UK Drill and RnB.]]></description><link>https://blog.victorwilliams.me</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1681318415688/OjN3VOJKs.png</url><title>Victor Williams — Blog</title><link>https://blog.victorwilliams.me</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 07 Jun 2026 13:39:55 GMT</lastBuildDate><atom:link href="https://blog.victorwilliams.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How to create exit animations with Framer Motion]]></title><description><![CDATA[Framer Motion is a powerful library built on top of React that simplifies the creation of animations within your user interface. While core React functionality allows for animations and transitions using CSS, Framer Motion offers a more feature-rich ...]]></description><link>https://blog.victorwilliams.me/how-to-create-exit-animations-with-framer-motion</link><guid isPermaLink="true">https://blog.victorwilliams.me/how-to-create-exit-animations-with-framer-motion</guid><category><![CDATA[React]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[vite]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[framer-motion]]></category><category><![CDATA[animation]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[CSS]]></category><dc:creator><![CDATA[Victor Williams]]></dc:creator><pubDate>Fri, 10 May 2024 13:12:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1715345723909/c71d9691-fe4c-4302-b1cb-d9dca77a99b5.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Framer Motion is a powerful library built on top of React that simplifies the creation of animations within your user interface. While core React functionality allows for animations and transitions using CSS, Framer Motion offers a more feature-rich toolset designed to implement dynamic and performant animations.</p>
<p>In this article, you'll learn how to implement exit animations using the <code>exit</code> prop and the <code>AnimatePresence</code> component. We'll progressively build upon this foundation, demonstrating how to create more advanced exit animations with custom transitions and delayed effects. At the end of this, you'll build a simple pop-up modal using all you learn. I hope you have a lovely read.</p>
<h2 id="heading-get-started">Get Started</h2>
<p><strong>Prerequisites:</strong></p>
<ul>
<li><p>Node.js and npm (or yarn) installed on your system.</p>
</li>
<li><p>An existing React project.</p>
</li>
<li><p>Basic knowledge of Framer Motion</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">For this guide, we'll use a React-TypeScript project and Tailwind CSS for styling. While these are my preferred choices, you can tailor the setup to your existing project or preferences. To follow along with the guide, you can clone the demo's <a target="_blank" href="https://github.com/victorcodess/exit-animation-modal">source code</a> as well.</div>
</div>

<ol>
<li><strong>Install Framer Motion:</strong></li>
</ol>
<p>In your project directory, install Framer Motion using either npm or yarn:</p>
<p><strong>Using npm:</strong></p>
<pre><code class="lang-plaintext">npm install framer-motion
</code></pre>
<p><strong>Using yarn:</strong></p>
<pre><code class="lang-plaintext">yarn add framer-motion
</code></pre>
<ol start="2">
<li><strong>Create a basic component:</strong></li>
</ol>
<p>Let's create a simple component to play around with. Inside the <code>src</code> folder, create a new file named <code>my-component.tsx</code>. Here's a basic structure for our component:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;div className=<span class="hljs-string">"w-20 h-20 bg-green-600 rounded-full cursor-pointer"</span> /&gt;  
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> MyComponent;
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715292325360/f551c6e6-3d6b-4bc5-8cdf-68197ff1d08f.png" alt class="image--center mx-auto" /></p>
<ol start="3">
<li><strong>Import Framer Motion:</strong></li>
</ol>
<p>To make your component move with Framer Motion, you need to import the <code>motion</code> component. Update your <code>my-component.tsx</code> file to include this line at the top:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { motion } <span class="hljs-keyword">from</span> <span class="hljs-string">'framer-motion'</span>;
</code></pre>
<p>The <code>motion</code> import from <code>framer-motion</code> lets you convert an ordinary HTML tag like <code>div</code> to a <code>motion.div</code> tag that allows you to animate your React elements.</p>
<p>There you have it! You now have a basic React project set up with Framer Motion and are ready to create awesome exit animations!</p>
<h2 id="heading-can-css-handle-exit-animations">Can CSS Handle Exit Animations?</h2>
<p>Sure, CSS transitions seem like a natural fit for exit animations in React at first glance. You can define styles for an element and smoothly transition them to disappear, creating a fade-out or slide-out effect.</p>
<p>However, here's the catch: When you try to hide a React component during an exit animation using CSS, you run into a roadblock. React, by design, removes components from the Document Object Model (DOM) entirely when they are hidden. This removal from the DOM makes them unavailable for animation by CSS. CSS transitions rely on manipulating elements within the DOM, so a removed element can't be smoothly animated.</p>
<p>This presents a challenge for basic exit animations with CSS in React. While CSS might seem viable, it can't handle the core functionality of animating a disappearing component due to React's behavior. This is where Framer Motion steps in, offering a solution specifically designed for handling animations alongside React's component lifecycle.</p>
<h2 id="heading-using-animatepresence">Using AnimatePresence</h2>
<p>Remember, React entirely removes hidden components from the Document Object Model (DOM). This disrupts the animation process if you directly apply exit animations. <code>AnimatePresence</code> solves this challenge by acting as a wrapper around your components.</p>
<h3 id="heading-how-to-use-animatepresence"><strong>How to use</strong> <code>AnimatePresence</code><strong>:</strong></h3>
<ol>
<li><p><strong>Define the Exit Animation:</strong></p>
<ul>
<li>We start by defining the exit animation itself using the <code>exit</code> prop within Framer Motion variants. This prop specifies the animation that plays when the component exits the scene.</li>
</ul>
</li>
</ol>
<p>Here's an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> exitAnimation = {
  opacity: <span class="hljs-number">0</span>, <span class="hljs-comment">// Fade out to zero opacity</span>
};
</code></pre>
<ol start="2">
<li><p><strong>Wrap with</strong> <code>AnimatePresence</code><strong>:</strong></p>
<p> Next, we wrap our components with <code>AnimatePresence</code>. This ensures that even when a component is hidden, it remains in the DOM momentarily, allowing Framer Motion to complete the exit animation before it's truly removed.</p>
</li>
</ol>
<p>Here's how it looks in practice:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { AnimatePresence } <span class="hljs-keyword">from</span> <span class="hljs-string">'framer-motion'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [visible, setVisible] = useState(<span class="hljs-literal">true</span>);

  <span class="hljs-keyword">const</span> exitAnimation = {
    opacity: <span class="hljs-number">0</span>, <span class="hljs-comment">// Fade out to zero opacity</span>
  };

  <span class="hljs-keyword">return</span> (
    &lt;AnimatePresence&gt;
      {visible &amp;&amp; (
        &lt;motion.div
          exit={exitAnimation}
          className=<span class="hljs-string">"w-20 h-20 bg-green-600 rounded-full cursor-pointer"</span>
          onClick={<span class="hljs-function">() =&gt;</span> setVisible(<span class="hljs-literal">false</span>)}
        /&gt;
      )}
    &lt;/AnimatePresence&gt;
  );
}
</code></pre>
<p><strong>With</strong> <code>AnimatePresence</code><strong>:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715293939791/1c72de9a-a8c5-4d3e-8c73-1dcacc5b0a99.gif" alt class="image--center mx-auto" /></p>
<p><strong>Without</strong> <code>AnimatePresence</code><strong>:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715202267718/0a85075f-95d2-4567-a70c-9f7a5b47739b.gif" alt class="image--center mx-auto" /></p>
<p>In this example:</p>
<ul>
<li><p>We wrap the <code>motion.div</code> with <code>AnimatePresence</code>.</p>
</li>
<li><p>The <code>motion.div</code> has the defined <code>exitAnimation</code> applied using the <code>exit</code> prop, which fades out the element.</p>
</li>
<li><p>When the component is clicked (toggling <code>visible</code> to <code>false</code>), AnimatePresence ensures the exit animation plays before removing the element from the DOM.</p>
</li>
</ul>
<p>This is just a basic example, of course. Framer Motion allows you to animate various properties like opacity, scale, translate (position), and more, giving you the freedom to create a wide variety of exit animations.</p>
<h2 id="heading-advanced-exit-animations">Advanced Exit Animations</h2>
<p>We've explored the basics of defining exit animations with Framer Motion. Now, let's learn some advanced techniques to create better exit animations:</p>
<ol>
<li><h3 id="heading-fine-tune-with-custom-transitions"><strong>Fine-tune with Custom Transitions:</strong></h3>
</li>
</ol>
<p>The <code>transition</code> property within the <code>exitAnimation</code> object offers even more control over your animation. You can define custom easing functions to control the speed and flow of the animation:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> exitAnimation = {
  opacity: <span class="hljs-number">0</span>,
  transition: { duration: <span class="hljs-number">0.5</span>, ease: <span class="hljs-string">"easeInOut"</span> }, <span class="hljs-comment">// Use "easeInOut" for smooth start and end</span>
};
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715294238910/15c363df-fdf1-4a82-b229-7005fef2cd00.gif" alt class="image--center mx-auto" /></p>
<p>Here, we've added the <code>ease: "easeInOut"</code> property to the <code>transition</code>. This tells the animation to ease in and out smoothly, creating a more natural feel.</p>
<ol start="2">
<li><h3 id="heading-combining-multiple-animation-properties"><strong>Combining Multiple Animation Properties:</strong></h3>
</li>
</ol>
<p>Don't limit yourself to a single animation property! Framer Motion allows you to combine multiple properties within your <code>exitAnimation</code> object:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">const</span> exitAnimation = {
  opacity: <span class="hljs-number">0</span>,
  x: <span class="hljs-string">"-100vw"</span>, <span class="hljs-comment">// Slide off-screen to the left</span>
  rotate: <span class="hljs-number">90</span>, <span class="hljs-comment">// Rotate 90 degrees</span>
  transition: { duration: <span class="hljs-number">0.7</span> },
};
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715263506883/2e56cafe-4914-4acf-9b3a-2c9988635ea0.gif" alt class="image--center mx-auto" /></p>
<p>In this example, we're fading out the component (<code>opacity: 0</code>), sliding it off-screen to the left (<code>x: "-100vw"</code>), and adding a 90-degree clockwise rotation (<code>rotate: 90</code>) for a more dramatic exit.</p>
<ol start="3">
<li><h3 id="heading-delayed-exits-for-multiple-elements"><strong>Delayed Exits for Multiple Elements:</strong></h3>
</li>
</ol>
<p>An exit animation can become even more engaging when applied to multiple elements. Framer Motion offers two techniques to create a cascading or wave-like effect: individual delays and stagger.</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">MyComponent</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [visible, setVisible] = useState(<span class="hljs-literal">true</span>);

  <span class="hljs-keyword">const</span> exitAnimationParent = {
    opacity: <span class="hljs-number">0</span>,
    x: <span class="hljs-string">"-25vw"</span>,
    rotate: <span class="hljs-number">90</span>,
    transition: {
      duration: <span class="hljs-number">0.5</span>,
      ease: <span class="hljs-string">"easeInOut"</span>,
      delay: <span class="hljs-number">0.5</span>,
    },
  };

  <span class="hljs-keyword">const</span> exitAnimationChild = {
    opacity: <span class="hljs-number">0</span>,
    x: <span class="hljs-string">"25vw"</span>,
    rotate: <span class="hljs-number">90</span>,
  };

  <span class="hljs-keyword">return</span> (
    &lt;AnimatePresence&gt;
      {visible &amp;&amp; (
        &lt;motion.div
          exit={exitAnimationParent}
          className=<span class="hljs-string">"w-20 h-20 bg-green-600 cursor-pointer rounded-2xl flex justify-evenly items-center"</span>
          onClick={<span class="hljs-function">() =&gt;</span> setVisible(<span class="hljs-literal">false</span>)}
        &gt;
          &lt;motion.div
            exit={exitAnimationChild}
            transition={{ duration: <span class="hljs-number">0.5</span>, ease: <span class="hljs-string">"easeInOut"</span>, delay: <span class="hljs-number">0.2</span> }}
            className=<span class="hljs-string">"w-7 h-7 bg-white  rounded cursor-pointer"</span>
          /&gt;
          &lt;motion.div
            exit={exitAnimationChild}
            transition={{ duration: <span class="hljs-number">0.5</span>, ease: <span class="hljs-string">"easeInOut"</span> }}
            className=<span class="hljs-string">"w-7 h-7 bg-white rounded cursor-pointer"</span>
          /&gt;
        &lt;/motion.div&gt;
      )}
    &lt;/AnimatePresence&gt;
  );
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715275016571/66873ed3-a148-4c79-abce-d63978e263a8.gif" alt class="image--center mx-auto" /></p>
<p>The provided component demonstrates delayed exits for two child elements within a parent container. Here's a breakdown of what's going on:</p>
<ol>
<li><p><strong>Parent Container Animation:</strong></p>
<ul>
<li><p>The parent container (<code>motion.div</code>) uses the <code>exitAnimationParent</code> variant. The animation properties and configuration remain the same:</p>
<ul>
<li><p>Fades the container out with <code>opacity: 0</code>.</p>
</li>
<li><p>Slides the container off-screen by 25 viewports to the left with <code>x: "-25vw"</code>.</p>
</li>
<li><p>Rotate the container 90 degrees clockwise with <code>rotate: 90</code>.</p>
</li>
<li><p>The animation has a duration of 0.5 seconds, uses an "easeInOut" easing function, and has a delay of 0.5 seconds before starting.</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Child Element Animations:</strong></p>
<ul>
<li><p>Each child element (<code>motion.div</code>) still uses the <code>exitAnimationChild</code> variant defining opacity and x-axis translation.</p>
</li>
<li><p>However, the key difference is the individual <code>transition</code> prop for each child.</p>
<ul>
<li><p>The first child element now has a slight delay of 0.2 seconds within its transition.</p>
</li>
<li><p>The second child element retains the original transition properties (0.5 seconds duration and "easeInOut" easing).</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>These are just a few ways to create advanced exit animations with Framer Motion. While individual delays create a cascading effect, Framer Motion offers a more scalable approach for complex scenarios: <code>staggerChildren</code> and <code>delayChildren</code>. We won't cover those in this tutorial.</p>
<h2 id="heading-building-a-modal-component-with-exit-animation">Building a Modal Component with Exit Animation</h2>
<p>Modal components are a common UI element for displaying additional content or functionality within an overlay. With Framer Motion, we can add a touch of polish with a smooth exit animation when the modal is dismissed.</p>
<p>A modal component typically consists of two parts:</p>
<ul>
<li><p><strong>Backdrop:</strong> A dimmed background element that creates a visual distinction between the modal and the rest of the application content.</p>
</li>
<li><p><strong>Modal Content:</strong> The main content area displayed within the modal, often containing information, forms, or interactive elements.</p>
</li>
</ul>
<h3 id="heading-creating-the-modal-component"><strong>Creating the Modal Component:</strong></h3>
<p>Here's a basic structure for our modal component with Framer Motion:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { motion } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;

<span class="hljs-keyword">interface</span> ModalProps {
  setShowModal: <span class="hljs-function">(<span class="hljs-params">showModal: <span class="hljs-built_in">boolean</span></span>) =&gt;</span> <span class="hljs-built_in">void</span>;
}

<span class="hljs-keyword">const</span> Modal = <span class="hljs-function">(<span class="hljs-params">{ setShowModal }: ModalProps</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    &lt;motion.div
      className=<span class="hljs-string">"overflow-y-auto overflow-x-hidden fixed top-0 bottom-0 mx-auto my-auto right-0 left-0 z-50 justify-center items-center w-full bg-black/50 md:inset-0 flex"</span>
      initial={{ opacity: <span class="hljs-number">0</span> }}
      animate={{ opacity: <span class="hljs-number">1</span> }}
      exit={{ opacity: <span class="hljs-number">0</span> }}
    &gt;
      &lt;motion.div
        className=<span class="hljs-string">"h-[270px] w-full relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl sm:my-8 sm:w-full sm:max-w-lg flex flex-col items-center justify-center px-4 pb-4 pt-5 sm:p-6 sm:pb-4 gap-5"</span>
        initial={{ scale: <span class="hljs-number">0.5</span> }}
        animate={{ scale: <span class="hljs-number">1</span> }}
        exit={{ scale: <span class="hljs-number">0</span> }}
      &gt;
        &lt;div className=<span class="hljs-string">"bg-green-100 rounded-full p-3"</span>&gt;
          &lt;svg
            xmlns=<span class="hljs-string">"http://www.w3.org/2000/svg"</span>
            fill=<span class="hljs-string">"none"</span>
            viewBox=<span class="hljs-string">"0 0 24 24"</span>
            stroke-width=<span class="hljs-string">"1.5"</span>
            stroke=<span class="hljs-string">"currentColor"</span>
            aria-hidden=<span class="hljs-string">"true"</span>
            className=<span class="hljs-string">"text-green-700 w-6 h-6"</span>
          &gt;
            &lt;path
              stroke-linecap=<span class="hljs-string">"round"</span>
              stroke-linejoin=<span class="hljs-string">"round"</span>
              d=<span class="hljs-string">"M4.5 12.75l6 6 9-13.5"</span>
            &gt;&lt;/path&gt;
          &lt;/svg&gt;
        &lt;/div&gt;
        &lt;h4 className=<span class="hljs-string">"font-semibold text-lg"</span>&gt;Payment successful&lt;/h4&gt;
        &lt;p className=<span class="hljs-string">"text-center w-[300px] -mt-2 leading-snug text-gray-600"</span>&gt;
          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sit esse
          dolorem officia.
        &lt;/p&gt;
        &lt;button
          <span class="hljs-keyword">type</span>=<span class="hljs-string">"button"</span>
          className=<span class="hljs-string">"inline-flex w-full justify-center rounded-md bg-[#4f46e5] px-3 py-2 text-white shadow-sm hover:bg-[#3f38b5] transition-colors text-md font-bold "</span>
          onClick={<span class="hljs-function">() =&gt;</span> setShowModal(<span class="hljs-literal">false</span>)}
        &gt;
          Close modal
        &lt;/button&gt;
      &lt;/motion.div&gt;
    &lt;/motion.div&gt;
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> Modal;
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><p><strong>Initial State:</strong> The modal content starts with <code>opacity: 0</code> (invisible) and a <code>scale: 0.5</code> (scaled down to 50%).</p>
</li>
<li><p><strong>Animate State:</strong> When the modal opens, the content animates to <code>opacity: 1</code> (fully visible) and <code>scale: 1</code> (normal size).</p>
</li>
<li><p><strong>Exit State:</strong> When the modal closes, the content animates back to <code>opacity: 0</code> (invisible) and <code>scale: 0</code> (scaled down), creating a shrinking and fading-out effect.</p>
</li>
</ul>
<h3 id="heading-adding-the-modal-to-your-application"><strong>Adding the Modal to Your Application:</strong></h3>
<p>Now you can integrate this <code>Modal</code> component into your application. Here's an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { AnimatePresence } <span class="hljs-keyword">from</span> <span class="hljs-string">"framer-motion"</span>;
<span class="hljs-keyword">import</span> Modal <span class="hljs-keyword">from</span> <span class="hljs-string">"./modal"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [showModal, setShowModal] = useState(<span class="hljs-literal">false</span>);

  <span class="hljs-keyword">return</span> (
    &lt;div className=<span class="hljs-string">"w-full h-[100vh] flex items-center justify-center relative"</span>&gt;
      &lt;button
        className=<span class="hljs-string">"inline-flex w-full justify-center rounded-md bg-[#4f46e5] px-3 py-2 text-md font-bold text-white shadow-sm hover:bg-[#3f38b5] sm:w-auto"</span>
        onClick={<span class="hljs-function">() =&gt;</span> setOpen(!open)}
      &gt;
        Open modal
      &lt;/button&gt;

      &lt;AnimatePresence&gt;
        {open &amp;&amp; &lt;Modal setOpen={setOpen} /&gt;}
      &lt;/AnimatePresence&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1715268217741/8a0aa218-8b23-4545-a5a1-5376aaef4192.gif" alt class="image--center mx-auto" /></p>
<p>In this example, clicking the "Open modal" button sets <code>showModal</code> to true, triggering the modal to open with its scale-up animation. Clicking the "Close modal" button sets <code>showModal</code> to false and initiates the modal's exit animation.</p>
<p>This is a basic example, of course. You can customize the variants and animation properties to create different exit effects.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>If you made it all the way here, congrats!</p>
<p>Hopefully, you've learned how easy and intuitive implementing exit animations using Framer motion is. Let's recap what we covered:</p>
<ul>
<li><p>We learned why we couldn't use plain CSS transitions to create exit animations in React.</p>
</li>
<li><p>We learned how <code>AnimatePresence</code> ensures the exit animation plays before the element is removed from the DOM.</p>
</li>
<li><p>We explored how to implement more advanced exit animations using custom easing functions, multiple properties, and transition delays.</p>
</li>
<li><p>Finally, we built a simple modal component using all we learned in this guide.</p>
</li>
</ul>
<p>Framer Motion is a powerful library; this guide has just scratched the surface! You can explore state changes and gestures and even build complex animation sequences. Check out the documentation <a target="_blank" href="https://www.framer.com/motion/">here</a>.</p>
<p>Remember, though, that animations should always be intentional. They can be a fantastic tool to guide users, communicate app state, and enhance the overall experience. But avoid going overboard – animations shouldn't slow down your app or become distracting. Aim for a balance that doesn't impede on user experience.</p>
<p>I'd love to see what you build with your new knowledge. Have fun, and thanks for reading!</p>
<hr />
<p>I would greatly appreciate any constructive feedback you may have. Feel free to share your thoughts! I'm happy to write if you found this helpful and are interested in more Framer Motion-related content. In the coming weeks, you can also expect more blog articles exploring exciting web technologies I come across. I hope you had a lovely read. 🤍</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I'm also open to new opportunities! If you're looking for a frontend developer experienced with React, Next.js, and Tailwind CSS, check out my portfolio for more of my work: <a target="_blank" href="https://www.victorwilliams.me/">https://www.victorwilliams.me</a>. I'm available for full-time, part-time, or freelance gigs. Feel free to reach out if you have any projects in mind!</div>
</div>]]></content:encoded></item><item><title><![CDATA[The Importance of Collaboration in Achieving Successful Design]]></title><description><![CDATA[I'll never forget the time I spent weeks designing a website for a startup incubator. The design leaned heavily on a bold, minimalist aesthetic – think impactful headlines against a clean, uncluttered background. The client loved it! But then came th...]]></description><link>https://blog.victorwilliams.me/importance-of-collaboration-in-design</link><guid isPermaLink="true">https://blog.victorwilliams.me/importance-of-collaboration-in-design</guid><category><![CDATA[Design]]></category><category><![CDATA[Collaboration]]></category><category><![CDATA[UX]]></category><category><![CDATA[UI]]></category><category><![CDATA[design thinking]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[communication]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[UI Design]]></category><dc:creator><![CDATA[Victor Williams]]></dc:creator><pubDate>Mon, 06 May 2024 21:28:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1714717823068/29ffe913-de1f-4f05-9414-0051eff483f2.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I'll never forget the time I spent weeks designing a website for a startup incubator. The design leaned heavily on a bold, minimalist aesthetic – think impactful headlines against a clean, uncluttered background. The client loved it! But then came the handover. I hadn't looped in the developer throughout the process. My lack of upfront communication resulted in a significant disconnect between the design and the final product. </p>
<p>Weeks later, upon launch, the website bore little resemblance to the original mockups. The fonts were no longer bold, the layout was confusing, the buttons were unresponsive, and the overall experience was frustrating. This is a common pitfall when design happens in isolation. </p>
<h3 id="heading-collaboration-in-design">Collaboration in Design</h3>
<p>At its core, successful design achieves a set of goals. This could be creating a product that's easy to use, a website that sells more items, or a space that inspires creativity. It requires creativity, functionality, and a deep understanding of user needs. This can only be achieved by bringing together the expertise of various design disciplines through <strong>collaboration</strong>.</p>
<p>Having worn both hats – product designer and frontend developer – throughout my career, I've gained a unique perspective on the importance of collaboration in achieving successful design outcomes. From brainstorming initial concepts to iterating on prototypes, encouraging open communication and understanding between designers and developers is vital for creating user-centered experiences that are both visually appealing and technically sound.</p>
<p>But fear not, fellow designers and developers! This article isn't here to dwell on my frustrations. Instead, I want to share some practical tips and strategies to bridge this communication gap and promote a truly collaborative design process.</p>
<h2 id="heading-benefits-of-collaboration"><strong>Benefits of Collaboration</strong></h2>
<p>I've always believed successful design isn't a one-man show. In my career, I've witnessed firsthand the magic that happens when designers, developers, and other stakeholders come together. </p>
<p>Collaboration brings together individuals with diverse backgrounds, creating a richer pool of ideas and fostering a deeper understanding of the entire design process. Here are ways collaboration unlocks the true potential of design:</p>
<ul>
<li><strong>Improved Problem-Solving:</strong> Collaboration isn't just about sharing ideas; it encourages communication and brainstorming. When designers, developers, and other stakeholders come together, they can tackle design challenges from multiple angles, identifying potential issues and developing creative solutions that might not have emerged from individual efforts.</li>
</ul>
<blockquote>
<p>"None of us is as smart as all of us."</p>
<p>- Ken Blanchard</p>
</blockquote>
<ul>
<li><p><strong>Enhanced User Experience (UX):</strong> A website or app might look fantastic but fails if it's challenging to navigate or doesn't meet user needs. Collaboration, particularly between UI/UX designers and developers, ensures that the final product is not only visually appealing but also functional, user-friendly and addresses the core needs of the target audience.</p>
</li>
<li><p><strong>Feasibility and Efficiency:</strong> Early collaboration helps identify potential roadblocks early on. For instance, a developer might point out limitations in a design concept, allowing the team to adjust their approach before significant time is wasted. This proactive approach streamlines the design process and ensures the final product is feasible within the project's technical constraints and timelines.</p>
</li>
<li><p><strong>Reduced Errors and Revisions:</strong> Clear communication and collaboration minimize misunderstandings and rework later in the design process. By openly discussing ideas and ensuring everyone is on the same page, the team can avoid costly revisions and ensure a smoother design workflow.</p>
</li>
</ul>
<h2 id="heading-examples-of-collaboration-in-action"><strong>Examples of Collaboration in Action</strong></h2>
<p>Let's see how collaboration brings design to life:</p>
<h3 id="heading-my-personal-experience"><strong>My personal experience:</strong></h3>
<p>Remember that frustrating website with unresponsive buttons and a confusing layout? The client, rightfully so, was unhappy with the final result, so they kindly requested a revision. I felt a deep sense of responsibility to fix the situation. I realized the problem was that I was unaware the developer would use WordPress to build the designs, so they couldn't implement them fully.</p>
<p>With this in mind, I made slight changes in the design to accommodate this challenge, and the developer pointed out potential snags early on. When the redevelopment began, I frequently shared feedback with the developer, ensuring they could translate the visual intent into a functional, user-friendly web experience. This time, the website launch was a breeze. The final product surpassed everyone's expectations, and the client was pleased.</p>
<h3 id="heading-a-more-general-scenario"><strong>A more general scenario:</strong></h3>
<p>Picture a team working on revamping an e-commerce website. The UI/UX designer proposes a visually attractive product page layout. They also suggest incorporating user reviews and clear filtering options to improve user experience. The developer chimes in, highlighting technical considerations for implementing these features while maintaining optimal website performance. This collaborative approach ensures the final product is aesthetically pleasing, user-friendly, and functionally sound.</p>
<h2 id="heading-keys-to-effective-collaboration"><strong>Keys to Effective Collaboration</strong></h2>
<p>Collaboration is a powerful tool, but it thrives on a foundation of clear communication and organization. Here are some tips to ensure your design team collaborates effectively:</p>
<ul>
<li><p><strong>Establish Clear Communication Channels:</strong> Define preferred methods for communication, be it email, instant messaging platforms, or project management tools. Encourage open communication and active listening to ensure everyone's voice is heard.</p>
</li>
<li><p><strong>Utilize Collaborative Tools:</strong> Design software with collaborative features like Figma or Mural allows team members to work on designs simultaneously, enabling real-time feedback and iteration.</p>
</li>
<li><p><strong>Set Up Regular Team Meetings:</strong> Schedule regular meetings (weekly or bi-weekly) to discuss project progress, address challenges, and brainstorm ideas. These meetings can be a mix of formal presentations and informal brainstorming sessions.</p>
</li>
<li><p><strong>Define Roles and Responsibilities:</strong> Clearly outline the roles and responsibilities of each team member. This helps avoid confusion and ensures everyone focuses on their area of expertise while understanding the bigger picture.</p>
</li>
<li><p><strong>Embrace Feedback:</strong> A successful design is rarely born from a single vision. Encourage team members to provide constructive feedback on each other's work. Focus on the design, not the individual, and continuously use feedback to improve the final product.</p>
</li>
<li><p><strong>Celebrate Successes:</strong> Take time to acknowledge and celebrate collective achievements. Recognizing teamwork motivates individuals and strengthens the collaborative spirit within the team.</p>
</li>
</ul>
<h2 id="heading-challenges-of-design-collaboration">Challenges of Design Collaboration</h2>
<p>While collaboration offers many benefits, achieving a truly collaborative design environment is challenging. In my experience, some of the biggest roadblocks to consider are:</p>
<ul>
<li><p><strong>Communication Gaps:</strong> Design teams often comprise individuals with diverse backgrounds and communication styles. UI/UX designers might use terminology unfamiliar to developers or vice versa. This can lead to misunderstandings and hinder effective communication.</p>
</li>
<li><p><strong>Differing Priorities:</strong> Natural tensions can arise when designers prioritize aesthetics and user experience (UX) while developers focus on technical feasibility and project timelines. Finding a healthy balance between these priorities requires clear communication and a shared understanding of the project goals.</p>
</li>
<li><p><strong>Lack of Trust or Respect:</strong> For true collaboration to flourish, team members must have a foundation of trust and mutual respect. Without it, individuals might hesitate to share ideas or offer constructive feedback, hindering the creative process.</p>
</li>
<li><p><strong>Confusing Ownership and Responsibility:</strong> In a collaborative environment, it's essential to clearly define roles and responsibilities for each team member. Ambiguity can lead to confusion about who owns specific tasks or design elements, potentially causing delays and rework.</p>
</li>
<li><p><strong>Information Silos:</strong> Without a central platform for sharing ideas and updates, information can get siloed within individual disciplines. This can lead to a disconnect between design decisions and their technical implementation.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Today, collaboration is no longer a luxury; it's a necessity. By bringing together the diverse perspectives of designers, developers, and other stakeholders, teams can create solutions that are not only aesthetically pleasing but also functional, user-friendly and achieve project goals.</p>
<p>The benefits of collaboration extend far beyond the design phase itself. Effective collaboration streamlines the design process, reduces errors, and promotes a more innovative and productive design environment. So, the next time you embark on a design project, remember: <strong>collaboration is key</strong>.</p>
<p>By implementing the tips I outlined here and encouraging a collaborative spirit within your team, you can unlock the true potential of design and create experiences that truly resonate with your users.</p>
<hr />
<p>I would greatly appreciate any constructive feedback you may have. Feel free to share your thoughts! If you found this helpful and are interested in more design-related content, I'm happy to write. In the coming weeks, you can also expect more blog articles exploring exciting web technologies I come across. I hope you had a lovely read. 🤍</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I'm also open to new opportunities! If you're looking for a frontend developer experienced with React, Next.js, and Tailwind CSS, you can check out my portfolio for more of my work: <a target="_blank" href="https://www.victorwilliams.me/">https://www.victorwilliams.me</a>. I'm currently available for full-time roles, part-time roles, or freelance gigs. Feel free to reach out if you have any projects in mind!</div>
</div>]]></content:encoded></item><item><title><![CDATA[Step-by-Step Guide: Adding Google Maps to Your React App Using Vis.gl]]></title><description><![CDATA[Have you ever felt overwhelmed integrating the Google Maps API into a React project for the first time? Well, I definitely have! Choosing the right library can be daunting, especially when you need specific features like dynamic markers and location ...]]></description><link>https://blog.victorwilliams.me/how-to-add-google-maps-to-react-app-visgl</link><guid isPermaLink="true">https://blog.victorwilliams.me/how-to-add-google-maps-to-react-app-visgl</guid><category><![CDATA[visgl]]></category><category><![CDATA[React]]></category><category><![CDATA[google maps]]></category><category><![CDATA[maps]]></category><category><![CDATA[Tailwind CSS]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[vite]]></category><dc:creator><![CDATA[Victor Williams]]></dc:creator><pubDate>Thu, 25 Apr 2024 12:25:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/_SFJhRPzJHs/upload/afa61503cb2ab2b7dfb09ea7c5a5d16f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Have you ever felt overwhelmed integrating the Google Maps API into a React project for the first time? Well, I definitely have! Choosing the right library can be daunting, especially when you need specific features like dynamic markers and location search.</p>
<p>In this article, you’ll see a simple example of how to integrate Google Maps into a React project. However, we’ll start by discussing why you might want to do so and some advanced Google Maps features you can use. If you prefer, you can jump ahead to the tutorial — make sure to check out the demo project’s <a target="_blank" href="https://github.com/victorcodess/react-google-maps-demo">source code</a> as well.</p>
<h2 id="heading-using-google-maps-in-react">Using Google Maps in React</h2>
<p>There are a number of reasons why you may choose to integrate Google Maps into your React app. We’ll be taking a look at one of the most popular ones. You can use them as a base for other, more complex cases if you desire.</p>
<ul>
<li><p><strong>Enhanced User Experience (UX):</strong> Google Maps is a familiar and user-friendly platform for visualizing locations. Integrating it into your React app allows users to easily explore geographical data, navigate places of interest, and understand spatial relationships.</p>
</li>
<li><p><strong>Location-based Functionality:</strong> Google Maps unlocks a wide range of location-based functionalities for your React app. You can display user locations, track deliveries, visualize sales data on a map to identify trends, or even create real-time route planning and navigation features.</p>
</li>
<li><p><strong>Increased Engagement:</strong> Interactive maps are inherently engaging. Users can zoom in and out, explore different map views, and discover new information. This interactivity can keep users engaged with your application for longer periods.</p>
</li>
<li><p><strong>Data Visualization:</strong> Google Maps can be a powerful tool for data visualization. You can use markers, heatmaps, and polylines to represent various types of data on a map, allowing users to gain valuable insights from geographical patterns.</p>
</li>
</ul>
<h2 id="heading-react-google-maps">React Google Maps</h2>
<p>For React developers, like myself, seeking a first-party solution for integrating Google Maps, the <code>vis.gl/react-google-maps</code> library stands out as a compelling choice. This official offering from the Google Maps Platform team simplifies the process of adding interactive maps to your React application.</p>
<p>It was first provisioned by the Google Maps Platform team, in order to provide solid integrations between React and the Maps JavaScript API. The design of <code>vis.gl/react-google-maps</code> draws inspiration from the successful integration between <code>react-map-gl</code> and the map renderers based on <code>mapbox-gl-js</code>.</p>
<p>It's important to note that <code>vis.gl/react-google-maps</code> requires a valid Google Maps Platform API key for functionality. Additionally, while the library offers a decent set of core components, developers may need to interact directly with the underlying Google Maps JavaScript API for more advanced use cases.</p>
<p>Although <code>vis.gl/react-google-maps</code> is a compelling choice for integrating Google Maps with React, it's important to acknowledge that other popular libraries exist. One such alternative is <code>google-maps-react</code>, offering a familiar approach for developers accustomed to working with Google Maps APIs.</p>
<p>Regardless of which library you select, make sure it aligns with your project's requirements and your development preferences. In this article, you'll focus on using <code>vis.gl/react-google-maps</code> for consistency.</p>
<h2 id="heading-get-started">Get Started</h2>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>Node.js and npm (or yarn) installed on your system.</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">For this walkthrough, you'll be creating a React project using Vite and Tailwind CSS for styling. While these are my preferred choices, you can absolutely tailor the setup to your existing project or preferences.</div>
</div>

<p><strong>Project Setup:</strong></p>
<ol>
<li><p><strong>Create a React project with Vite:</strong></p>
<pre><code class="lang-plaintext"> npm create vite@latest react-google-maps-demo -- --template react-ts
 cd react-google-maps-demo
</code></pre>
<p> This command creates a new React project with TypeScript support using Vite, a modern build tool.</p>
</li>
<li><p><strong>Install Dependencies:</strong></p>
<pre><code class="lang-plaintext"> npm install @vis.gl/react-google-maps
</code></pre>
<p> This installs the <code>vis.gl/react-google-maps</code> library, allowing you to integrate Google Maps into your React application. This module comes with full TypeScript-support out of the box, so no additional module is required for the typings.</p>
</li>
<li><p><strong>(Optional) Install Tailwind CSS:</strong></p>
<pre><code class="lang-plaintext"> npm install -D tailwindcss postcss autoprefixer
 npx tailwindcss init -p
</code></pre>
<p> If you plan to use Tailwind CSS for styling, <a target="_blank" href="https://tailwindcss.com/docs/guides/vite">follow these steps</a> to install and configure it. Remember to configure your Tailwind configuration file (<code>tailwind.config.js</code>) according to your project's needs.</p>
</li>
<li><p>Start the development server:</p>
<pre><code class="lang-plaintext"> npm run dev
</code></pre>
<p> This command starts the development server and opens your application in the browser:</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713797503519/40165063-63a7-4999-a53a-132800604d60.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-obtaining-google-maps-api-key">Obtaining Google Maps API key</h2>
<p>To use Google Maps features within your React application, you'll need to obtain an <a target="_blank" href="https://developers.google.com/maps/documentation/javascript/get-api-key">API key</a> from the Google Cloud Platform (GCP). They have several API’s to use with the Maps API but for now, you’ll need just the <code>Maps Javascript API</code> to get started for the map. So ensure that the <code>Maps Javascript API</code> is enabled in your console.</p>
<p><strong>Steps to Acquire an API Key:</strong></p>
<ol>
<li><p><strong>Create or Access a GCP Project:</strong> If you don't have an existing project, create one on the <a target="_blank" href="https://console.cloud.google.com/google/maps-apis/start">GCP Console</a>.</p>
</li>
<li><p><strong>Enable Required APIs:</strong> Navigate to the "APIs &amp; Services" section in the <strong>Google Maps Platform</strong> and enable the following APIs for your project:</p>
<ul>
<li><strong>Maps JavaScript API</strong></li>
</ul>
</li>
<li><p><strong>Create an API Key:</strong> In the "Credentials" section of the <strong>Google Maps Platform</strong>, create a new API key. Consider restricting this key to only allow usage for your specific project for better security.</p>
</li>
</ol>
<p><strong>Never commit your API key to a public repository</strong> <strong>like Github</strong>. Instead, create a <code>.env.local</code> file in your project's root directory and add the following line, replacing <code>&lt;your API key here&gt;</code> with your actual key:</p>
<pre><code class="lang-typescript">VITE_REACT_GOOGLE_MAPS_API_KEY=&lt;your API key here&gt;
</code></pre>
<h2 id="heading-displaying-a-basic-map"><strong>Displaying a Basic Map</strong></h2>
<p>In this section, I'll walk you through rendering a simple Google Map in your React application using <code>vis.gl/react-google-maps</code>.</p>
<ol>
<li><p><strong>Import Necessary Components:</strong></p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">import</span> { APIProvider, <span class="hljs-built_in">Map</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vis.gl/react-google-maps'</span>;
</code></pre>
<p> You import the <code>APIProvider</code> and <code>Map</code> components from the library.</p>
</li>
<li><p><strong>Set Up the</strong><code>App</code><strong>Component:</strong></p>
<pre><code class="lang-typescript"> <span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> (
   &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
     &lt;<span class="hljs-built_in">Map</span>
       style={{ width: <span class="hljs-string">'100vw'</span>, height: <span class="hljs-string">'100vh'</span> }}
       defaultCenter={{ lat: <span class="hljs-number">22.54992</span>, lng: <span class="hljs-number">0</span> }}
       defaultZoom={<span class="hljs-number">3</span>}
       gestureHandling={<span class="hljs-string">'greedy'</span>}
       disableDefaultUI={<span class="hljs-literal">true</span>}
     /&gt;
   &lt;/APIProvider&gt;
 );
 <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<ul>
<li><p>The <code>APIProvider</code> component wraps the <code>Map</code> component and provides the necessary context and functionality for using Google Maps within your React application. It requires your API key as a prop.</p>
</li>
<li><p>The <code>Map</code> component itself defines the map element. You configure its appearance and behavior using props:</p>
<ul>
<li><p><code>style</code>: Sets the width and height of the map container.</p>
</li>
<li><p><code>defaultCenter</code>: Specifies the initial location of the map using latitude and longitude coordinates (here, centered near the equator).</p>
</li>
<li><p><code>defaultZoom</code>: Defines the initial zoom level (a higher value represents a closer view).</p>
</li>
<li><p><code>gestureHandling</code>: Controls how the map interacts with user gestures like touch or panning. Here, <code>'greedy'</code> prioritizes map interactions over page scrolling.</p>
</li>
<li><p><code>disableDefaultUI</code>: Removes the default user interface elements provided by Google Maps (zoom controls, map type options, etc.).</p>
</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>View the Map:</strong></p>
<p> With these components in place, our application should render a basic interactive map.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713799649570/18548304-8377-475c-af8d-3b75f3ff616c.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-adding-infowindows-and-markers"><strong>Adding InfoWindows and Markers</strong></h2>
<h3 id="heading-infowindows">InfoWindows</h3>
<p>The <code>InfoWindow</code> component is a part of the Google Maps API provided by the <code>@vis.gl/react-google-maps</code> package, which allows you to create information windows on the map. Information windows are pop-up windows that appear above the map at a specific location and provide additional information about a particular point of interest.</p>
<p>The <code>InfoWindow</code> component is used as a child component within the <code>Map</code> component. It takes several props, but the most important one is <code>position</code>, which specifies the geographic coordinates (latitude and longitude) where the info window should be displayed on the map.</p>
<p>The code snippet below demonstrates how to add an <code>InfoWindow</code> with the content "Hello World!" positioned at specific coordinates:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { APIProvider, InfoWindow, <span class="hljs-built_in">Map</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"@vis.gl/react-google-maps"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> (
  &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
    &lt;<span class="hljs-built_in">Map</span>
      style={{ width: <span class="hljs-string">"100vw"</span>, height: <span class="hljs-string">"100vh"</span> }}
      defaultCenter={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }}
      defaultZoom={<span class="hljs-number">13</span>}
      gestureHandling={<span class="hljs-string">"greedy"</span>}
      disableDefaultUI={<span class="hljs-literal">true</span>}
    &gt;
      &lt;InfoWindow position={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }}&gt;
        Hello World!
      &lt;/InfoWindow&gt;
    &lt;/<span class="hljs-built_in">Map</span>&gt;
  &lt;/APIProvider&gt;
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>With these components in place, our application should render a map with an information window saying "Hello World!".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713815832229/131c64b9-59cd-4d36-9327-007319f025aa.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-marker">Marker</h3>
<p>The <code>Marker</code> component is a part of the Google Maps API provided by the <code>@</code><a target="_blank" href="http://vis.gl/react-google-maps"><code>vis.gl/react-google-maps</code></a> package, enabling you to place markers on the map to indicate specific points of interest or locations.</p>
<p>While <code>InfoWindows</code> provide details, markers visually represent points of interest on the map. You can use the <code>Marker</code> component from <code>vis.gl/react-google-maps</code> to add markers. The usage is similar to <code>InfoWindows</code>, with a <code>position</code> prop and optional customization options like icons.</p>
<p>The code snippet below demonstrates adding a basic marker at specific coordinates:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { APIProvider, <span class="hljs-built_in">Map</span>, Marker } <span class="hljs-keyword">from</span> <span class="hljs-string">"@vis.gl/react-google-maps"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> (
  &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
    &lt;<span class="hljs-built_in">Map</span>
      style={{ width: <span class="hljs-string">"100vw"</span>, height: <span class="hljs-string">"100vh"</span> }}
      defaultCenter={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }}
      defaultZoom={<span class="hljs-number">12</span>}
      gestureHandling={<span class="hljs-string">"greedy"</span>}
      disableDefaultUI={<span class="hljs-literal">true</span>}
    &gt;
      &lt;Marker position={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }} /&gt;
    &lt;/<span class="hljs-built_in">Map</span>&gt;
  &lt;/APIProvider&gt;
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>With our components in place, our application should render a map with a single marker. You can also render multiple markers if you need.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713862252832/da979ef9-cf2f-487c-a853-8367aae052e7.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-advanced-markers">Advanced Markers</h3>
<p>The <code>AdvancedMarker</code> component provides a more customizable alternative to the standard <code>Marker</code> component.</p>
<p>The <code>AdvancedMarker</code> component allows for extensive customization of the marker's appearance and behavior. You can apply custom styles, including complex layouts, backgrounds, borders, and shadows, to the marker using JSX/TSX, CSS classes or inline styles.</p>
<p>To use the <code>AdvancedMarker</code> component, it is necessary to add a custom <code>mapId</code> to the map options. <a target="_blank" href="https://developers.google.com/maps/documentation/get-map-id#:~:text=Create%20a%20map%20ID,-A%20map%20ID&amp;text=You%20can%20create%20map%20IDs,Create%20New%20Map%20ID%20form.">The <code>mapId</code> prop in the <code>Map</code> component specifies the ID of the Google Map being rendered.</a> This prop is particularly useful when working with styled maps or when multiple maps are present on the same page.</p>
<p>This example renders an <code>AdvancedMarker</code> with custom styles and an SVG element:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { APIProvider, AdvancedMarker, <span class="hljs-built_in">Map</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">"@vis.gl/react-google-maps"</span>;

<span class="hljs-keyword">const</span> App = <span class="hljs-function">() =&gt;</span> (
  &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
    &lt;<span class="hljs-built_in">Map</span>
      style={{ width: <span class="hljs-string">"100vw"</span>, height: <span class="hljs-string">"100vh"</span> }}
      defaultCenter={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }}
      defaultZoom={<span class="hljs-number">12</span>}
      gestureHandling={<span class="hljs-string">"greedy"</span>}
      disableDefaultUI={<span class="hljs-literal">true</span>}
      mapId={<span class="hljs-keyword">import</span>.meta.env.VITE_MAP_ID}
    &gt;
      &lt;AdvancedMarker
        position={{ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> }}
        className=<span class="hljs-string">"w-[250px] bg-white flex flex-col items-center gap-1 py-3 px-3 rounded-xl shadow-xl"</span>
      &gt;
        &lt;h2 className=<span class="hljs-string">"text-[20px] font-medium"</span>&gt;I am so customized&lt;/h2&gt;
        &lt;p&gt;That is pretty awesome!&lt;/p&gt;

        &lt;svg
          className=<span class="hljs-string">"absolute text-white h-10 w-full left-0 top-full"</span>
          x=<span class="hljs-string">"0px"</span>
          y=<span class="hljs-string">"0px"</span>
          viewBox=<span class="hljs-string">"0 0 255 255"</span>
          xmlSpace=<span class="hljs-string">"preserve"</span>
        &gt;
          &lt;polygon
            className=<span class="hljs-string">"fill-current shadow-lg"</span>
            points=<span class="hljs-string">"0,0 127.5,127.5 255,0"</span>
          /&gt;
        &lt;/svg&gt;
      &lt;/AdvancedMarker&gt;
    &lt;/<span class="hljs-built_in">Map</span>&gt;
  &lt;/APIProvider&gt;
);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App;
</code></pre>
<p>The result should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713890812022/325f0a86-54c0-4a46-99bd-a5680f3f55b8.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-react-google-maps-hooks">React Google Maps Hooks</h2>
<p>The <code>useMap()</code> and <code>useMapLibrary()</code> hooks are part of the <code>vis.gl/react-google-maps</code> package, which provides React hooks for integrating Google Maps functionality into a React application.</p>
<h3 id="heading-usemap"><strong>useMap()</strong></h3>
<p>The <code>useMap()</code> hook allows you to access and interact with the Google Map instance within your React component. It provides a way to interact with the map programmatically, such as changing the map's center, zoom level, or adding markers dynamically.</p>
<h4 id="heading-example-usage"><strong>Example Usage:</strong></h4>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useMap, APIProvider, <span class="hljs-built_in">Map</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vis.gl/react-google-maps'</span>;

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> map = useMap();

  <span class="hljs-comment">// Access and manipulate the map instance</span>
  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">// Set the map's center and zoom level</span>
    map.setCenter({ lat: <span class="hljs-number">53.54992</span>, lng: <span class="hljs-number">10.00678</span> });
    map.setZoom(<span class="hljs-number">12</span>);
  }, [map]);

  <span class="hljs-keyword">return</span> (
    &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
     &lt;<span class="hljs-built_in">Map</span>
       style={{ width: <span class="hljs-string">'100vw'</span>, height: <span class="hljs-string">'100vh'</span> }}
       gestureHandling={<span class="hljs-string">'greedy'</span>}
       disableDefaultUI={<span class="hljs-literal">true</span>}
     /&gt;
   &lt;/APIProvider&gt;
  );
};
</code></pre>
<h3 id="heading-usemaplibrary"><strong>useMapLibrary()</strong></h3>
<p>The <code>useMapLibrary()</code> hook allows you to access additional libraries provided by the Google Maps JavaScript API, such as the Places API, Geoloction API, e.t.c. It provides a way to load and use these libraries dynamically within your React component.</p>
<h4 id="heading-example-usage-1"><strong>Example Usage:</strong></h4>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { useMap, APIProvider, <span class="hljs-built_in">Map</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@vis.gl/react-google-maps'</span>;

<span class="hljs-keyword">const</span> MyComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// triggers loading the places library and returns true once complete (the</span>
  <span class="hljs-comment">// component calling the hook gets automatically re-rendered when this is</span>
  <span class="hljs-comment">// the case)</span>
  <span class="hljs-keyword">const</span> map = useMap();
  <span class="hljs-keyword">const</span> placesLib = useMapsLibrary(<span class="hljs-string">'places'</span>);
  <span class="hljs-keyword">const</span> [placesService, setPlacesService] = useState(<span class="hljs-literal">null</span>);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!placesLib || !map) <span class="hljs-keyword">return</span>;

    setPlacesService(<span class="hljs-keyword">new</span> placesLib.PlacesService(map));
  }, [placesLib, map]);

  useEffect(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">if</span> (!placesService) <span class="hljs-keyword">return</span>;

    <span class="hljs-comment">// ...use placesService...</span>
  }, [placesService]);

  <span class="hljs-keyword">return</span> (
    &lt;APIProvider apiKey={<span class="hljs-keyword">import</span>.meta.env.VITE_REACT_GOOGLE_MAPS_API_KEY}&gt;
     &lt;<span class="hljs-built_in">Map</span>
       style={{ width: <span class="hljs-string">'100vw'</span>, height: <span class="hljs-string">'100vh'</span> }}
       gestureHandling={<span class="hljs-string">'greedy'</span>}
       disableDefaultUI={<span class="hljs-literal">true</span>}
     /&gt;
   &lt;/APIProvider&gt;
  );
};
</code></pre>
<h1 id="heading-conclusion"><strong>Conclusion</strong></h1>
<p>Hopefully, this article has equipped you with the foundation to integrate Google Maps into your React applications using <code>vis.gl/react-google-maps</code>. We've covered:</p>
<ul>
<li><p>Setting up a React project with the necessary dependencies.</p>
</li>
<li><p>Obtaining a Google Maps API key for map interactions.</p>
</li>
<li><p>Rendering a basic map with initial configuration options.</p>
</li>
<li><p>Adding interactive elements like markers and info windows for points of interest.</p>
</li>
<li><p>Using <code>AdvancedMarker</code> for better marker customization.</p>
</li>
<li><p>Leveraging map hooks (<code>useMap</code> and <code>useMapLibrary</code>) for programmatic control and additional map libraries integration.</p>
</li>
</ul>
<p>By effectively combining the power of Google Maps with the flexibility of React and the utilities provided by <code>vis.gl/react-google-maps</code>, you can create dynamic and informative map experiences within your React applications.</p>
<p>It's really important to consider error handling mechanisms in your React applications, especially when interacting with external APIs like Google Maps.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Important Note: </strong>The <code>vis.gl/react-google-maps</code> library is currently in its alpha phase. This means it's still under active development, and features or behaviors might change in future releases. Be prepared for potential issues and occasional breaking changes.</div>
</div>

<p>This is just the beginning! The Google Maps Platform offers a vast array of functionalities beyond what we've covered here. Explore the official <a target="_blank" href="https://developers.google.com/maps/documentation">Google Maps documentation</a> to learn more about features like geocoding, directions, and more. Also, the <code>vis.gl/react-google-maps</code> library offers more components like <code>MapControl</code> and <code>Pin</code>, and other hooks like the <code>useApiIsLoaded()</code> and <code>useApiLoadingStatus()</code> hooks. You should refer to <a target="_blank" href="https://github.com/visgl/react-google-maps">their documentation</a> to learn how they work. Another resource I recommend you to check out is this <a target="_blank" href="https://www.youtube.com/playlist?list=PL2rFahu9sLJ2QuJaKKYDaJp0YqjFCDCtN">Youtube Playlist</a> from the Google Maps Platform team.</p>
<p>While <code>vis.gl/react-google-maps</code> is still in its early stages, I believe it has a lot of potential. Backed by a talented internal team and a growing community of open-source contributors, the library is definitely poised for significant development. I'm excited to see what new features and functionalities get included in upcoming releases!</p>
<hr />
<p>This is my first technical article! 🥳</p>
<p>I would greatly appreciate any constructive feedback you may have. Feel free to share your thoughts! If you found this helpful and are interested in more Google Maps-related content, I'm happy to write on other features or components. In the coming weeks, you can also expect more blog articles exploring exciting web technologies I come across. I hope you had a lovely read. 🤍</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">I'm also open to new opportunities! If you're looking for a frontend developer experienced with React, Next.js, and Tailwind CSS, you can check out my portfolio for more of my work: <a target="_blank" href="https://www.victorwilliams.me/">https://www.victorwilliams.me</a>. I'm currently available for full-time roles, part-time roles, or freelance gigs. Feel free to reach out if you have any projects in mind!</div>
</div>]]></content:encoded></item><item><title><![CDATA[2023: A Year in Review – Navigating Challenges and Embracing Growth]]></title><description><![CDATA[Staring at this blank Google doc felt like staring into a void. Words danced just out of reach, mocking my efforts to capture the whirlwind that was 2023. Time, it seems, is a sneaky thief, making the year sneak up in the blink of an eye. So many ama...]]></description><link>https://blog.victorwilliams.me/2023-a-year-in-review</link><guid isPermaLink="true">https://blog.victorwilliams.me/2023-a-year-in-review</guid><category><![CDATA[yearinreview]]></category><category><![CDATA[reflection]]></category><category><![CDATA[personal]]></category><dc:creator><![CDATA[Victor Williams]]></dc:creator><pubDate>Tue, 02 Jan 2024 23:54:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704146853987/5e5ffc0f-9d20-4cc8-ad94-00ec737ba0f5.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Staring at this blank Google doc felt like staring into a void. Words danced just out of reach, mocking my efforts to capture the whirlwind that was 2023. Time, it seems, is a sneaky thief, making the year sneak up in the blink of an eye. So many amazing things happened, so many incredible people crossed my path―both new faces and familiar ones who held my hand through thick and thin.</p>
<p>But where do I start? Do I dive headfirst into the heart-pounding highs, or whisper about the quiet victories that warmed my soul? Maybe it's all about the faces, the laughter, the love – the threads that wove this year into a tapestry I never want to forget. Before the ink spills and the story unfolds, let me take a breath, dig through the attic of my mind, and piece together the puzzle of what has been. This won't be just a list of dates and events, but a story―a messy, beautiful, sometimes bittersweet ode to living life to the fullest.</p>
<h2 id="heading-workcareer"><strong>Work/Career</strong></h2>
<p>Starting with my career feels fitting. It's the area of my life where I most believe I hold the reins, or at least, that's my usual refrain. <a target="_blank" href="https://blog.victorwilliams.me/reflecting-on-my-18th-year-a-personal-review-of-2022">Last year, I crafted a roadmap of goals for my professional journey.</a> Can I honestly say I followed it? The answer, like most paths worth taking, has its twists and turns.</p>
<h3 id="heading-crown"><strong>Crown</strong></h3>
<p>I couldn’t do a lot career-wise this year because of school. For half the year, I remained at Crown Branding Agency as a Product Designer but left in May. Leaving in May wasn't a dramatic exit, but it felt like closing a chapter. Crown, my first real "job," was a gift box of discovery. An amazing team, thrilling client projects―each one a stepping stone to carving my professional identity. The rest of the year? Unemployed. But I wouldn't call it empty. It was a forced pause, a space to sift through the dust of ambition and define what I truly craved career-wise.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704249025125/40be7bf7-0d84-4d55-9c73-3f3a4d0d71c3.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-mono"><strong>Mono</strong></h3>
<p>One of the audacious goals I set for myself was to intern at a reputable tech company during my SIWES I IT. In May, I started applying to every tech company I knew. I sent out so many connection requests on LinkedIn, to as many as 5+ employees for every company I was interested in. In total, I reached out to over 20 tech startups, every thing was documented on a notion page I had created, but the replies? Crickets, mostly. Some of the employees I reached out to got back to me, most didn’t. Rejections, often disguised as "not hiring interns at the moment" or "we have no internship program to begin with," peppered my inbox, even when sprinkled with compliments on my work. It was a grueling process, even with the occasional pat on the back.</p>
<p>Then, fate (or a random Twitter tweet) intervened. Mono was launching an internship program! I was really excited when I saw this. I just dropped a comment and forgot about it totally.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704248102791/f0d09704-af3e-4c8c-bfa9-06b9c0e9216b.png" alt class="image--center mx-auto" /></p>
<p>The application process at Mono was a whirlwind. The first application link crashed under the weight of eager applicants, but I was determined not to miss this opportunity. I quickly jumped on the second link, fingers flying across the keyboard. The interviews were surprisingly engaging, even though I initially doubted my chances—there were so many talented candidates. But after a night of intense preparation, I faced the final round with newfound confidence. When the acceptance email finally landed in my inbox, it felt like the stars had aligned.</p>
<p>My heart pounded as I stared at the email subject line: "Congratulations! You've been accepted to the Mono Internship Program!" It was the culmination of months of relentless hustle, countless rejections, and one serendipitous tweet. Getting an internship at a top tech company had been my audacious goal, and against all odds, I'd actually done it.</p>
<p>My internship at Mono was really incredible. Mono's culture wasn't just about productivity—it was about fostering a sense of belonging and empowerment. I found myself surrounded by brilliant minds who were eager to share their knowledge and challenge each other to grow. I worked on really impactful projects with the other amazing interns and senior engineers. I learnt a lot from my time there, and I’d definitely do it again if I could.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/YyiYxIUNC6s?si=gYp0ixtG9pyVurjb">https://youtu.be/YyiYxIUNC6s?si=gYp0ixtG9pyVurjb</a></div>
<p> </p>
<h3 id="heading-faang-big-4-phcn"><strong>FAANG? BIG 4? PHCN?</strong></h3>
<p>For the past 2 years, I’ve had my mind set one goal—to land an internship offer at an international company. The time for this finally came, but for some reason, I wasn’t ready. I had been occupied all through the year with school and my internship, that I wasn’t able to prepare for something that mattered a lot to me.</p>
<p>But this didn’t stop me. In October, I had started applying to internships. I applied to over 30 different roles in the span of 2 months. The entire process was even more stressful compared to that of my SIWES. Rejections piled up―some swift and impersonal, others lingering after online assessments and Hirevues.</p>
<p>Lies I told myself wouldn't stick. After ten "no's," the sting deepened. Top performances in OA stages? Nope, still rejections. It stung, oh it stung.</p>
<p>There were some roles where I performed really well in the OAs but I still got rejected, and it hurt bad. There are only 4 companies that haven’t rejected me yet, but I haven’t heard back from any of them in so long. Each morning, the inbox refresh ritual yields the same result: an empty void.</p>
<p>Forgetting is difficult, but I'm trying. Hope, faint yet stubborn, clings on. Because here's the truth: I tried. I poured my heart into it, and honestly, I think that matters.</p>
<h3 id="heading-volunteering"><strong>Volunteering</strong></h3>
<blockquote>
<p>“Sometimes you have to create the thing you want to be part of” ― Howard Schultz</p>
</blockquote>
<p>That quote echoes deep within me, especially when it comes to volunteering in tech communities at Covenant University. It's not just about checking boxes; it's about building the future I dream of, a future where my university sparks innovation across Nigeria.</p>
<p>Currently, I actively co-lead three vibrant communities: Google Developer Student Clubs (GDSC), Microsoft Learn Student Ambassadors (MLSA), and Hebron Startup Lab (HSL) Creators Community. This year, we didn't just exist, we thrived! My fellow Student Ambassadors and I organized over 5 technical workshops, igniting the minds of 300+ fellow students. We even launched MLSA CU's first-ever Welcome Event, and let me tell you, it was electric! Witnessing the community blossom from 60 members to a 400-strong force fills me with immense pride. And guess what? I had the privilege of guiding two students into the MLSA program – their success fuels my own fire.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704248181588/2a2e29ed-1924-402b-b91f-30b3f5c8f152.png" alt class="image--center mx-auto" /></p>
<p>Speaking of fire, GDSC CU is on fire! In May, I became the Co-lead, and throughtout the year, we hosted over 5 events/workshops and even an ideathon! The energy there is contagious, and the people I work with? They're the secret sauce!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704248542639/f08bbe4e-a308-45c2-b6b2-a0e89dddda0c.png" alt class="image--center mx-auto" /></p>
<p>But there's more brewing. At HSL, the creators community has sharpened its vision, and we're cooking up some game-changing projects. Watch this space – you won't be disappointed!</p>
<p>Why do I pour my heart into these communities? Because I believe, with unwavering conviction, that Covenant University can be Nigeria's innovation hub. Imagine a place where every student is equipped with the digital skills to tackle our local challenges, head-on and hand-in-hand. That's the future I'm building, brick by brick, workshop by workshop, community by community.</p>
<h2 id="heading-health"><strong>Health</strong></h2>
<h3 id="heading-physical-health"><strong>Physical Health</strong></h3>
<p>My physical health in 2023, well, let's be honest, it wasn't a victory lap. I fell sick quite a lot of times. I often had allergies that were tiggered by dust or cold. If any thing improved, I’d say its how often I abstained from carbonated drinks. I think I’ve gotten used to staying long periods without having to consume some form of soda. But once I slip back, it’s a disaster, I might end up taking enough soda to cover up all the times I abstained. My 2024 goal? Gym, here I come! It’s crazy how I’ve never been to the gym to workout before.</p>
<h3 id="heading-mental-health"><strong>Mental Health</strong></h3>
<p><em>Omoo x100</em></p>
<p>Oh boy, my mental health this year was a wild ride. At the start of the year, I felt like I was looking through a kaleidoscope, everything seemed so fragmented and distorted. I was really struggling with finding clarity in my life. It really took time for me to find structure around me. School was one thing that took such a toll on my emotions. I was constantly judging my sanity for choosing to study this course.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704246531101/02443760-41a2-4e12-91e8-a6a5d142c0db.png" alt class="image--center mx-auto" /></p>
<p>But to say it was all doom and gloom would be a flat-out lie. Because in 2023, I laughed. A lot. I spent time with friends who always made me laugh. I made so many happy and hilarious memories with my friends and roommates, and anytime I look back at the time I spent with them, I can’t just help but smile.</p>
<p>So, yes, my mental health still has chapters left to write. But I'm no longer stuck in the first draft. I'm taking intentional steps, embracing wellness strategies like a warm blanket on a chilly day. And who knows, maybe by next year, the kaleidoscope will finally focus.</p>
<h2 id="heading-finance"><strong>Finance</strong></h2>
<h3 id="heading-earning"><strong>Earning</strong></h3>
<p>My finances were significantly better than last year. I earned more money this year than I ever have, and I’m proud of that. Sure, I aimed for Everest and landed on Kilimanjaro, but hey, closer to the clouds, right? Sacrificing some hustle for school may have slowed down the climb, but I'm definitely getting there. Next year, I'm going to make a lot more money, and I think I have a plan.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704246945478/9910900c-161e-4b31-8685-17aeeb2654a8.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-investing"><strong>Investing</strong></h3>
<p>Now, investments? I think I did quite okay. Earning more money meant that I had more to invest. Currently I have a plan with Money Africa, so I get to speak with a financial advisor every once in a while. I’m really proud of how far I’ve come with my investments, I crossed triple digits in dollars this year. 🎉</p>
<h3 id="heading-budgeting"><strong>Budgeting</strong></h3>
<p>This one was really tough for me because it was so hard. I honestly try to budget, but there are times you just find yourself overspending. I realized later on that this mostly a problem of how disciplined I was, and not how much money I had. I’ve been putting in more effort into keeping a budget, but mine is more flexible than strict. Flexible in the sense that I always have a strict amount of money that goes into savings and investment, and any other “important” thing at the time, and then the rest of money goes into surviving.😭</p>
<h3 id="heading-saving"><strong>Saving</strong></h3>
<p>When it comes to savings, I want to say that I did well. But omo, the last couple months of the year, the only thing I was saving was myself. 💀</p>
<h2 id="heading-relationships"><strong>Relationships</strong></h2>
<h3 id="heading-family"><strong>Family</strong></h3>
<p>I spend most of the year in school, honestly this has been the case since secondary school because I attended a boarding school. But I did put in effort to communicate with my parents and siblings as often as I could. I am really fortunate to have my family members who tirelessly support me in everything that I do. Honestly there were a lot of times this year that I needed encouragement and my parents were always there for me. My brother is also one of the biggest reasons I have achieved quite a number of things career-wise, I’m really grateful for all the resources and guidance he’s provided me with. I’m also grateful that I spent this Christmas with every single member of my family in the same house in good health. I hope to be able to give back and contribute to my family’s well being next year.</p>
<h3 id="heading-friends"><strong>Friends</strong></h3>
<p>I spent so much of my time alone this past year. Why? Because it’s how I’ve always lived my life. I’m not saying I don’t have friends or that I don’t like spending time with them, but I really enjoy my personal space. Although this was okay for the most time, other times, the silence stung. This year, the loneliness crept in a lot, a reminder that solitude, while cherished, shouldn't morph into isolation. I think things got better generally. I’m really grateful for the roommates I had in my 300 level Omega semester, my friends, including those from HSL, GDSC, and MLSA. I never get to tell them, but I really appreciate the time we spent, the memories we made and the jokes we laughed to. One of the things I’d love to do this year is to make more meaningful friendships and be a better friend to those already here.</p>
<h3 id="heading-romance"><strong>Romance</strong></h3>
<p>"Omo guy, there's this babe I started talking to..." Yeah, that phrase got a fair workout this year. I think I’ve painfully gained more clarity as to the kind of things I’d want from a romantic relationship. I’d say it was all worth it, those pointless talking stages that never really went anywhere kind of mattered, and along the way I kind of realised why things haven’t been working out. This year, I’m focusing more on quality than quantity. I hope to meet attractive women with substance, character, and personality, and until that time comes, I’m learning how to be a better man.</p>
<h2 id="heading-academics"><strong>Academics</strong></h2>
<p>From having my worst ever GPA at the start of the year to having my best ever GPA the next semester, I really saw things this year. My relationship with my academics is really weird. There are times when I’ve just felt like completely giving up on school, and times where I kind of enjoy the concepts I’m learning (rarely). Overall I’ve just realised that if I really want to do well academically, I’d have to sacrifice a lot of things. And the question I keep asking myself is—Is the juice worth the squeeze?</p>
<p>I’ve decided that I’m going to give my possible best to graduate with a first class CGPA, and if ever my best isn’t enough, then I know that I tried.</p>
<h2 id="heading-learnings"><strong>Learnings</strong></h2>
<h3 id="heading-tech"><strong>Tech</strong></h3>
<p>I didn’t learn that many new technologies this year. My major goal was to get better at the ones I already use to the point that I could build anything I wanted. And build I did! I built a couple of <a target="_blank" href="https://github.com/victorcodess">projects</a> this year, the most important was my <a target="_blank" href="https://victorwilliams.me/">portfolio website.</a> I had lots of fun working on it, it was my first time using Framer Motion and GSAP. I also learnt Typescript this year, and I haven’t looked back ever since. I got better at React and Tailwind CSS too. But the real game-changer was my internship at Mono. Software engineering and product building went from blurry concepts to tangible experiences. I wasn’t able to get into backend development as I initially planned to, but trust me, it's on my radar for 2024. And oh, I started learning Three.js and Blender at the end of 2023, and it’s been exciting.</p>
<h3 id="heading-personal-life"><strong>Personal life</strong></h3>
<p>Personal growth? This year, I made it my middle name (well, not officially, but you get the picture). I took some really important steps to ensure that all major aspects of my life were being developed and I was becoming more of a well-rounded person. Books, well, they deserve their own chapter (a chapter I wish I'd been reading more diligently in 2023!).</p>
<p>This year, I discovered the power of simply showing up. It wasn't about pushing through exhaustion or ignoring all other needs, but about being present and making a genuine effort, even when I felt uninspired. Sometimes, showing up meant forcing myself to focus in class, even when the lecturer's monotone lulled me to sleep. Other times, it meant opening a book, even if I struggled to focus. But each time, showing up, in whatever form it took, chipped away at resistance and paved the way for unexpected progress. It taught me that consistency, not intensity, is the key to growth. Showing up isn't always easy, but it's become my anchor, reminding me that progress often lies just beyond the edge of my comfort zone. As James Clear said―if you can get 1 percent better each day for one year, you’ll end up thirty-seven times better by the time you’re done.</p>
<p><img src="https://jamesclear.com/wp-content/uploads/2015/08/tiny-gains-graph-700x700.jpg" alt="How to Master the Art of Continuous Improvement" /></p>
<p>A friend of mine once told me something that hasn’t left me ever since―Every action you take or don’t take has a consequence, whether good or bad, that you must accept. I realise that for every decision I make, I have to think to myself―would I be able to live with the consequence that comes from this? If I don’t read today, would I be fine with the queue of C’s in my result? Would indulging in this second bottle of La Casera be worth the self-reproach? The answer wasn't always easy, but the awareness sharpened my focus, guiding me towards the choices that aligned with my long-term goals.</p>
<h2 id="heading-whats-next"><strong>What's next?</strong></h2>
<blockquote>
<p>Don't you ever stop running, and don't you ever look behind you. All that exists is what's ahead. ― Secretariat</p>
</blockquote>
<p><strong>No resolutions, just daily revolutions.</strong> I'm ditching goals for systems, chasing sunsets instead of summits. This year's anthem is whispered words, not blaring pronouncements. I'll wander maps and minds, write stories on screens and faces, learn from books and laughter. Kindness will be my ripple, love my wildfire. Forget conquering, I'm savoring. Forget existing, I'm living. Welcome, 2024, let's dance.</p>
<p><em>I poured my heart into this, and I hope you had a good read! If you did, a like and comment would make my day! Thank you and have an amazing year. ❤️</em></p>
]]></content:encoded></item><item><title><![CDATA[Reflecting on My 18th Year: A Personal Review of 2022]]></title><description><![CDATA[As I close out my 18th year, I want to take a moment to reflect on all the progress and growth I've experienced in various areas of my life. In this super personal article, I'll share my thoughts on my work and career, academics, finance, health, rel...]]></description><link>https://blog.victorwilliams.me/reflecting-on-my-18th-year-a-personal-review-of-2022</link><guid isPermaLink="true">https://blog.victorwilliams.me/reflecting-on-my-18th-year-a-personal-review-of-2022</guid><category><![CDATA[review]]></category><category><![CDATA[yearinreview]]></category><category><![CDATA[#growth]]></category><category><![CDATA[internships]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Victor Williams]]></dc:creator><pubDate>Sat, 31 Dec 2022 18:25:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1672494063925/1ee2925f-e529-4a8b-9dd7-6eea996a34eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As I close out my 18th year, I want to take a moment to reflect on all the progress and growth I've experienced in various areas of my life. In this super personal article, I'll share my thoughts on my work and career, academics, finance, health, relationships, and the things I've learned over the past year. Come along with me as I look back on my journey and set some new goals for the future.</p>
<p>This year has been pretty amazing, and I'm grateful for all the great experiences I've had. This is my first time doing an end-of-year review, and it's been cool to see how much more intentional I've become about my growth. There have been a lot of ups and downs this year, and while I'd love to focus just on the ups, that wouldn't give the full picture.</p>
<p>I officially became an adult this year when I turned 18 in April, but I still have a long way to go before I feel like one. There are still lots of areas where I have room to grow, like my finances, health, relationships, and career, so I feel like I'm just getting started on this whole adult thing.</p>
<hr />
<h2 id="heading-what-went-well-the-good-wins-and-successes">What went well <strong>—</strong> The Good, Wins, and Successes</h2>
<h3 id="heading-here-are-some-of-my-biggest-wins-this-year">Here are some of my biggest wins this year:</h3>
<ul>
<li><p>I started learning UI/UX design at the start of the year (actually back in December 2021, but I started taking it more seriously this year).</p>
</li>
<li><p>I got my first actual job ever as a Product designer at an early-stage branding agency called Crown Branding Agency.</p>
</li>
<li><p>At Crown, I worked on 3 real-life projects for clients. These projects have gone on to be built and deployed.👑</p>
</li>
<li><p>I took time to work on my resume and started applying for internships at international companies and I got OAs (Online Assessments) at Google, JPMorgan, and Optiver.</p>
</li>
<li><p>I started taking LeetCoding seriously, and I solved about 55 easy questions and 4 medium questions. I was also able to maintain a 25-day streak.</p>
</li>
<li><p>I got accepted into the Microsoft Learn Student Ambassador program.🤩</p>
</li>
<li><p>I came 3rd at the Microsoft Cloud Skills Challenge that was held in September.</p>
</li>
<li><p>I was able to advance from a New milestone to Alpha and then to Beta Milestone after holding my first workshop.🚀</p>
</li>
<li><p>I started the first Microsoft Student Community at Covenant University and we're now at about 60 members.</p>
</li>
<li><p>I hosted 3 technical workshops for members of the community.</p>
</li>
<li><p>I was appointed as the lead for the vanilla Javascript team in my 200-level omega semester at our university's Google developer Student Club. Our team was able to build a seafood restaurant website by the end of the semester which was pretty cool.✨</p>
</li>
<li><p>I later got appointed as a member of the core team for the 2022/2023 session. I also offered to serve as the cohort lead for Reactjs. I got to work with these amazing people: <a target="_blank" href="https://www.linkedin.com/in/james-nottidge-43b66321b/?originalSubdomain=ng">James</a>, <a target="_blank" href="https://www.linkedin.com/in/israel-galadima-446a54198/?originalSubdomain=ng">Israel</a>, <a target="_blank" href="https://www.linkedin.com/in/olubusolami-sogunle-0308041b1/">Busola</a>, <a target="_blank" href="https://www.linkedin.com/in/loba000/">Tobi</a>, <a target="_blank" href="https://www.linkedin.com/in/aweayo/">Awe</a>, and <a target="_blank" href="https://www.linkedin.com/in/jesse-paul-osemeke/">Jesse</a>.</p>
</li>
<li><p>I started earning corporate money this year. I also learned a lot about investing and personal finance. I started investing and saving more money too.</p>
</li>
<li><p>I got serious about coding again and started learning Javascript from scratch.</p>
</li>
<li><p>I actually built a couple of cool things this year. I built :</p>
<ul>
<li><p><a target="_blank" href="https://url-shortener-nine-delta.vercel.app/">A website that helps you shorten long URLs</a> 🔗</p>
</li>
<li><p><a target="_blank" href="https://alpaca-image-generator-beta.vercel.app/">An image generator website that allows users to generate, combine, and download images of an Alpaca</a> 🦙</p>
</li>
<li><p><a target="_blank" href="https://sky-watch.vercel.app/">A web app that lets you check the current weather and forecast for the next 2 days in any city</a> 🌦️</p>
</li>
</ul>
</li>
<li><p>I spent Christmas with my family all safe and sound.💕</p>
</li>
<li><p>I ended the year with a First Class CGPA.</p>
</li>
<li><p>I started getting a bit more serious with schoolwork.</p>
</li>
<li><p>I attended DevFest Lagos.</p>
</li>
<li><p>I learned a couple of new technologies like React, Next.js, and MaterialUI.</p>
</li>
<li><p>I started learning more about myself and started reading more personal growth books.</p>
</li>
</ul>
<hr />
<h2 id="heading-what-didnt-go-well-the-bad-losses-and-imperfections">What didn't go well <strong>—</strong> <strong>The Bad, Losses, and Imperfections</strong></h2>
<h3 id="heading-here-are-some-of-my-biggest-losses-this-year">Here are some of my biggest losses this year:</h3>
<ul>
<li><p>I lost my scholarship due to the carelessness of a lecturer. By the time I revalidated my result and got it remarked, it was already too late.</p>
</li>
<li><p>I got rejected by all the companies I applied to. Most companies didn't even send OAs because my graduation date was too far (2025), and some because they weren't offering sponsorships to international students. I also failed my OAs with Google, JPMorgan, and Optiver, majorly due to my incompetence.</p>
</li>
<li><p>Felt like a failure at some point for not getting invited to interviews.🫠</p>
</li>
<li><p>I tried to read many "non-school" books this year but I never had the time to finish most of them. It's either I get distracted by work or something else while trying to read.</p>
</li>
<li><p>I didn't get accepted into the GitHub Campus Expert program, even after putting so much effort into my application.</p>
</li>
<li><p>I maintained a lot of my bad eating and posture habits for most of the year.</p>
</li>
<li><p>After almost 2 months of grinding LeetCode, I started getting burnt out because I couldn't balance it with everything I was doing. I decided to "pause", but I found it hard to get back ever since.</p>
</li>
<li><p>I didn't reach my savings goals because of my poor spending habits.</p>
</li>
<li><p>The stock market showed me crazy shege.😭</p>
</li>
<li><p>I didn't invest enough energy into my social life, and I kept on beating myself up so much about it.</p>
</li>
<li><p>My CGPA dropped so badly, mainly because I fell ill during exams.</p>
</li>
<li><p>I started lapsing a lot in school work because I was focusing most of my energy on my career and extracurriculars.</p>
</li>
<li><p>Spent way too much time on social media, and it really affected my mental well-being.</p>
</li>
<li><p>There were quite a couple of things I wanted to be and achieve this year, but I didn't.🫠</p>
</li>
</ul>
<hr />
<h2 id="heading-what-did-i-learn-moving-forward-plans-for-2023">What did I learn <strong>—</strong> Moving Forward, Plans for 2023</h2>
<h3 id="heading-here-are-some-things-i-learned">Here are some things I learned:</h3>
<p>I feel the most important thing I learned this year was that I always have to be intentional about my personal growth. The sad reality of life is that nobody is ever going to be able to do these things for you, most especially as an adult. The choices I make every day are always going to impact the person I become. I also learned that one of the most important skills I need to learn as an individual is self-discipline and the courage to do the things I have set to do.</p>
<p>Something I also realized this year is that there's more to me as a person than just "Tech and Programming". I've always been passionate about Fashion and Music and I want to put more effort into exploring my creative side.</p>
<h3 id="heading-here-are-some-of-my-plans-for-next-year">Here are some of my plans for next year:</h3>
<p>My utmost goal for 2023 is to be better than 2022</p>
<ul>
<li><p>Get beastly at UI design🧑🏿‍🎨</p>
</li>
<li><p>Read at least 1 book every month (non-school books)</p>
</li>
<li><p>Do my IT at a reputable tech company in Nigeria</p>
</li>
<li><p>Bag an internship at an International company for my 400-level IT</p>
</li>
<li><p>Grind more LeetCode and get pretty good at medium questions</p>
</li>
<li><p>Invest in building more meaningful and genuine relationships</p>
</li>
<li><p>Learn Typescript, NodeJS, TailwindCSS, Express.js, MongoDB, Framer motion, WebGL, and three.js.</p>
</li>
<li><p>Build something cool with AI or Blockchain</p>
</li>
<li><p>Recruit more people into the Ambassadors program</p>
</li>
<li><p>Earn my first million💸💸</p>
</li>
<li><p>Improve my social life, maybe even commit👀</p>
</li>
<li><p>Increase my network and get to know more people</p>
</li>
<li><p>Continue to impact the entire developers' community at Covenant University🦅</p>
</li>
<li><p>Get into technical writing and release at least 10 articles before the end of the year</p>
</li>
<li><p>Earn in dollars🤑</p>
</li>
<li><p>Become a GitHub Campus Expert</p>
</li>
<li><p>Receive an academic scholarship</p>
</li>
<li><p>End the year with a First Class CGPA</p>
</li>
<li><p>Take my health more seriously</p>
</li>
<li><p>Save up to a million naira</p>
</li>
<li><p>Start therapy🫂</p>
</li>
<li><p>Spend more time with family and friends🧑🏿‍🧑🏿‍🧒🏿💕</p>
<hr />
</li>
</ul>
<p>I'm honestly grateful for all that was, and I can't wait for the amazing things that are to be.</p>
<p>Thanks for reading💕</p>
]]></content:encoded></item></channel></rss>