<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kobe Ruado</title>
    <description>The latest articles on Forem by Kobe Ruado (@insidiae).</description>
    <link>https://forem.com/insidiae</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F728996%2F2b2cc78c-eed0-48f5-8139-6e0fd9569770.png</url>
      <title>Forem: Kobe Ruado</title>
      <link>https://forem.com/insidiae</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/insidiae"/>
    <language>en</language>
    <item>
      <title>Making More Meaningful Contributions in Hacktoberfest 2023</title>
      <dc:creator>Kobe Ruado</dc:creator>
      <pubDate>Tue, 31 Oct 2023 15:49:23 +0000</pubDate>
      <link>https://forem.com/insidiae/making-more-meaningful-contributions-in-hacktoberfest-2023-4agp</link>
      <guid>https://forem.com/insidiae/making-more-meaningful-contributions-in-hacktoberfest-2023-4agp</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Hacktoberfest is a great way to get started making contributions to open source projects. As this month comes to a close, I want to share my experience as a contributor for this year's Hacktoberfest, as well as the things I learned along the way as I make more meaningful contributions than previous years.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started contributing to Open Source with Hacktoberfest
&lt;/h2&gt;

&lt;p&gt;When I started learning to code, I was using GitHub mainly as a place to track my progress as I take online courses and build projects to improve my developer skills, meaning pretty much all I did was commit my code and push straight to the &lt;code&gt;main&lt;/code&gt; branch. But I knew I can do so much more than that. I always wanted to make my own contributions to open source, but back then I felt I don't have enough skills to navigate the extremely large codebases of popular open source repositories. But sure, even if I can't navigate those popular repos with their large codebases, at least there's loads of guides on how to find &lt;a href="https://goodfirstissue.dev/" rel="noopener noreferrer"&gt;good first issues&lt;/a&gt; or smaller projects with more beginner-friendly issues that I can tackle!&lt;/p&gt;

&lt;p&gt;Looking back, making my first PR was a lot easier said than done. I didn't want my first PRs to be just scanning the project READMEs for typos then make a PR to fix it and call it a day. I want to make some REAL open source contributions. I want to &lt;em&gt;write some code&lt;/em&gt;! But how on earth am I gonna make those PRs if all I knew was basic HTML/CSS/JS, maybe throw in some React and maybe a &lt;em&gt;liiiiittle&lt;/em&gt; bit of Python from that one time I was exploring some AI/ML stuff? I can't take those "good first issues" if I don't even know the programming language those projects are written in!&lt;/p&gt;

&lt;p&gt;So when I first heard about Hacktoberfest back in 2021, I thought it would be a great starting point for me to make commits and pull requests (PRs) outside of my own repos. It's also a time where a lot of tech communities get together and collaborate on a fairly large project while still being accessible to beginners like me! So that's what my first (legit) Hacktoberfest contributions came to be - I participated in tech communities hosting Hacktoberfest events, found some collaborative projects where I can apply my skills, and followed each project's contribution guidelines to get my PRs approved really quick!&lt;/p&gt;

&lt;p&gt;For Hacktoberfest 2022, I wanted to make contributions to bigger open-source repos, not just the one-off projects created specifically for Hacktoberfest to be archived later. My development skills also improved a lot in that year, so I was more confident in finding open source projects that have open issues that match my skillset! So I still participated in community-led Hacktoberfest projects, but I also explored some popular repos to see if I can make some PRs in larger-scale projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Environments FTW
&lt;/h3&gt;

&lt;p&gt;My biggest highlight for Hacktoberfest 2022 was making contributions for &lt;a href="https://github.com/freeCodeCamp/freeCodeCamp" rel="noopener noreferrer"&gt;freeCodeCamp&lt;/a&gt; and &lt;a href="https://github.com/codesandbox/sandpack" rel="noopener noreferrer"&gt;Sandpack&lt;/a&gt;, and I want to highlight how I navigated these popular repos even when they have such large codebases.&lt;/p&gt;

&lt;p&gt;The biggest thing that helped me make contributions to freeCodeCamp and Sandpack was that they both have configurations that we can use to open the repos in cloud environments (Gitpod for freeCodeCamp, CodeSandbox for Sandpack) and let them automagically handle the setup and properly install the projects' dependencies. This lets me just focus on working on the changes I need to make and also test if my solutions actually solve the issues I was working on.&lt;/p&gt;

&lt;p&gt;So what sort of issues did I solve in these oh-so-complex projects?&lt;/p&gt;

&lt;p&gt;...I clarified some instructions in one of freeCodeCamp's lessons, and added new themes for Sandpack. 😅&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.npr.org%2Fassets%2Fimg%2F2023%2F05%2F26%2Fhonest-work-meme-cb0f0fb2227fb84b77b3c9a851ac09b095ab74d8-s1100-c50.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.npr.org%2Fassets%2Fimg%2F2023%2F05%2F26%2Fhonest-work-meme-cb0f0fb2227fb84b77b3c9a851ac09b095ab74d8-s1100-c50.jpg" alt="It ain't much, but it's honest work"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yeah, my PRs were pretty simple, but I learned another valuable lesson that I can use to keep contributing on projects as big as those!&lt;/p&gt;

