<?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: Halla Moore</title>
    <description>The latest articles on Forem by Halla Moore (@hallamoore).</description>
    <link>https://forem.com/hallamoore</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%2F55072%2F86cbce20-6f81-4bab-ab1f-973dcd7bd266.png</url>
      <title>Forem: Halla Moore</title>
      <link>https://forem.com/hallamoore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hallamoore"/>
    <language>en</language>
    <item>
      <title>Structuring a Complex React/Redux Project</title>
      <dc:creator>Halla Moore</dc:creator>
      <pubDate>Wed, 07 Mar 2018 17:49:16 +0000</pubDate>
      <link>https://forem.com/nylas/structuring-a-complex-reactredux-project-4mbg</link>
      <guid>https://forem.com/nylas/structuring-a-complex-reactredux-project-4mbg</guid>
      <description>&lt;p&gt;The Nylas engineering team recently updated the &lt;a href="https://dev.to/nylas/announcing-the-nylas-dashboard-20-1pg-temp-slug-6941808"&gt;Nylas Dashboard&lt;/a&gt;, giving everyone on our customer's teams -- from developers to product managers, sales engineers, customer success reps and finance teams -- the ability to access their Nylas API account. &lt;/p&gt;

&lt;p&gt;After our &lt;a href="https://dev.to/nylas/raising-the-limits-on-developer-speed-4dgl"&gt;blog post about increasing developer speed&lt;/a&gt; during the revamp of the Nylas Dashboard, we had some follow-up requests for a) the scaffold script we wrote, which is now available &lt;a href="https://gist.github.com/hallamoore/bf4e18e64cca1b9e45bf69901e56ee43"&gt;here&lt;/a&gt;, and b) the general structure of the project. &lt;/p&gt;

&lt;p&gt;Our dashboard front-end code is a React/Redux application, and the general structure looks something like this:&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="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;appConstants&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;DropdownMenu&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
      &lt;span class="nx"&gt;dropDownArrow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;png&lt;/span&gt;
      &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;stylesheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;containers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;higherOrderComponents&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;layouts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
      &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
      &lt;span class="nx"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="nx"&gt;applications&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="nx"&gt;rootReducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
    &lt;span class="nx"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
  &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;css&lt;/span&gt;
  &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
  &lt;span class="nx"&gt;registerServiceWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
  &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🙀 There’s a lot going on here, so I’ll briefly break down what each directory or file is for.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;appConstants/&lt;/code&gt; is simply where we kept any application-wide constants, like API keys for third party services. We originally named this &lt;code&gt;constants/&lt;/code&gt;, but it turned out that there was another constants node module elsewhere in the project that caused naming conflicts, so we renamed it to &lt;code&gt;appConstants/&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;We broke up our React components into multiple directories to try to keep things grouped in a more manageable manner. We initially only had a split between presentational components and containers. The important distinction between these is that presentational components are stateless while containers are not. You can learn more about the difference between presentational components and containers from &lt;a href="https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0"&gt;this article&lt;/a&gt;. However, as we continued to add more and more components, we needed more separation. The directories we ended up with are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;components/&lt;/code&gt; - the original directory for presentational components. Most of our presentational components still live here.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;containers/&lt;/code&gt; - the original directory for containers. (I bet you couldn’t have guessed that one 😜)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;higherOrderComponents/&lt;/code&gt; - &lt;a href="https://reactjs.org/docs/higher-order-components.html"&gt;Higher Order Components (HOCs)&lt;/a&gt; are a special type of container that are actually functions. These functions encapsulate reusable logic patterns and are used to wrap other components with that logic. For instance, one of our HOCs is a LazyLoaded component. This displays a loading indicator before the necessary data is loaded, and reports back to us if it takes too long. We pass any screens that need this loading behavior through the LazyLoaded HOC rather than having to re-implement the behavior within each one! 💥&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;layouts/&lt;/code&gt; - This is the only other directory that holds presentational components. These presentational components are specifically concerned with how an entire page in our application is laid out.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;screens/&lt;/code&gt; - Screens are containers that pull in all of the presentational components and sub-containers for a particular application view. All of our screens start with a layout component and add children from there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each component has its own subdirectory within one of those parent directories. The main file in each subdirectory is &lt;code&gt;index.js&lt;/code&gt;, which is where the general component definition goes. &lt;code&gt;index.test.js&lt;/code&gt; is the test file that we automatically add via our scaffolding script. We also keep any styling for the component in this subdirectory. This includes any images it needs and a separate &lt;code&gt;stylesheet.js&lt;/code&gt; file if the styles get too bulky to keep in &lt;code&gt;index.js&lt;/code&gt;. We used &lt;a href="https://github.com/Khan/aphrodite"&gt;Aphrodite&lt;/a&gt; to be able to write our styles in JavaScript, which helped us keep the styles localized to each component rather than buried in massive CSS files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/models&lt;/code&gt; is where we defined classes for each of our API objects. Each class defined a &lt;code&gt;toJSON()&lt;/code&gt; and a &lt;code&gt;fromJSON()&lt;/code&gt; method which allowed us to transform JSON responses into instances while we worked with them inside the application, and then back to JSON when we had to send the data back to our servers. The project also uses &lt;a href="https://flow.org/"&gt;Flow&lt;/a&gt; as a type checker, and transforming the JSON into more concrete data structures allowed us to properly type-annotate each field.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/modules&lt;/code&gt; is basically a directory for utility or helper code. We grouped closely-related code into their own files and ended up with modules like &lt;code&gt;errorReporter.js&lt;/code&gt; and &lt;code&gt;apiRequest.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;store/&lt;/code&gt; is for all of our Redux code. As I mentioned in my previous blog post, we separated our store into subdirectories for each of our models. Each of these subdirectories had the traditional Redux files of &lt;code&gt;actions.js&lt;/code&gt;, &lt;code&gt;reducers.js&lt;/code&gt;, and &lt;code&gt;selectors.js&lt;/code&gt;. We additionally had a &lt;code&gt;constants.js&lt;/code&gt; file for any constants relevant to that model store, and &lt;code&gt;endpoints.js&lt;/code&gt; for functions that interact with our back-end API. At the &lt;code&gt;store/&lt;/code&gt; root, we have files that import all of the functions from the corresponding subdirectory files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;actions.js&lt;/code&gt; imports from all of the sub &lt;code&gt;actions.js&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api.js&lt;/code&gt; imports from all of the sub &lt;code&gt;endpoints.js&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rootReducer.js&lt;/code&gt; combines all of the sub &lt;code&gt;reducers.js&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;selectors.js&lt;/code&gt; imports all of the sub &lt;code&gt;selectors.js&lt;/code&gt; files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also have &lt;code&gt;configureStore.js&lt;/code&gt; which does the initial setup of actually creating the store and potentially loading any previously saved state. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;index.css&lt;/code&gt; holds our over-arching CSS styles. Most of our styles are inside our component directories, but there are a few &lt;code&gt;body&lt;/code&gt; and &lt;code&gt;html&lt;/code&gt; level styles that live in this file instead.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;index.js&lt;/code&gt; simply renders our root React component.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;registerServiceWorker.js&lt;/code&gt; sets up service workers so that we can serve assets from a local cache to make our application run faster.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Routes.js&lt;/code&gt; connects each of our screen components to an application route. For example, this is where we register our &lt;code&gt;RegisterScreen&lt;/code&gt; to be loaded when the user visits the &lt;code&gt;/register&lt;/code&gt; route in our dashboard.&lt;/p&gt;