&lt;h3&gt;
  
  
  The value of reading instructions
&lt;/h3&gt;

&lt;p&gt;Ideally, each open source project should have instructions on how to navigate their codebase and start making contributions, or at least install the dependencies and get their project working either locally on your machine or a cloud environment like I mentioned before, which you can usually find in a &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; file. Additionally, you can also sort the &lt;code&gt;Issues&lt;/code&gt; tab and filter the issues labelled something like "good first issue", "help wanted", "contributions welcome", etc. Heck, some projects can even have issues that the maintainers posted specifically for Hacktoberfest!&lt;/p&gt;

&lt;p&gt;Even if the project can initially seem too big for you to navigate, following these sorts of instructions can get you a long way to making meaningful contributions. In fact, reading setup instructions was how I found out that I can use cloud environments to help me make changes to big repos (CodeSandbox also has some &lt;a href="https://codesandbox.io/blog/get-started-with-hacktoberfest" rel="noopener noreferrer"&gt;great&lt;/a&gt; &lt;a href="https://dev.to/codesandboxio/contribute-to-sandpack-in-hacktoberfest-4j65"&gt;guides&lt;/a&gt; on how to make your contributions via CodeSandbox)!&lt;/p&gt;

&lt;h2&gt;
  
  
  Growth
&lt;/h2&gt;

&lt;p&gt;And now, here we are with Hacktoberfest 2023. For this year my goal is really straightforward: Use the skills I learned and make my Hacktoberfest PRs in open source repos that I have either used in my projects before or at least follow on GitHub/Twitter/etc, and continue that momentum to keep contributing to open source projects beyond Hacktoberfest.&lt;/p&gt;

&lt;p&gt;I'm extremely pleased to say that I made better contributions this year than the previous Hacktoberfest! Here's a quick recap:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I &lt;a href="https://github.com/cloudinary-community/cloudinary-examples/pull/61" rel="noopener noreferrer"&gt;fixed a code example&lt;/a&gt; in Astro's docs &lt;del&gt;okay that was a two-line fix just changing some imports but still&lt;/del&gt;
&lt;/li&gt;
&lt;li&gt;I added &lt;a href="https://github.com/cloudinary-community/cloudinary-examples/pull/61" rel="noopener noreferrer"&gt;a Remix version for a Product Gallery&lt;/a&gt; in Cloudinary's example integrations&lt;/li&gt;
&lt;li&gt;I &lt;a href="https://github.com/freeCodeCamp/freeCodeCamp/pull/52016" rel="noopener noreferrer"&gt;created a Playwright test&lt;/a&gt; for one of freeCodeCamp's UI components&lt;/li&gt;
&lt;li&gt;I &lt;a href="https://github.com/colbyfayock/cloudinary-util/pull/78" rel="noopener noreferrer"&gt;fixed some TypeScript types&lt;/a&gt; for Cloudinary's utils package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I'm not fully satisfied with the contributions I made this Hacktoberfest (I still think the PRs I'm making remain relatively small), but they do feel a lot more impactful than my PRs in the previous editions of Hacktoberfest.&lt;/p&gt;

&lt;p&gt;Moving forward, I'm really excited to keep contributing to open source projects using the skills I developed in Hacktoberfest events. In a way, writing this blog post serves as my pledge to continue this good momentum I built and keep making better, more meaningful contributions to open source porjects even outside Hacktoberfest!&lt;/p&gt;

&lt;h2&gt;
  
  
  How can YOU make more meaningful open source contributions?
&lt;/h2&gt;

&lt;p&gt;Want to join me in making impactful contributions and give back to the wonderful open source projects you use in your projects? I've got you covered! Here are some tips and tricks I wish I knew when starting out making contributions to other people's projects:&lt;/p&gt;

&lt;h3&gt;
  
  
  Join active tech communities
&lt;/h3&gt;

&lt;p&gt;If you're an absolute beginner and you don't know many programming languages/frameworks or other advanced topics, participating in tech communities can be a great way to get started working in open source! A lot of tech communities have their collaborative projects that members can actively participate in and applying various things while learning to code, plus Hacktoberfest is also a great time for these communities to host their own events with even more open source projects to contribute to!&lt;/p&gt;

&lt;h3&gt;
  
  
  Build more projects
&lt;/h3&gt;

&lt;p&gt;When finding open source projects to contribute to, there's really no going around simply building more projects and using more open source tools/frameworks along the way. Not only does it give you more experience writing better code, it also gives you a lot better context when use various open source tools/frameworks, encounter issues/bugs or something that you think can be improved, and gives you more incentive to make your own contributions!&lt;/p&gt;

&lt;h3&gt;
  
  
  RTFM
&lt;/h3&gt;

&lt;p&gt;Like I mentioned before, reading instructions commonly found in the projects' &lt;code&gt;README.md&lt;/code&gt; or &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; can help a lot especially if you need to run their code in your local machine (or use cloud environments if you're having trouble installing stuff). Reading the issues you want to work on also helps in making your PR - a lot of well-written issues often give enough context of the problem or even give hints to the solution that needs to be done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Documentation/Localization PRs are underrated
&lt;/h3&gt;

&lt;p&gt;A growing trend I see in Hacktoberfest events is open source projects looking for extra help on documentation or localization. At first glance these might seem like very small fixes, but I often find them equally as meaningful as code contributions, since working with documentations/localizations often involve a lot of communication with the project maintainers to ensure their topics can get relayed properly to other developers looking to use their project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collaborate!
&lt;/h3&gt;

&lt;p&gt;At the end of the day, Hacktoberfest is an event that encourages proper collaboration with open source project maintainers to ensure the quality of contributions. When you find an issue you want to work on, be sure to follow the guidelines set by the project maintainers such as waiting to be assigned before making your PR and using the post templates they provide when you do open your PR, and be sure to follow the maintainers' instructions when they request a change in your PR. Not only does it improve the chance of your PR getting merged faster, collaborating with project maintainers also lightens up their workload to ensure that all contributions follow a certain standard of quality.&lt;/p&gt;

&lt;p&gt;Hacktoberfest is a great event for beginners to get started giving back to the developer community by making contributions to open source, but the contributions shouldn't stop after this event ends! Keep participating in your local communities, building more projects, and make your next contributions to open source more meaningful.&lt;/p&gt;

&lt;p&gt;See you next year!&lt;/p&gt;

</description>
      <category>hack23contributor</category>
    </item>
    <item>
      <title>Building Headless Data Visualizations with D3.js</title>
      <dc:creator>Kobe Ruado</dc:creator>
      <pubDate>Sun, 31 Jul 2022 11:41:55 +0000</pubDate>
      <link>https://forem.com/insidiae/building-headless-data-visualizations-with-d3js-cj8</link>
      <guid>https://forem.com/insidiae/building-headless-data-visualizations-with-d3js-cj8</guid>
      <description>&lt;p&gt;D3.js is perhaps the most popular framework for building data-driven visualizations in the web. It offers a wide variety of tools that give dynamic properties based on the data that we pass in. It's also a fully-featured framework for working with the DOM, allowing us to give these dynamic properties into tangible elements in the web page.&lt;/p&gt;

&lt;p&gt;D3 got me really interested in building all kinds of interactive charts, so I decided to take the &lt;a href="https://www.newline.co/fullstack-d3"&gt;Fullstack D3&lt;/a&gt; course to help me get going! The biggest takeaway I got from there is this 7-step process for building any dataviz component:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch/Access data&lt;/li&gt;
&lt;li&gt;Create chart dimensions (how big do we want our chart to be?)&lt;/li&gt;
&lt;li&gt;Draw the canvas (use the dimensions to define the inner/outer bounds of our chart)&lt;/li&gt;
&lt;li&gt;Create scales (transform data values into dynamic properties)&lt;/li&gt;
&lt;li&gt;Draw data&lt;/li&gt;
&lt;li&gt;Draw peripherals (like the X/Y axes, annotations/legends, etc.)&lt;/li&gt;
&lt;li&gt;Set up interactions (like showing tooltips on hover)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's create a simple Line Chart using D3 as an example. I'm using &lt;a href="https://www.youtube.com/watch?v=S3LNbBg_B2A"&gt;the same Line Chart example from the free chapter of the Fullstack D3 course&lt;/a&gt;. It doesn't include Step 7, but this example should be good enough to show our step-by-step process in action!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;drawLineChart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//* Step 1. Access Data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./data/my_weather_data.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;temperatureMax&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 2. Create chart dimensions&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 3. Draw canvas&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#wrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;wrapper&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px)`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 4. Create scales&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yAccessor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xAccessor&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperatures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hsl(180deg 44% 92%)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "#e0f3f3"&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 5. Draw data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lineGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xAccessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yAccessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lineGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fill&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stroke&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hsl(41deg 35% 52%)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// "#af9358"&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stroke-width&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 6. Draw peripherals&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yAxisGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axisLeft&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yAxis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yAxisGenerator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xAxisGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;axisBottom&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xAxis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bounds&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translateY(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;px)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xAxisGenerator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;drawLineChart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In less than 90 lines of code, we can display this basic line chart:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l3e0lwLl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj1r9kh7a01zeh09f1py.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l3e0lwLl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jj1r9kh7a01zeh09f1py.png" alt="Vanilla line chart" width="880" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For vanilla JS projects this code is usually good enough, but I wanted to go a step further. I wanted to integrate D3 code into my existing React projects, so I took some time &lt;a href="https://github.com/Insidiae/fullstack-d3-react"&gt;rewriting the course exercises and projects&lt;/a&gt; from vanilla D3 into D3 + React (+ TypeScript, for extra challenge).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Headless UI?
&lt;/h2&gt;