&lt;p&gt;Overall, we tried to structure our project such that all of the relevant code is nearby when we’re working on a specific part, while still maintaining a separation of concerns. Keeping smaller files grouped by model or component really helped improve the developer experience. We may continue to iterate on our structure in the future, but so far this has worked well for us! Let us know if you have any questions or if you do things differently at your company.&lt;/p&gt;




&lt;p&gt;This post was originally published on the &lt;a href="https://www.nylas.com/blog/structuring-a-complex-react-redux-project"&gt;Nylas Engineering Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Raising the Limits on Developer Speed</title>
      <dc:creator>Halla Moore</dc:creator>
      <pubDate>Wed, 24 Jan 2018 19:27:32 +0000</pubDate>
      <link>https://forem.com/nylas/raising-the-limits-on-developer-speed-4dgl</link>
      <guid>https://forem.com/nylas/raising-the-limits-on-developer-speed-4dgl</guid>
      <description>&lt;h3&gt;
  
  
  How we used React/Redux, Jest, and automation to rebuild our dashboard in only three months
&lt;/h3&gt;

&lt;p&gt;Up until five months ago, our &lt;a href="https://dashboard.nylas.com" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; was slow, limited, and (worst of all) written in Angular. We don’t have anything in particular against Angular itself, but nobody on our team had any significant experience with it. This meant that fixing even a tiny bug took a large amount of effort. We had big plans to add awesome features to our dashboard — organizations, multiple applications per user, queryable logs, and more! — but we weren’t convinced that building on top of our legacy code was the best use of our time. So we scrapped it.&lt;/p&gt;

&lt;p&gt;Our goal was to build the new dashboard in a way that would enable us to develop quickly and effectively. We knew we wanted to use React, to keep in line with our other in-house JavaScript projects, but the dashboard has a considerable amount of application state, so we decided to use Redux as well. We started by taking a bunch of pointers from Bumpers’ &lt;em&gt;&lt;a href="https://medium.com/bumpers/isnt-our-code-just-the-best-f028a78f33a9" rel="noopener noreferrer"&gt;Isn’t our code just the *BEST* 🙄&lt;/a&gt;&lt;/em&gt; article.&lt;/p&gt;