&lt;p&gt;The Headless UI pattern (not to be confused with &lt;a href="https://headlessui.com/"&gt;the Tailwind Labs project&lt;/a&gt; with the same name) is a pattern in which the logical parts (i.e. the state, dynamic properties, lifecycle methods, etc.) of components are separated from the rendering logic (i.e. the HTML markup and the CSS styles).&lt;/p&gt;

&lt;p&gt;I recently watched &lt;a href="https://www.youtube.com/watch?v=O4IWJcafX8c"&gt;an excellent talk in React Summit&lt;/a&gt; about using the Headless UI pattern in a well-known open-source library, and I realized "Huh, Isn't this pretty much what I've been doing with my D3+React rewrite project?"&lt;/p&gt;

&lt;p&gt;And indeed, when I rewrite my D3 charts into React I can see a clear separation between the logical parts of my chart and the markup I render into the page. This makes sense, because I'm still using the same tools D3 gives me, but I swapped the D3 selectors and data joins out and let React handle the rendering instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using D3 for Headless Data Visualizations
&lt;/h2&gt;

&lt;p&gt;As it turns out, our step-by-step process gives us a clear opportunity to separate the logical parts of our chart from the markup and styles!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9dA2CfXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt79ya1mzz2bihqyz4pi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9dA2CfXa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt79ya1mzz2bihqyz4pi.png" alt="Our 7-step process, now with Headless UI" width="880" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my React rewrite of that Line Chart example from earlier, the logical parts of the chart only consists of steps 1, 2, and 4, as well as some helpers for steps 5 and 6. Notice how we're still using the same D3 methods to get the scales and generator functions for our data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;LineChart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//* Step 1b. Access Data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;temperatureMax&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 2. Create chart dimensions&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoundedDimensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;//? Initialize the bounded dimensions here, so TypeScript doesn't get all fussy&lt;/span&gt;
    &lt;span class="na"&gt;boundedWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;boundedHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;//* Step 4. Create scales&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;xAccessor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scaleLinear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yAccessor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;//* Set up steps 5 and 6&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lineGenerator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xAccessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;yAccessor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xTicks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yTicks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ticks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;//* The rest is the rendering logic&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rendering logic for step 6 actually gets a bit tricky, since we used some built-in D3 methods to put our X/Y axes directly into the DOM. Fortunately, D3 also gives us some handy tools to build our own X/Y axes from scratch, with a bit of peeking at the final rendered output to check the markup we need to copy.&lt;/p&gt;

&lt;p&gt;Here's what our markup now looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;LineChart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;dataset&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//* Steps 1, 2, and 4 omitted for brevity&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Step 3. Draw canvas */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt; &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
          &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;rect&lt;/span&gt;
            &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt;
            &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;freezingTemperaturePlacement&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hsl(180deg 44% 92%)"&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Step 5. Draw data */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;path&lt;/span&gt;
            &lt;span class="na"&gt;d&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;lineGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;
            &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"hsl(41deg 35% 52%)"&lt;/span&gt;
            &lt;span class="na"&gt;strokeWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Step 6. Draw peripherals */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;
            &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sans-serif"&lt;/span&gt;
            &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"middle"&lt;/span&gt;
            &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(0, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="na"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedWidth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;xTicks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;xScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;, 0)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="na"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0.71em"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"sans-serif"&lt;/span&gt; &lt;span class="na"&gt;textAnchor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="na"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boundedHeight&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;yTicks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`translate(0, &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;yScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;line&lt;/span&gt; &lt;span class="na"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt; &lt;span class="na"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"0.32em"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;g&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;svg&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LAjXY63I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8m27ng5ny7j3rle1ckm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LAjXY63I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8m27ng5ny7j3rle1ckm.png" alt="Line chart rewritten in React" width="880" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It doesn't look &lt;em&gt;exactly&lt;/em&gt; the same, but I think it's pretty indistinguishable from our original example unless you squint hard enough!&lt;/p&gt;

&lt;p&gt;The full code for the Line Chart rewritten in React results in slightly longer code, adding up to a little over 100 lines. I'd say that's good enough, given that we had to create our X/Y axes from scratch!&lt;/p&gt;

&lt;p&gt;What's more, we can actually make our Line Chart a bit more reusable. We can skip Step 2 by accepting the chart dimensions as a prop instead, and we can also make a different Line Chart for other metrics my passing the metric we want as a prop as well (as long as that metric returns a numeric value, of course 😉)!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;LineChart&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BoundedDimensions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NumericWeatherDataMetric&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//* Step 1b. Access Data&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;d3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;%Y-%m-%d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dateParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;yAccessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WeatherData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;//* We can skip Step 2 here because we're now accepting the dimensions as a prop.&lt;/span&gt;

  &lt;span class="c1"&gt;// Literally everything else stays the same!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;Another awesome part of that React Summit talk was taking the Headless UI pattern one step further and going &lt;em&gt;Framework Agnostic&lt;/em&gt;, essentially having the same functionality no matter which framework you use. Let's apply the same concept with our Line Chart!&lt;/p&gt;

&lt;p&gt;Adding code snippets for the same component written in different frameworks feels redundant, so I'll just provide links instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Insidiae/headless-d3/tree/main/vue"&gt;Vue Line Chart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Insidiae/headless-d3/tree/main/svelte"&gt;Svelte Line Chart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Insidiae/headless-d3/tree/main/solid"&gt;Solid Line Chart&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a quick tl;dr:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separating the logical parts of our chart from the markup and styles pretty much did most of the heavy lifting for making our chart framework agnostic! The main difference across my rewrites had to do with the framework-specific ways to render the markup, and passing the dynamic properties to the relevant elements.&lt;/li&gt;
&lt;li&gt;Having the same logic reused across different frameworks let me do these rewrites a lot faster than I expected! I had basically zero knowledge on how to write Vue/Svelte/Solid components before I did these rewrites, but since I already know what goes into the Line Chart, all it took to rewrite it in these different frameworks was a couple minutes of browsing thru their respective docs about a few basic topics on their rendering logic:

&lt;ul&gt;
&lt;li&gt;Fetching data&lt;/li&gt;
&lt;li&gt;Passing props to components&lt;/li&gt;
&lt;li&gt;Using dynamic properties in the markup&lt;/li&gt;
&lt;li&gt;Rendering lists&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I see a lot of potential with this Headless UI pattern paired with D3. For instance we can extract some of these commonly used D3 methods and generator functions into a custom React hook (or whatever their equivalents are in other frameworks), and make a reusable headless library of common charts powered by D3!&lt;/p&gt;

&lt;p&gt;Rewriting my previous D3 exercises and projects into React provided an even more awesome learning experience beyond the course material, and thanks to that one React Summit talk I also gained some new insights about reusable code patterns and even applied my knowledge in different frameworks!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>d3</category>
    </item>
    <item>
      <title>The 2022 Training Arc Begins!</title>
      <dc:creator>Kobe Ruado</dc:creator>
      <pubDate>Tue, 01 Feb 2022 04:20:38 +0000</pubDate>
      <link>https://forem.com/insidiae/the-2022-training-arc-begins-3ne9</link>
      <guid>https://forem.com/insidiae/the-2022-training-arc-begins-3ne9</guid>
      <description>&lt;p&gt;It's time to start the year off with a bang! I've had lots of fun &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/tree/main/Round%200"&gt;doing the #100DaysOfCode challenge last year&lt;/a&gt;, and I had an absolute blast doing several online courses and building their major course projects with my own personal take, from adding minor improvements and additional features to adding another layer to the tech stack used in the project. That's why I'm starting this year off with a fresh new round of &lt;a href="https://www.100daysofcode.com/"&gt;#100DaysOfCode&lt;/a&gt;, with more focus on doing the things I really like and satisfying my curiosity on the various technologies I encounter in my career.&lt;/p&gt;

&lt;p&gt;Over this past month I've been &lt;del&gt;taking a much-needed break from coding&lt;/del&gt; assembling a new curriculum of online courses I'll be taking this year, focusing mainly on courses with a ton of exercises and projects that I can maybe tweak to my liking as I learn more stuff over the course of this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/tree/main/Round%201"&gt;#100DaysOfCode Round 1: Mad Science&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This round is an improvement of sorts refining the ideas from the previous round I completed last year, improving the parts I really liked about last round, and developing a streamlined curriculum of online courses mostly about various topics I'm curious about (hence "Mad Science"), and other topics that reinforce the skills relevant to my career.&lt;/p&gt;

&lt;p&gt;My main task for this round remains the same: Complete as many of these courses as I can, making steady progress each day for the next 100 days. This includes, but is not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting the &lt;em&gt;100% Complete&lt;/em&gt; status on the course, and thus acquiring the Certificate of Completion&lt;/li&gt;
&lt;li&gt;Completing the course projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Online Courses?
&lt;/h3&gt;

&lt;p&gt;Honestly? Because it's fun! After doing a bunch of online courses last year, it tuned out to be something I very much enjoy. As such, I want to take the parts I liked about last round, refine these ideas to make a curriculum of online courses, and pretty much just continue doing what I love and make lots of progress this year!&lt;/p&gt;

&lt;p&gt;For this round, I've chosen exercise-driven courses for topics I don't know much about (or want to take a deeper dive in). To help myself come up with project ideas, something that I admittedly lack the skill (or creativity?) to do, I've also picked a bunch of project-based courses with some interesting and comprehensive projects that I can tweak to my liking as I learn more throughout this round. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Starting Lineup
&lt;/h2&gt;

&lt;p&gt;I've organized my courses into two distinct categories. The first category consists of courses where I plan to follow along with the course content from start to finish. These will typically be the courses that I'll be adding to my Main Curriculum for this round. The second category consists of courses about topics I've already done, or courses that have plenty of comprehensive projects about various topics. For these courses, I'll be taking the major course projects and use those as supplementary resources/extra credit material for my Main Curriculum courses, ideally incorporating the things I learn from the Main Curriculum courses to add extra features and/or provide an alternate implementation for these course projects.&lt;/p&gt;