&lt;p&gt;Instead of having all of our store files directly at the &lt;code&gt;/store&lt;/code&gt; level, as is common in many Redux applications, we split the store into several subdirectories, each one with their own actions, reducers, and selectors files. Each of these subdirectories correspond to one of our models, e.g. Account, Organization, Application, etc. This made development much faster by grouping relevant code together. Now, when someone wants to make changes to the Account state, they only have to navigate to &lt;code&gt;/store/account&lt;/code&gt;to find that code, rather than having to &lt;code&gt;ctrl+f&lt;/code&gt; in massive files that bunch all of the code for different models together.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sidenote: Another point we took from the Bumpers article was the addition of an endpoints file in each of these store subdirectories. The API calls can be handled in this file and called in-turn by the actions file. This is a nice separation-of-concerns that makes it easy to switch out either the actions or the API interface without affecting the other, and provides a clean stub interface for testing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This separation made it extremely easy to modify stores, but unfortunately, adding new stores required a lot of prep work. For each new store, we had to create a new directory, add a bunch of files, and write the same initial skeleton code — all work that could be automated! We wrote a scaffolding script to do it for us and added it to our &lt;em&gt;package.json&lt;/em&gt; file. We were able to run this script with Yarn via &lt;code&gt;yarn scaffold &amp;lt;type&amp;gt; &amp;lt;name&amp;gt;&lt;/code&gt;. We added several other pieces of skeleton code to this script, so we could create quickly components and model definitions as well as stores. This made the process of adding new code super easy and fast. Most of the code only needed a few details to be fleshed out and then it was good to go. 👍&lt;/p&gt;

&lt;p&gt;Another thing that we did to increase our development speed was to use &lt;a href="https://facebook.github.io/jest/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; for testing. We believe testing is an important part of development, but writing tests can significantly slow down the development process. Jest’s visual output is fantastic (on par with pytest for Python), but the real kicker is its concept of snapshots.&lt;/p&gt;

&lt;p&gt;Using Jest’s snapshots is as simple as &lt;code&gt;expect(testData).toMatchSnapshot()&lt;/code&gt;. The first time this test is run, the user will be prompted to inspect &lt;code&gt;testData&lt;/code&gt; and confirm that it has the expected value. Jest then creates a snapshot file with the confirmed data value. On each subsequent test run, Jest will compare the current value of &lt;code&gt;testData&lt;/code&gt; to the value stored in the snapshot. If the values do not match, the console will show the differences between the two values and ask if the snapshot should be updated.&lt;/p&gt;

&lt;p&gt;This is much faster than having to 1) figure out what the value of data should be when initially writing the test (particularly if it has a complex structure), and 2) having to go change a bunch of hard-coded test values when something does legitimately change (which happens a lot in early development stages). We were able to add skeleton tests to our scaffold script, so each React component automatically got a test like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @flow&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-test-renderer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;NewComponent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders as expected&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="o"&gt;=&amp;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;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;NewComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;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;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&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;This helped ensure that all of our components were tested. If it was a simple component, the skeleton test was all it needed. If it was a more complex component, the test would fail and prompt the developer to update the test to be more accurate. This effectively eliminated the case where developers forget to write a test for a component, and not having to do any extra work to test the simpler components was a huge plus.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sidenote: Prettier, an auto-formatter that we talked about in our &lt;a href="https://dev.to/nylas/how-do-we-even-js-the-components-of-nylass-javascript-stack-6h"&gt;tooling blog post&lt;/a&gt;, also did wonders for our development speed. You don’t realize how much time you spend on spacing until you no longer have to do it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As these changes were integrated with our workflow, we were able to develop faster and faster. We completed the entire dashboard project (along with the associated backend changes necessary to support the new features we wanted to implement) in an astounding 12 weeks. The key lesson we learned from this experience was that investing the initial time into building a strong developing foundation is well worth the effort! For this project, building that strong foundation involved grouping code together in a functional way and automating as many patterns as we could. Going forward, we’ll be sure to look out for ways that we can do the same in our other projects!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.nylas.com%2Fhs-fs%2Fhubfs%2Fblog%2520images%2Fdashboard.png%3Ft%3D1516818502866%26width%3D1200%26name%3Ddashboard.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.nylas.com%2Fhs-fs%2Fhubfs%2Fblog%2520images%2Fdashboard.png%3Ft%3D1516818502866%26width%3D1200%26name%3Ddashboard.png" alt="Dashboard Commits" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;We had a rising trend in the number of commits to the dashboard project, until it neared completion. This was with a team of 4-5 engineers, depending on the week.&lt;/em&gt; &lt;/p&gt;




&lt;p&gt;This post was originally published on the &lt;a href="https://www.nylas.com/blog/raising-the-limits-on-developer-speed" rel="noopener noreferrer"&gt;Nylas Engineering Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>react</category>
      <category>redux</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