&lt;p&gt;Here is the first batch of courses I plan on doing for this round:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://epicreact.dev/"&gt;Epic React&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Starting the year off strong with this course! I'm really excited about the workshop format of this course, which is unlike any other video-based course I've seen so far.&lt;/p&gt;

&lt;p&gt;Epic React also has a Typescript-based &lt;code&gt;next&lt;/code&gt; branch for most of its workshops, and I do plan on checking those out and learn Typescript as I go along with the course.&lt;/p&gt;

&lt;h4&gt;
  
  
  Supplemental Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/typescript-the-complete-developers-guide/"&gt;Typescript: The Complete Developer's Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💯 Extra Credit
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.freecodecamp.org/learn/front-end-development-libraries/#front-end-development-libraries-projects"&gt;freeCodeCamp - Front End Development Libraries Projects&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Build a Markdown Previewer&lt;/li&gt;
&lt;li&gt;Build a Drum Machine&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://css-for-js.dev/"&gt;CSS for Javascript Developers&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This is another course with a somewhat different format to what I'm used to with Udemy courses. Combined with a solid course content, I have high hopes that this course will help me get even better with CSS!&lt;/p&gt;

&lt;h4&gt;
  
  
  Supplemental Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.uifoundations.com/"&gt;UI Foundations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://zerotomastery.io/workshops-and-more/"&gt;ZTM Academy Workshop: Designer to Developer Handoff ➡ Design File to Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developedbyed.com/p/the-ultimate-javascript-animation-course"&gt;The Ultimate JavaScript Animation Course&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💯 Extra Credit
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.freecodecamp.org/learn/responsive-web-design/#responsive-web-design-projects"&gt;freeCodeCamp: Responsive Web Design Projects&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Build a Technical Documentation Page&lt;/li&gt;
&lt;li&gt;Build a Personal Portfolio Page&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;a href="https://www.newline.co/fullstack-d3"&gt;Fullstack D3 and Data Visualization&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;After I finished the D3 section of &lt;a href="https://www.udemy.com/course/the-advanced-web-developer-bootcamp"&gt;The Advanced Web Developer Bootcamp&lt;/a&gt; last year, I've always been intrigued by data visualization with D3. With this course, I hope to satisfy that curiosity about D3 and build some beautiful data visualization projects. Bonus points if I can combine React with D3 to make the visualizations interactive as well!&lt;/p&gt;

&lt;h4&gt;
  
  
  Supplemental Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/learn/data-visualization/"&gt;freeCodeCamp - Data Visualization Certification Projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  💯 Extra Credit
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Redo projects using React + D3&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Major Project - TBA
&lt;/h3&gt;

&lt;p&gt;I've got plans to redo a past E-commerce project into the latest version of the frameworks/libraries I used the first time around. More details soon!&lt;/p&gt;

&lt;h4&gt;
  
  
  Supplemental Resources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://advancedreact.com/"&gt;Fullstack Advanced React &amp;amp; GraphQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a lot more courses that I want to take other than the ones listed above, and for now I've organized them into &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/blob/main/Round%201/curriculum.md#specializations"&gt;Specializations&lt;/a&gt;, &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/blob/main/Round%201/curriculum.md#electives"&gt;Electives&lt;/a&gt;, and &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/blob/main/Round%201/curriculum.md#misc-project-grab-bag"&gt;other courses to take project ideas from&lt;/a&gt;. My plan is to do this first batch of courses first, then add these other courses into the Main Curriculum and see where my curiosity takes me!&lt;/p&gt;

</description>
      <category>100daysofcode</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>2021: Year in Review</title>
      <dc:creator>Kobe Ruado</dc:creator>
      <pubDate>Fri, 31 Dec 2021 11:49:38 +0000</pubDate>
      <link>https://forem.com/insidiae/2021-year-in-review-3i2l</link>
      <guid>https://forem.com/insidiae/2021-year-in-review-3i2l</guid>
      <description>&lt;p&gt;Hello world! To most of you this is probably the first time you've heard of me, but to a certain group of people this is the first time you've heard from me in a really long while. A lot has happened not just this year, but coming back from the 2020 lockdowns as well. Now that I'm feeling much better after this honestly amazing year, I think I can finally take a step back and talk about the mess I made and what I've been doing to make up for them. And what better way to explain myself than write my very first blog post about what exactly I've been up to?&lt;/p&gt;

&lt;p&gt;Let's talk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crash and burn
&lt;/h2&gt;

&lt;p&gt;2020 has not been a kind year to me, which I assume can also be said for a lot of other people. I had big plans at the time, ready to bounce back once and for all with a clear roadmap to graduation thanks to the help of my friends and mentors. And then the lockdowns started, and even in the comfort of my own home I found myself unable to fulfill even the simplest most basic requirements, and it snowballed to me ending up dropping literally every project I had.&lt;/p&gt;

&lt;p&gt;Looking back, I have to admit that this problem wasn't entirely caused by the lockdowns. Even a few years before I was barely scraping by, managing to do the bare minimum of tasks in both my work and at university so that I can at least call myself "productive". In hindsight I think that stubbornness only prolonged the inevitable, and failing to adjust with the &lt;em&gt;"new normal"&lt;/em&gt; of the lockdown period was the final nail in the coffin. I started dropping projects at work and even wasted my progress in my university thesis project, and the shame I felt from my failures made me cut off contact from basically the entire outside world, and isolated myself for months during the lockdown.&lt;/p&gt;

&lt;p&gt;One of the most memorable lessons I learned while I was working at startups was to fail fast, and fail often. What I think these lessons neglect to mention is that failures cost a lot. Even moreso when that one little misstep snowballs into more serious failures, and suddenly I find myself with a lot of burned bridges, friendships destroyed, and my reputation completely and utterly ruined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going up from rock bottom
&lt;/h2&gt;

&lt;p&gt;Somewhere along those several months of isolating myself, I realized that I needed to move forward somehow. I wanted to get rid of that nasty feeling of shame and disappointment, and if I can't do anything to make it up to the people I failed, the least I could do was to offer a genuine apology with the intent to work on improving myself and maybe not fail any more people next time.&lt;/p&gt;

&lt;p&gt;Towards the end of 2020, I started reaching out to a certain few of my most respected people (of which I felt that I disappointed the most) - At first I just wanted to apologize for my mistakes, not even expecting any response in return, I really just wanted to get some closure for my mistakes and maybe start moving on and screw up less next time. To my surprise I was actually greeted back with open arms, and after a few weeks of me sorting myself out I was offered back my job and before I know it, I got myself a miraculous second chance to continue the project I was previously working on.&lt;/p&gt;

&lt;p&gt;For the first few months of me getting back to work, I was playing it as safe as I possibly could, purely because I absolutely did not want to waste this miraculous second chance that I got and disappoint the people that put their trust in me yet again. Regardless, I contributed whatever I can to move our projects along, and going into 2021 I decided to make the most out of this opportunity to climb back up from rock bottom, and work on improving myself to contribute better on the job that I just got back.&lt;/p&gt;

&lt;p&gt;I started 2021 with a pretty simple goal: Make what used to be an insurmountable, monumental task for me right now into a lazy Sunday afternoon for me in the future. With the help of my online course backlogs I started (re-)learning everything from the ground up, contribute to my work using the things I learned, and then rinse and repeat, and maybe make a little bit more progress the next day. At the start of 2021, there were a lot of days where I'd consider it a massive win to even be able to open my code editor, and at best I would just watch a couple online course lectures without actually following along with the code. There's a certain value in those small actions however, and over the course of this year my progress steadily kept getting bigger and more consistent, and I've started to gain back the strength and confidence that I once had thanks to that small start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting #100DaysOfCode
&lt;/h2&gt;

&lt;p&gt;Once I felt a bit more comfortable with my workflow, I started taking on a tougher challenge, focusing on what's going to give me the best value for my time learning new things and contributing more to my work at the same time. To achieve this I started my &lt;a href="https://github.com/Insidiae/perpetual-testing-initiative"&gt;Perpetual Testing Initiative&lt;/a&gt;, a spin-off of sorts to &lt;a href="https://www.100daysofcode.com/"&gt;the #100DaysOfCode challenge&lt;/a&gt; that I came up with just to start with a more casual ruleset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I was tracking my progress not by time spent, but rather an arbitrary amount of progress that I feel is &lt;em&gt;"just right"&lt;/em&gt; for the day,&lt;/li&gt;
&lt;li&gt;Focusing less on the complete 100-day streak and more on the learning experience along the way (i.e. taking breaks as needed to preserve what little stamina I had 😛).&lt;/li&gt;
&lt;li&gt;Relying heavily on online courses to (re-)learn my skills and improve my work.&lt;/li&gt;
&lt;li&gt;Working in silence until the round is complete (See: &lt;a href="https://www.youtube.com/watch?v=EuSGUhhmYfk"&gt;I Triggered It Thirty-Five Minutes Ago&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also selected a set amount of online courses to work on for this first round, as a way to direct my focus rather than getting distracted by the shiny new stuff, and also to use the knowledge I gained from these online courses to improve the quality of my work. Here are the twelve courses I chose for this round:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7gHmgdmu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tu9zl48p35s6mjca4fjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7gHmgdmu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tu9zl48p35s6mjca4fjv.png" alt="Initial course progress" width="880" height="723"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've also marked each course as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BLUE&lt;/strong&gt; - Priority courses to complete (i.e. get 100% progress and complete the major course projects)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORANGE&lt;/strong&gt; - Optional courses, but it would still be nice if I can also complete them within these 100 days&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I dubbed this initial round &lt;code&gt;Round 0&lt;/code&gt; for a number of reasons: When I started this round I really wasn't sure if I was going to be able to complete the full 100 days, so my initial objective was to just do as many days as I can and then peace out when my stamina runs out and I did not see myself being able to continue further, and so I just wanted to see how well I can do on this round without making it fully &lt;em&gt;"official"&lt;/em&gt;. I also saw this round as kind of a new starting point - or in other words, staring from &lt;em&gt;zero&lt;/em&gt;. And hey, who doesn't like some good ol' 0-indexing puns?&lt;/p&gt;

&lt;p&gt;Throughout the first few weeks of this round, I'd already consider it a whole day's worth of progress to be able to complete just a few lecture videos. I also immediately broke my streak to remind myself to preserve my stamina and take a break whenever I start to feel like not coding anything. Taking breaks as needed also played a large part of preserving my motivation throughout this round, and I think it's even one of the main reasons I was able to do so much progress in this round at all! After taking a break for a couple weeks about halfway through the round, I started to find myself actually &lt;em&gt;wanting&lt;/em&gt; to write some more code and watch a couple more lecture videos. Towards the end of this round I'd say I've actually accomplished my main goals: I went from being barely able to muster up the strength to even open up my code editor to casually breezing through multiple sections of the online courses I'm taking without breaking a sweat - and not only was I able to complete the whole 100 days, I also fully completed most of the courses I picked for this round, along with a few more extra courses whose progress I wasn't even counting for this round!&lt;/p&gt;

&lt;p&gt;Here's my final progress in the courses I selected above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--64UKBciZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq9940zdemoe4uvpq1wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--64UKBciZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq9940zdemoe4uvpq1wl.png" alt="Final course progress" width="880" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Throughout the 100 (not necessarily consecutive) days of this round, I've managed to complete 10 out of the 12 courses I selected. I'd say that's some pretty good progress!&lt;/p&gt;

&lt;h3&gt;
  
  
  Highlights
&lt;/h3&gt;

&lt;p&gt;I've managed to surprise myself with how much progress I made this year. Here are some highlights I particularly liked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Insidiae/perpetual-testing-initiative/blob/main/Round%200/log.md#day-63-tuesday-november-2nd-2021"&gt;Completing all five of freeCodeCamp's Scientific Computing with Python projects in one day&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Completing 3/4 of the Pull Requests I needed for the &lt;a href="https://hacktoberfest.digitalocean.com/"&gt;Hacktoberfest challenge&lt;/a&gt; in one day, and adding more pull requests throughout the month of October&lt;/li&gt;
&lt;li&gt;Starting to deviate from my comfort zone of simply following along with the course lecture videos, culminating in remaking the final major project in one of the courses from good ol' Node/Express/EJS into &lt;a href="https://github.com/Insidiae/yelpcamp-mern"&gt;a full blown MERN stack project&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fun stats
&lt;/h3&gt;

&lt;p&gt;2021 ended up being a very productive year for me. Let's take a look at some fun stats.&lt;/p&gt;

&lt;p&gt;Here's a pretty neat visualization of my GitHub contributions in 2021, thanks to &lt;a href="https://wrapped.run/"&gt;GitHub Wrapped&lt;/a&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aETrWTBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hg6zwliy79lq6iz7eae0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aETrWTBC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hg6zwliy79lq6iz7eae0.png" alt="GitHub Wrapped 2021" width="880" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's also my &lt;a href="https://skyline.github.com/insidiae/2021"&gt;2021 GitHub Skyline&lt;/a&gt;, where my GitHub contributions are visualized into a 3D skyline.&lt;/p&gt;

&lt;p&gt;I also managed to keep up a fairly decent streak on &lt;a href="https://www.duolingo.com"&gt;Duolingo&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VbW-Pgaf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7od1qprr8nlihrykd2pn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VbW-Pgaf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7od1qprr8nlihrykd2pn.png" alt="Duolingo stats" width="880" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I dedicate this year to the many people I disappointed with my mistakes and failures. At this point I feel like it's already too late to fix my mistakes, but the least I can do is to move forward with a genuine conviction to never let other people down the way I did back then. Throughout this year, I made it my number one goal to keep improving myself, and maybe through a continuous effort and an honest motivation to do better, someday I can have the power to mend the broken connections and the bridges I burnt back then. And so moving forward this upcoming year, I'll keep building even bigger and better projects in the purpose of doing better than I did last time.&lt;/p&gt;

&lt;p&gt;While 2021 has been a really amazing year for me in terms of progress, both in doing #100DaysOfCode and lots of extra stuff I've also done outside the challenge as well, I can still see quite a few improvements to be done and incorporate as I move forward in 2022. I'm already cooking up some big plans for the next round of #100DaysOfCode, and it honestly feels exciting to look forward to the projects I'm planning to do in 2022. For now, I'm happy to report that I've accomplished everything I can for this year, both personally and at work, and I'll be taking a much-deserved break for the time being while I flesh out my plans for the upcoming year's round of #100DaysOfCode. Until then, stay tuned!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
