<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pavneet Singh Saund</title>
    <description>The latest articles on DEV Community by Pavneet Singh Saund (@pavsaund).</description>
    <link>https://dev.to/pavsaund</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%2F821%2Fc33377f0-55df-4380-9d4e-be8f6259b2df.JPG</url>
      <title>DEV Community: Pavneet Singh Saund</title>
      <link>https://dev.to/pavsaund</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pavsaund"/>
    <language>en</language>
    <item>
      <title>Build dynamic breadcrumb routes and child routes with matchPath in React Router v6</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Sun, 27 Feb 2022 00:19:36 +0000</pubDate>
      <link>https://dev.to/pavsaund/build-dynamic-breadcrumb-routes-and-child-routes-with-mathpath-in-react-router-v6-2jcf</link>
      <guid>https://dev.to/pavsaund/build-dynamic-breadcrumb-routes-and-child-routes-with-mathpath-in-react-router-v6-2jcf</guid>
      <description>&lt;p&gt;When faced with a challenge of implementing breadcrumbs for a business critical application recently I went down a rabbit hole of trying to understand the semantics of react-router and finding a good way of building a dynamic breadcrumb component that didn't break every time a route was added or changed. Let alone need to implement a custom route for every new page. In this post I go into what I ended up with as a routing model that supports dynamic breadcrumbs&lt;/p&gt;

&lt;h2&gt;
  
  
  The requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Maintain a single routing model (or composition of models) as the source of truth for the app&lt;/li&gt;
&lt;li&gt;Not have to manually maintain breadcrumbs for different pages&lt;/li&gt;
&lt;li&gt;Support child routes&lt;/li&gt;
&lt;li&gt;Use the same model to generate bread crumbs for the currently active page.&lt;/li&gt;
&lt;li&gt;Be able to show dynamic breadcrumb titles based on parameters.&lt;/li&gt;
&lt;li&gt;Bonus: Support generating Navlinks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TLDR;
&lt;/h2&gt;

&lt;p&gt;You can check out this github repository to see my trail and error: &lt;a href="https://github.com/pavsaund/react-routing-model/"&gt;https://github.com/pavsaund/react-routing-model/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can view the code in action on stackblitz: &lt;a href="https://stackblitz.com/github/pavsaund/react-routing-model/"&gt;https://stackblitz.com/github/pavsaund/react-routing-model/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Digging into details
&lt;/h2&gt;

&lt;p&gt;It took me a while to really grok the routing model with nested routes in React Router v6. I put this down to coming from very basic use of v5 and mostly using other frameworks. I found this article on nested routes most useful &lt;a href="https://ui.dev/react-router-nested-routes"&gt;https://ui.dev/react-router-nested-routes&lt;/a&gt;. Based on this I realized I wanted to define my routes as a single model, where possible and to use the &lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt; component to render the routes for a given path. &lt;a href="https://reactrouter.com/docs/en/v6/getting-started/concepts#outlets"&gt;More info on the usage of &lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's start with what the routes look like from a React Router perspective, and what you'll likely see in your regular react app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;home&lt;/span&gt;&lt;span class="dl"&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/away&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;away&lt;/span&gt;&lt;span class="dl"&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;withOutlet&lt;/span&gt; &lt;span class="o"&gt;/&amp;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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="o"&gt;=&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub-zero&lt;/span&gt;&lt;span class="dl"&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Route&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Routes&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I started with the model I wanted, which was built separately from React Router's. The idea is that a simple model can easily be parsed and mapped into something React Router could understand. I didn't want to implement ALL the features of React Router, but just enough for my use case. This worked fine for the initial proof of concept. Then after experimenting a bit and also understanding more of the route model that React Router expected I actually ended up augmenting the &lt;code&gt;RouteObject&lt;/code&gt; model with custom properties. This is the end result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;RouteObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;nav&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&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;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Home&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;home&lt;/span&gt;&lt;span class="dl"&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;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Away&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/away&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;away&lt;/span&gt;&lt;span class="dl"&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;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;withOutlet&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;children&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sub-Zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sub-zero&lt;/span&gt;&lt;span class="dl"&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;},&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;&amp;lt;Page /&amp;gt;&lt;/code&gt;-component is a simple helper component to render a page with a title, and the &lt;code&gt;withOutlet&lt;/code&gt; prop is an indication to render a &lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt; component for the child routes to render. &lt;a href="https://github.com/pavsaund/react-routing-model/blob/7bad0d2a1ebbb2e1bb6ca047746414efab73c2b4/src/Layout/Page.tsx"&gt;Implementation here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the breadcrumbs
&lt;/h2&gt;

&lt;p&gt;Now, for the fun part - actually understanding how to get the active path from React Router. This is where grokking how React Router builds its paths were important. I realised after hitting my head on the wall that there is no central place where all the routes are stored that is exposed through public API. (&lt;a href="https://github.com/remix-run/react-router/blob/8601f27e74021c3d0da13cfa036f38c0cd7af9b3/packages/react-router-dom/index.tsx#L119"&gt;There is an exposed &lt;code&gt;UNSAFE_RouteContext&lt;/code&gt; if you want to live on the edge&lt;/a&gt;). My current understanding is that React Router and nested routes seem to work by each level of the router owning its own routes and the next level to take over. Meaning that a parent route doesn't actually know anything about its children, and a child only knows its own path pattern based on the resolved parent's route. Now to build the breadcrumb.&lt;/p&gt;

&lt;h3&gt;
  
  
  Matching the top-level crumb with &lt;code&gt;matchPath&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Using the &lt;a href="https://reactrouter.com/docs/en/v6/api#matchpath"&gt;&lt;code&gt;matchPath&lt;/code&gt; utility&lt;/a&gt; the React Router will match the given location against the path provided. It also returns the resolved pathname, and any params it resolves. By specifying &lt;code&gt;end = false;&lt;/code&gt; on the &lt;code&gt;PathPattern&lt;/code&gt; option will allow a partial match on the supplied location. This allows us to know if a given pattern is part of the current location, and should be included in the breadcrumb or not.&lt;/p&gt;

&lt;p&gt;So, let's resolve the top-level paths aginst to our second route &lt;code&gt;/sub/zero&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//for '/sub/zero'&lt;/span&gt;
&lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns match&lt;/span&gt;
&lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/away&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns null&lt;/span&gt;
&lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns match&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, so this means that both the &lt;code&gt;Home&lt;/code&gt; and &lt;code&gt;Sub&lt;/code&gt; paths match and can be added to our breadcrumb. Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;locationPathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&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;crumbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/** simplified matches
 * [
 *  {pattern: '/'},
 *  {pattern: '/sub'}
 * ]
 * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Matching children
&lt;/h3&gt;

&lt;p&gt;So, now how can we match the &lt;code&gt;zero&lt;/code&gt; child route? Let's manually match again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//for '/sub/zero'&lt;/span&gt;
&lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns null&lt;/span&gt;
&lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returns match&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK! Now we're getting somewhere. It's not enough to match against the path pattern itself, you also need to match with the parent pathname. So let's add the parent path into the mix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;joinPaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="nx"&gt;locationPathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;parentPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&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;crumbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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;pathPatternWithParent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;joinPaths&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;parentPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pathPatternWithParent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&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;nestedMatches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;locationPathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;pathPatternWithParent&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;nestedMatches&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="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cm"&gt;/** simplified matches
 * [
 *  {pattern: '/'},
 *  {pattern: '/sub'}
 *  {pattern: '/sub/zero'}
 * ]
 * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a bit more going on here so let's break down what's happening.&lt;br&gt;
&lt;code&gt;parentPath&lt;/code&gt; has been added as a parameter with a default value of &lt;code&gt;''&lt;/code&gt;. Then using the &lt;code&gt;joinPaths&lt;/code&gt; function the parent and definition path are joined, and any redundant &lt;code&gt;//&lt;/code&gt; are replaced with a single slash.&lt;/p&gt;

&lt;p&gt;Next, if there are children on the matched route, then recursively call the &lt;code&gt;matchRouteDefinitions&lt;/code&gt; with the child routes. This time we pass in the &lt;code&gt;pathPatternWithParent&lt;/code&gt; as the &lt;code&gt;parentPath&lt;/code&gt; parameter, which then allows the child router paths to match.&lt;/p&gt;

&lt;p&gt;Now, this is the happy path (pun intended 😏) implementation. There are some edge cases you may or may not want to support.&lt;/p&gt;
&lt;h3&gt;
  
  
  Edge case 1: Don't match breadcrumb for &lt;code&gt;/&lt;/code&gt; - Home route
&lt;/h3&gt;

&lt;p&gt;For my use case, I didn't want &lt;code&gt;Home&lt;/code&gt; to show up, so I added another path check before deciding to add the path match&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="c1"&gt;//...&lt;/span&gt;
   &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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="c1"&gt;//...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&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;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/** simplified matches
   * [
   *  {pattern: '/sub'}
   *  {pattern: '/sub/zero'}
   * ]
   * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edge case 2: Don't match a no-match/catch-all route
&lt;/h3&gt;

&lt;p&gt;It's common to add a NoMatch route to serve a user with a 404 page of some kind. The problem is that this route will match anything - which is kind of the point.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;404&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;404 Not Found&lt;/span&gt;&lt;span class="dl"&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;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/** simplified matches
   * [
   *  {pattern: '/'},
   *  {pattern: '/sub'},
   *  {pattern: '/sub/zero'},
   *  {pattern: '*'},
   * ]
   * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we can add the &lt;code&gt;*&lt;/code&gt; pattern to the ignore list as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skipPaths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&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="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
 &lt;span class="c1"&gt;//...&lt;/span&gt;
   &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&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="c1"&gt;//...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignoredPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/sub/zero&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/** simplified matches
   * [
   *  {pattern: '/sub'}
   *  {pattern: '/sub/zero'}
   * ]
   * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Edge case 3 - Child route with ''-path with redirect matches parent route
&lt;/h3&gt;

&lt;p&gt;For a use case where a child route has an empty path then the resolved from &lt;code&gt;matchPath&lt;/code&gt; ends up being the same. This may actually be what React Router refers to as an &lt;a href="https://reactrouter.com/docs/en/v6/getting-started/concepts#index-route"&gt;&lt;code&gt;Index&lt;/code&gt; path&lt;/a&gt; - but I haven't explored that aspect enough yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Another&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/another&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Another&lt;/span&gt;&lt;span class="dl"&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="na"&gt;children&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="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Another-index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Empty&lt;/span&gt;&lt;span class="dl"&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;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Another-other&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;other&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&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;Page&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Other&lt;/span&gt;&lt;span class="dl"&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;]&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/another/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/** simplified matches
   * [
   *  {pattern: '/'},
   *  {pattern: '/another'},
   *  {pattern: '/another'},
   * ]
   * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you need a guard or check in place before adding the match.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isNotSameAsPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;previousMatchedPathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;previousMatchedPathname&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;isMoreSpecificThanPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;toPathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;previousMatchedPathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;previousMatches&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;toPathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;previousMatchedPathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;canBeAddedToMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;isNotSameAsPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="nx"&gt;isMoreSpecificThanPreviousMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&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;//...&lt;/span&gt;
   &lt;span class="nx"&gt;definitions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;definition&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="c1"&gt;//...&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;match&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ignoredPaths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;canBeAddedToMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;match&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;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//...&lt;/span&gt;
        &lt;span class="nx"&gt;nestedMatches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;nestedMatch&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;canBeAddedToMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nestedMatch&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;crumbs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nestedMatch&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/another/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="cm"&gt;/** simplified matches
   * [
   *  {pattern: '/'},
   *  {pattern: '/another'},
   * ]
   * /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Rendering routes
&lt;/h2&gt;

&lt;p&gt;So, now that we have all our routes defined in a nice object, wouldn't it be good to render them using that same object? As I mentioned in the introduction, this caused me some pain until I realised I could extend the &lt;code&gt;RouteObject&lt;/code&gt; that React Router already exposes. Then it's possible to use the &lt;code&gt;useRoutes&lt;/code&gt; hook to do the rendering for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="p"&gt;}&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;./routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&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;routesToRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;My&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;routesToRender&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;Then in the page that has child routes, including the &lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt; component. Remember to do this for each component that has child routes. React Router will then figure out which child routes to render there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Outlet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Sub&lt;/span&gt;&lt;span class="p"&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;routesToRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Sub&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Outlet&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;h2&gt;
  
  
  Rendering the breadcrumbs
&lt;/h2&gt;

&lt;p&gt;Now that we have all the moving parts in place, we can put it all together in the &lt;code&gt;Breadcrumbs&lt;/code&gt; component. In the below exampled the &lt;code&gt;matchRouteDefinitions&lt;/code&gt; function now returns an &lt;code&gt;ActiveRoutePath&lt;/code&gt; which is a structure that includes both the &lt;code&gt;match&lt;/code&gt; and the &lt;code&gt;RoutePathDefinition&lt;/code&gt; for convenience.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ActiveRoutePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PathMatch&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="na"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useActiveRoutePaths&lt;/span&gt;&lt;span class="p"&gt;(&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;RoutePathDefinition&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;ActiveRoutePath&lt;/span&gt;&lt;span class="p"&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;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLocation&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;activeRoutePaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActiveRoutePath&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;matchRouteDefinitions&lt;/span&gt;&lt;span class="p"&gt;(&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;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;activeRoutePaths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Breadcrumbs&lt;/span&gt;&lt;span class="p"&gt;({&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;BreadcrumbsProps&lt;/span&gt;&lt;span class="p"&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;activeRoutePaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActiveRoutePath&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useActiveRoutePaths&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeRoutePaths&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;active&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;length&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;index&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="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&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; &amp;gt; &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;index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&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="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&lt;/span&gt;&lt;span class="err"&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="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, in our &lt;code&gt;App.tsx&lt;/code&gt; we can include the breadcrumbs path and it will render breadcrumbs automatically based on the page you are visiting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;App&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;routesToRender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRoutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&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;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Breadcrumbs&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;My&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;routesToRender&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, &lt;code&gt;matchPath&lt;/code&gt; can be used to manually match a path pattern against the current url to build breadcrumbs for the routes along the path. As a bonus, by extending the &lt;code&gt;RouteObject&lt;/code&gt; type exposed from React Router 6, you can add capabilities specific to your application's needs.&lt;/p&gt;

&lt;p&gt;There are two requirements I haven't dug into yet in this post. Stay tuned for the follow-up posts that will cover these cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be able to show dynamic breadcrumb titles based on parameters.&lt;/li&gt;
&lt;li&gt;Bonus: Support generating Navlinks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you enjoyed this post. Let me know if it's been useful to you, or if you have feedback.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>react</category>
      <category>reactrouter</category>
    </item>
    <item>
      <title>Highlights from the Aurelia vNext 2019 fall update</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Sat, 02 Nov 2019 21:09:31 +0000</pubDate>
      <link>https://dev.to/pavsaund/highlights-from-the-aurelia-vnext-2019-fall-update-48pe</link>
      <guid>https://dev.to/pavsaund/highlights-from-the-aurelia-vnext-2019-fall-update-48pe</guid>
      <description>&lt;p&gt;&lt;a href="https://aurelia.io/blog/2019/10/31/aurelia-vnext-2019-fall-update/"&gt;There was a recent blog post with the status of Aurelia vNext&lt;/a&gt;. For those of you that don't know, Aurelia is a front-end framework with a focus on standards, extensibility, ease of use and performance. It's been a while since a new major release, so vNext is a pretty big deal.&lt;/p&gt;

&lt;p&gt;These are some highlights of what I found pretty cool in the latest update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official name: &lt;strong&gt;Aurelia 2&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/aurelia/vscode-extension/pull/104"&gt;VSCode integration&lt;/a&gt; with direct linking between bindables, observables, views, and custom attributes to their backing code representation&lt;/li&gt;
&lt;li&gt;VanillaJS-like performance with JIT (Just in time) optimisations, and  new AOT (Ahead of Time) optimisations &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aurelia.io/blog/2019/10/31/aurelia-vnext-2019-fall-update/#extensibility"&gt;Extensibility&lt;/a&gt; that allows you to emulate the syntax of other frameworks, like Angular / Vue etc&lt;/li&gt;
&lt;li&gt;A continuous focus on &lt;a href="https://aurelia.io/blog/2019/10/31/aurelia-vnext-2019-fall-update/#web-standards"&gt;Web Standards&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Developer Experience has received som pretty considerable features, here are the ones I'm excited about

&lt;ul&gt;
&lt;li&gt;More lifecycle hooks, and they are now synchronous. (no more queueMicroTask!)&lt;/li&gt;
&lt;li&gt;New Router 🙌&lt;/li&gt;
&lt;li&gt;Functional API's&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Multiple Integration scenarios that allow nesting of frameworks, and connecting other libraries directly in the underlying pipeline and more&lt;/li&gt;
&lt;li&gt;Extensive Test Tooling support, helpers and libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The team is focused on keeping the migration path straight forward, though they have mentioned there'll be a few breaking changes. &lt;/p&gt;

&lt;p&gt;A lot of these improvements are raising the bar so high that we're bound to see more developers discover the joys of using Aurelia, as well as making that transition a lot easier for them with extensibility points.&lt;/p&gt;

&lt;p&gt;I'm pretty excited about the future of Aurelia 2, but doubt I'll be getting my hands dirty just yet. Looking forward to a preview/release candidate before I start testing it out, and more of the WIP features are in place.&lt;/p&gt;

</description>
      <category>aurelia</category>
      <category>frontend</category>
      <category>framework</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Adding a /now page</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Thu, 03 Oct 2019 18:50:37 +0000</pubDate>
      <link>https://dev.to/pavsaund/adding-a-now-page-4g32</link>
      <guid>https://dev.to/pavsaund/adding-a-now-page-4g32</guid>
      <description>&lt;p&gt;TL;DR: I’ve written and published a &lt;a href="https://pavsaund.com/now"&gt;/now page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more of the back story and understanding what it is, read on.&lt;/p&gt;

&lt;p&gt;I can’t remember when I first stumbled over Derek Sivers. It could have been one of his posts on &lt;a href="https://sivers.org/trust"&gt;giving away all his money&lt;/a&gt;, or perhaps his &lt;a href="https://www.ted.com/talks/derek_sivers_how_to_start_a_movement"&gt;TED talk&lt;/a&gt; on &lt;a href="https://sivers.org/ff"&gt;leadership lessons from a dancing guy&lt;/a&gt;. Regardless, at one point in time I remember reading about &lt;a href="https://sivers.org/nowff"&gt;the concept of a now page&lt;/a&gt;. I found it intriguing, but never really got around to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Now Page?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The concept is quite straight forward. It’s not an “about page”, nor is it a “contact page”. It’s a page describing what’s going on in your life right now.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of what you’d tell a friend you hadn’t seen in a year.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;But why even have a Now page?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This sums it up well:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s useful for the same reason an “about” page is useful on your site: because people on your site want to know more about you.&lt;/p&gt;

&lt;p&gt;Besides answering the common question, “What are you up to these days?”, those who have a now page say it’s a good reminder of their priorities. By publicly showing what you are focused on now, it helps you say no to other requests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The time is Now
&lt;/h3&gt;

&lt;p&gt;For some reason, the story of the first follower has stuck with me. It’s powerful when another person echoes your voice, or if you choose to echo another’s. It seems the effects of being that first follower can have long-tail impact. I realised while re-reading Derek’s original now-post that his first follower was &lt;a href="https://practicingdeveloper.com/now/"&gt;Gregory Brown&lt;/a&gt;, a person who &lt;a href="https://codingwithempathy.com/2016/12/27/reflecting-on-2016/"&gt;has been influential&lt;/a&gt; on my journey.&lt;/p&gt;

&lt;p&gt;It’s taken me a few years, but the time has finally come to put up my &lt;a href="https://pavsaund.com/now"&gt;Now-page&lt;/a&gt;. Perhaps a little too much overlap to an about page — but I suppose it will evolve.&lt;/p&gt;

&lt;p&gt;To get more info about Now-pages, check out: &lt;a href="https://nownownow.com/about"&gt;nownownow.com/about&lt;/a&gt;. Also, check out &lt;a href="https://nownownow.com/p/00tQ"&gt;my profile on nownownow.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://pavsaund.com/post/2019-10-03-adding-a-now-page/"&gt;&lt;em&gt;https://pavsaund.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on October 3, 2019.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>now</category>
      <category>development</category>
      <category>personalbranding</category>
    </item>
    <item>
      <title>Does Aurelia Support React-like Hooks?</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Tue, 01 Oct 2019 20:58:11 +0000</pubDate>
      <link>https://dev.to/pavsaund/does-aurelia-support-react-like-hooks-55mn</link>
      <guid>https://dev.to/pavsaund/does-aurelia-support-react-like-hooks-55mn</guid>
      <description>&lt;p&gt;There was recently a post on the Aurelia Discourse that caught my attention asking how react-like hooks would work when using Aureliajs. The &lt;a href="https://discourse.aurelia.io/t/how-we-react-hooks/2955/2?u=pavsaund"&gt;response from Aurelia’s creator&lt;/a&gt; underlined some of the reasons why I trust Aurelia to build JavaScript applications with Aurelia.&lt;/p&gt;

&lt;p&gt;Rob raised three aspects that Aurelia had that alleviated the need for “hooks”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With Aurelia, we don’t need hooks because we have three very powerful things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Dependency Injection&lt;/li&gt;
&lt;li&gt;Metaprogramming&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;He continues in his post to describe how Aurelia doesn’t try to re-invent the wheel but instead use time-tested OOP-practices that cater to Separation of Concerns.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;On Observability:&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;With Aurelia, we can observe normal objects/class properties. So, you can leverage the last 40ish years of OOP techniques and battle-tested approaches to building software. Also, the general observer pattern has been around for a very long time and has scaled to some of the most complex apps today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The interesting aspect here is that he explains how the patterns of other frameworks (React / Vue) leverage different techniques, and tools to compensate for their lack of support for full observability. With Vue coming in close to Aurelia, with some edge-cases that are uncovered.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;On Dependency Injection:&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;On the other hand, Aurelia has a very powerful DI framework. This lets you decompose any problem into small pieces that work together to tackle something complex. Need to make something reusblabe? Just factor it out into a new class and inject it wherever you need. That’s a basic form of composition that works very well, with decades of history behind it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;On Metaprogramming:&lt;/strong&gt;
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;None of the frameworks have metaprogramming capabilities like Aurelia. In Aurelia’s case, you can apply a decorator to a class, and the framework will use your declaration to “write” code for you, so you don’t have to. We take this further with conventions. So, you can write vanilla js, following a simple pattern, and Aurelia will write code for you to make things into custom elements, etc…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Some reflections&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Rob ends the piece by encouraging people to keep up to date on trends &amp;amp; techniques, but not to forget the years of learnings that have gone into existing techniques that work.&lt;/p&gt;

&lt;p&gt;I also think it’s important to recognize that there are different kinds of applications where features from React or Vue make more sense to use. Either because of the features those frameworks/libraries have, or because of the community support they have with plugins, libraries and helpers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on the&lt;/em&gt; &lt;a href="https://community.dolittle.com/t/does-aurelia-support-react-hooks/33?u=pavneet"&gt;&lt;em&gt;Dolittle Community Forum&lt;/em&gt;&lt;/a&gt; &lt;em&gt;&amp;amp; published on&lt;/em&gt; &lt;a href="https://pavsaund.com/post/2019-10-01-does-aurelia-support-react-hooks/"&gt;&lt;em&gt;https://pavsaund.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on October 1, 2019.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>aureliajs</category>
      <category>programming</category>
    </item>
    <item>
      <title>Officially backing Aurelia Front-End Framework</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Tue, 16 Apr 2019 21:53:55 +0000</pubDate>
      <link>https://dev.to/dolittle/officially-backing-aurelia-front-end-framework-2bjo</link>
      <guid>https://dev.to/dolittle/officially-backing-aurelia-front-end-framework-2bjo</guid>
      <description>

&lt;h3&gt;
  
  
  Officially backing Aurelia Front-End JavaScript Framework
&lt;/h3&gt;

&lt;p&gt;After discussing our strategy around front-end JavaScript frameworks at Dolittle, we decided to make our framework of choice official by &lt;a href="https://opencollective.com/dolittle?referral=39202"&gt;becoming a backer&lt;/a&gt; of the open source front-end framework &lt;a href="https://aurelia.io"&gt;Aurelia&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cdn-images-1.medium.com/max/203/1*RRRmPnMSIrMgBxyE2g6Kdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://cdn-images-1.medium.com/max/203/1*RRRmPnMSIrMgBxyE2g6Kdg.png" alt=""&gt;&lt;/a&gt;Open Collective backing badge from &lt;a href="https://opencollective.com/dolittle?referral=39202"&gt;Dolittle’s official backer page&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why donate to Open Source?
&lt;/h3&gt;

&lt;p&gt;At Dolittle, we believe in developing our platform in the open, and part of that is leaning on the work of other open source projects. We try to find ways to contribute back to open source and becoming an official backer is something we felt strongly about when it came to Aurelia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Aurelia?
&lt;/h3&gt;

&lt;p&gt;We’ve been using Aurelia as the defacto frontend JavaScript library for building our products, and the default framework for our open-source extensions for a while now.&lt;/p&gt;

&lt;p&gt;It’s not the hottest framework out there, nor the framework that has the most likes on GitHub. What it is though is a framework that aligns very well with our development principles for building typical Line-of-Business applications.&lt;/p&gt;

&lt;p&gt;It is Built on Open Web Standards, Open Source, Inspired by MVVM, Convention over Configuration, Fully Extensible and Separation of Concerns, &lt;a href="https://aurelia.io/docs/overview/what-is-aurelia#what-is-aurelia"&gt;to name a few&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s also gaining momentum with a committed and active core team who are working towards a &lt;a href="https://aurelia.io/blog/2018/08/05/aurelia-vnext"&gt;vNext release&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  In conclusion
&lt;/h3&gt;

&lt;p&gt;We want to thank the Aurelia team and open source contributors for their countless hours of work and hope our contribution helps them reach their goals. As their work is helping us reach ours.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;&lt;div class="ltag__twitter-tweet__main"&gt;
&lt;div class="ltag__twitter-tweet__header"&gt;
&lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ylCbr92d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/546483011/Rob1_normal.jpg"&gt;&lt;div class="ltag__twitter-tweet__full-name"&gt;Rob Eisenberg&lt;/div&gt;
&lt;div class="ltag__twitter-tweet__username"&gt;@eisenbergeffect&lt;/div&gt;
&lt;div class="ltag__twitter-tweet__twitter-logo"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kX-SksTr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-eb8b335b75231c6443385ac04fdfcaed8ca5423c3990e89dc0178a4090ac1908.svg"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="ltag__twitter-tweet__body"&gt;Big thanks to &lt;a href="https://twitter.com/Dolittle"&gt;@Dolittle&lt;/a&gt; for their donation to &lt;a href="https://twitter.com/AureliaEffect"&gt;@AureliaEffect&lt;/a&gt; &lt;a href="https://t.co/sSy4hc276h"&gt;opencollective.com/aurelia&lt;/a&gt; 🎉😊&lt;/div&gt;
&lt;div class="ltag__twitter-tweet__date"&gt;13:57 PM - 16 Apr 2019&lt;/div&gt;
&lt;div class="ltag__twitter-tweet__actions"&gt;
&lt;a href="https://twitter.com/intent/tweet?in_reply_to=1118151391418040322" class="ltag__twitter-tweet__actions__button"&gt;&lt;img alt="Twitter reply action" src="/assets/twitter-reply-action.svg"&gt;&lt;/a&gt;&lt;a href="https://twitter.com/intent/retweet?tweet_id=1118151391418040322" class="ltag__twitter-tweet__actions__button"&gt;&lt;img alt="Twitter retweet action" src="/assets/twitter-retweet-action.svg"&gt;&lt;/a&gt;2&lt;a href="https://twitter.com/intent/like?tweet_id=1118151391418040322" class="ltag__twitter-tweet__actions__button"&gt;&lt;img alt="Twitter like action" src="/assets/twitter-like-action.svg"&gt;&lt;/a&gt;17&lt;/div&gt;
&lt;/div&gt;&lt;/blockquote&gt;

&lt;p&gt;We also want to take the opportunity to bring focus to this great framework and its &lt;a href="https://discourse.aurelia.io"&gt;helpful community&lt;/a&gt;. Do check out Aurelia, if you haven’t done so already.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;A note on other frameworks…&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We want to make it very clear that our backing of Aurelia doesn’t mean you can’t use other front-end frameworks with Dolittle. We’re happy to say that you’re free to select whichever front-end framework you prefer. We have plans to add official support for more in the future.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Clap 👏 or follow to read more articles on Aurelia, and the open source application platform and company,&lt;/em&gt; &lt;a href="http://dolittle.com"&gt;&lt;em&gt;Dolittle&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally posted on the &lt;a href="https://medium.com/dolittle/officially-backing-aurelia-front-end-framework-ad6e21827774"&gt;Dolittle blog&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;





</description>
      <category>aurelia</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>2018 in review</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Mon, 14 Jan 2019 22:23:53 +0000</pubDate>
      <link>https://dev.to/pavsaund/2018-in-review-1g3j</link>
      <guid>https://dev.to/pavsaund/2018-in-review-1g3j</guid>
      <description>

&lt;p&gt;&lt;a href="https://cdn-images-1.medium.com/max/1024/1*E-dGdo6yu16Y2gvx0bHRaA.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://cdn-images-1.medium.com/max/1024/1*E-dGdo6yu16Y2gvx0bHRaA.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As is the tradition I want to spend a few minutes reflecting on the year 2018. I find that taking time to reflect gives me a perspective of where I am on my journey. Reflecting also helps give closure and allows me to direct my thoughts and efforts towards what I want to accomplish in the future.&lt;/p&gt;

&lt;p&gt;2018 has been one of the most exciting years from a professional perspective. From a personal growth perspective, 2018 has been both rewarding and frustrating. How can this be, you may ask (or not)? I’m asking at least and will be exploring that in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Putting things into perspective
&lt;/h3&gt;

&lt;p&gt;Having some perspective on where you are in life brings context. It allows you to understand where you need to focus your efforts and what you can expect from the outcomes. Without perspective, expectations run amok, and this has been a theme of mine for the last year.&lt;/p&gt;

&lt;p&gt;Let’s add some perspective by looking at the themes of the past few years:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codingwithempathy.com/2016/04/12/my-personal-burnout-lessons-learned/"&gt;2015: The year I hit my first real burnout. A low point in life that has turned out to be an eye-opening experience. I also became a dad for the 3rd time.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codingwithempathy.com/2016/12/27/reflecting-on-2016/"&gt;2016: The rebound year and discovering I had more to offer. My most active blog year, podcast appearance and a conference talk.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codingwithempathy.com/2017/12/30/coding-with-empathy-in-2017/"&gt;2017: Exploring ideas, video, and vulnerability. Putting myself out there on all fronts, blog, vlog, stoicism, and several conference talks.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;2018: Change, Challenges, Struggle, Failure, Growth. &lt;strong&gt;Let’s dig in!&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Change, Challenges, and Struggle
&lt;/h3&gt;

&lt;p&gt;This year brought around a significant change — a shift in careers. I transitioned from a Web Developer / Team Lead with a path towards Agile Coach / Management / Leadership type of roles at a larger company to becoming a founding employee at the startup, &lt;a href="https://dolittle.com/"&gt;Dolittle&lt;/a&gt; (more on this some other time).&lt;/p&gt;

&lt;p&gt;The role I took, and currently have is User Experience Lead / Web Developer, and as with any (small) company; titles mean nothing. User Experience is a new field for me to dive in to, practice and build skills in. Even though I’ve been a developer for many years, building applications in modern JavaScript has been an exciting challenge.&lt;/p&gt;

&lt;p&gt;Days have been filled with more frontend and JavaScript work than any before, both for our products and client projects as well as all the aspects of building a great culture and the fundaments of a company that will last for years to come.&lt;/p&gt;

&lt;h3&gt;
  
  
  Failure
&lt;/h3&gt;

&lt;p&gt;Working in any startup is hectic, and that’s also what I experienced, even though we limited ourselves to regular workdays, the sheer number of balls we needed to juggle was overwhelming at times. The transition has been exciting, invigorating and also painful. On one side I’ve wanted to explore and establish what UX is at Dolittle, and on the other, coding and working with clients to bring in some income naturally took precedence. All of the while fumbling trying to get on board with modern JavaScript Web Development. This lead to a feeling of not feeling adequate or competent in any of the work I was doing.&lt;/p&gt;

&lt;p&gt;Another consequence of feeling like all my energy was going towards not accomplishing things were the negative thoughts and the stories I was telling myself. Luckily for me, the people I decided to work with that Dolittle are some of the best humans I’ve ever had the privilege to know, second only to my life partner, and they offered their support. But the feelings still lingered — this was something I needed to work through and deal with for myself. Which leads to my next real failure — Not taking time to reflect and process how much I was learning.&lt;/p&gt;

&lt;p&gt;On a related note, I realise that previous accomplishments have been holding me back from future achievements. I’ve struggled to put my self and content out there for several reasons, one of them has been constantly comparing and raising the bar based on those previous accomplishments, without applying any form of context or perspective. The word “should” has been used way too often, which leads to an internal dialogue of shame.&lt;/p&gt;

&lt;h3&gt;
  
  
  Growth
&lt;/h3&gt;

&lt;p&gt;Things were looking a lot brighter towards the end of the year. I was more comfortable with the day-to-day challenges we had at work, as well being able to acknowledge my role and the contributions I was making. The brighter outlook gave me some space to reflect on my learnings. I was also able to identify a weakness I had (with help from colleagues), namely that I self-censor myself a lot. This weakness manifested itself in not speaking up in meetings, not sharing my thoughts on what I felt was important through other communication channels, and also it put a solid block over any attempt I made to write anything in public. Holding back thoughts isn’t to be confused with reflecting and pondering over a topic before forming an opinion (which I also do), but when it was evident that I had something to ask or say — I didn’t.&lt;/p&gt;

&lt;p&gt;I was afraid. Afraid to not have the right answer, to appear foolish and found it easier to keep thoughts within. Identifying this specific behaviour has been a critical discovery. Being afraid of allowing myself to be imperfect is a root behaviour for quite a lot of the issue I’ve been facing, and is something I’ll be working on in the coming year.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, being in a startup means wearing multiple hats, and this has been the year I re-embraced modern javascript web development with AureliaJS. It’s been a painful process of wanting to deliver and ship great products but stumble on “simple” things like identifying component abstractions, understanding es6 syntax, as well as learn the framework itself. My inner voice talking down these learnings as simple things is another manifestation of the “should”-problem with unrealistic expectations.&lt;/p&gt;

&lt;p&gt;When I now look back, I’m proud of the progress I’ve made in this area. From feeling inadequate to be able to write and structure applications, write re-usable and business components, and drive application logic with TDD in less than a year has been a huge win.&lt;/p&gt;

&lt;p&gt;None of my learnings would have been possible without the people I’m around me. They say that you are the average of the 5 people closest to you, and I’m surrounded by 5 of the most influential people in my career, not to mention them surrounded by others they are equally influenced by. I’m humbled, honoured and so privileged to be able to work in these conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  On a private note
&lt;/h3&gt;

&lt;p&gt;On a private note, I want to mention running. 2018 has been the year I purposefully made running a habit. I have some big hairy goals for 2019 when it comes to running, namely complete a marathon towards the end of the year, which means taking the habit and applying running plans &amp;amp; structure.&lt;/p&gt;

&lt;p&gt;I’ve also cut drastically down on phone usage around the family as well. Disabled my facebook account, removed twitter from my phone, and optimised more time to be present with them. It’s come in handy as our 3rd child has made the transition from innocent toddler to chaos monster (3 yrs old).&lt;/p&gt;

&lt;p&gt;I’ve also been able to plough through quite a few books during my commutes. For anyone interested, you can see my progress &lt;a href="https://www.goodreads.com/pavsaund"&gt;on Goodreads&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  In conclusion
&lt;/h3&gt;

&lt;p&gt;Summarising the ups and downs of an entire year in a post is challenging in itself, and writing this has been a lot harder than expected. I knew I wanted to write this before spending time on anything else, so it had the potential to become a blocker for me.&lt;/p&gt;

&lt;p&gt;I also wanted this to be a personal reflection post, rather than a set of useful tips, things I’ve learned, quick wins — lists of accomplishments, contributions and side projects. There’s enough of that out there. Instead, I hope this post reminds people that life is messy. We all have our ups and downs, our cycles of growth, expansion, reflection. That doesn’t mean that you’re less than others in any way, just that you’re human and on your own journey.&lt;/p&gt;

&lt;p&gt;At the end of the day, I’m privileged to work alongside some fantastic people, on a great mission together, building the company we’ve always wanted to work in. All the while, having a precious family life and being able to spend quality with my kids.&lt;/p&gt;

&lt;p&gt;In retrospect, the year 2018 has been precisely what I needed to prepare for me for 2019. That’s how I choose to see it, at least, and perhaps that’s enough?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How has 2018 been for you? How are you doing with the transition to 2019? Please share your thoughts and reflections.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://codingwithempathy.com/2019/01/14/2018-in-review/"&gt;&lt;em&gt;codingwithempathy.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on January 14, 2019.&lt;/em&gt;&lt;/p&gt;


</description>
      <category>userexperience</category>
      <category>startuplife</category>
      <category>reflections</category>
      <category>yearinreview</category>
    </item>
    <item>
      <title>Proof of Concept? MVP? Just tell me when it’s done!</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Mon, 26 Nov 2018 10:01:01 +0000</pubDate>
      <link>https://dev.to/pavsaund/proof-of-concept-mvp-just-tell-me-when-its-done-3k14</link>
      <guid>https://dev.to/pavsaund/proof-of-concept-mvp-just-tell-me-when-its-done-3k14</guid>
      <description>

&lt;p&gt;&lt;a href="https://cdn-images-1.medium.com/max/1024/1*BsllTh66nrleARYfwQ3-PA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://cdn-images-1.medium.com/max/1024/1*BsllTh66nrleARYfwQ3-PA.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The meeting between iterative product development and a company used to approaching product development through the project-lens can be quite harsh.&lt;/p&gt;

&lt;p&gt;On one hand, you have set budgets and revenue targets. The project deliveries have been planned out in detail for the coming months, quarters or even years, with a chain of dependencies for the rest of the year.&lt;/p&gt;

&lt;p&gt;On the other hand, you need to follow up deliveries and make day-to-day decisions that affect the scope and the end product drastically in a true agile manner.&lt;/p&gt;

&lt;p&gt;All the while nobody can give an answer to whether you’ll hit your targets or not. And you, as a stakeholder or project owner, just want to know &lt;strong&gt;when it will be done&lt;/strong&gt;!&lt;/p&gt;

&lt;h4&gt;
  
  
  Here’s the deal…
&lt;/h4&gt;

&lt;p&gt;There are a few things to note when moving into this world of digitalising organisations and iterative product development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agile™️ doesn’t mean faster or cheaper.&lt;/li&gt;
&lt;li&gt;You decide when it’s done.&lt;/li&gt;
&lt;li&gt;Product development is hard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re willing to take my word for it then you can stop reading now. Otherwise, please continue…&lt;/p&gt;

&lt;h4&gt;
  
  
  Agile / DevOps / Lean doesn’t mean faster, cheaper or easier
&lt;/h4&gt;

&lt;p&gt;Digitisation has been sold into organisations as the “way to go” and alongside this the notion of some form of agile software development. The implication (or outright promise) is that this form of development will be faster, cheaper or both. There are no guarantees of this.&lt;/p&gt;

&lt;p&gt;Instead, what these practices mean is that you are able to test your assumptions in a more iterative manner. This means you can create just enough of a product that will allow a customer to use it and give you feedback before your next iteration. So, in this sense, it’s a lot cheaper to verify you are on the right path, and the cost of course-correcting is a lower than if this was a project going over several months or years.&lt;/p&gt;

&lt;p&gt;Working this way is more demanding of your time, as you are now part of the team that builds and discovers the product — you need to be available on a more ad-hoc schedule. There are more small follow-up meetings and constant changes to priorities based on customer feedback, or new opportunities. Working like this is engaging and fun, but it can also be draining. Especially if you’re used to the more traditional “ordering” of software through larger “waterfall” -projects.&lt;/p&gt;

&lt;h4&gt;
  
  
  Product Development is Hard
&lt;/h4&gt;

&lt;p&gt;The hardest part of building a software product is knowing what to build. You may have an idea of what you want to create, but will that actually meet people’s needs? Saying you need an app or a service doesn’t instantly make it something that people want to use. The only way to find the market-fit is to test it out with real customers and users. This is what an iterative development methodology offers — the chance to test assumptions before you run out of budget (money, time, goodwill, etc).&lt;/p&gt;

&lt;p&gt;Gone are the days where business and in-house customers accepted sub-par products to be able to get their work done. Consumers are used to sleek, intuitive apps on the web and their devices. There’s no magic switch that causes these same people to lower the bar of what they expect when they enter their work setting.&lt;/p&gt;

&lt;p&gt;This expectation of quality becomes a challenge for businesses wanting to raise the bar. As the quality of the products improves, so does the need to build the right thing. It is crucial to verify whether the pain you are trying to address is one the people using your product actually feel, and want dealt with.&lt;/p&gt;

&lt;p&gt;To keep up with this pace means focusing more on product development as a core discipline, instead of something to be outsourced or managed from afar.&lt;/p&gt;

&lt;h4&gt;
  
  
  You decide when it’s done.
&lt;/h4&gt;

&lt;p&gt;The dirty secret is that “it” is never really done — the elusive product remains a moving target. Getting something out the door is just the first step. Instead, the focus should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When is the product good enough to be valuable to the people using it?&lt;/li&gt;
&lt;li&gt;How much are you willing to spend to find out how close you are to fulfilling those needs?&lt;/li&gt;
&lt;li&gt;How do you know the product is actually attending to the needs and delivering value?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With an iterative process, you have the opportunity to approach answering these questions and respond by changing the direction of your product. But the only way I’ve found to get real feedback is to give full slices of functionality in front of real users.&lt;/p&gt;

&lt;p&gt;Sketches, prototypes, proofs of concepts and minimum viable products are all viable approaches to elicit feedback — the earlier the better. Pick your flavour, be harsh with the scope, and get a working product out there!&lt;/p&gt;

&lt;h4&gt;
  
  
  Finally
&lt;/h4&gt;

&lt;p&gt;Organisations’ need for fixed budgets, scopes and roadmaps can hinder you from realising the tantalising promise of value in a truly iterative product development cycle. That value is the agility to be able to respond to changing needs, and new opportunities.&lt;/p&gt;

&lt;p&gt;Embrace experimentation through continuous feedback cycles and adjust the reality of where you are with a product based on them. Based on these feedback cycles you’ll know when you’re done.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Clap 👏 or follow Dolittle to read more about how we believe in enabling others to create products that help users feel like superheroes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Photo by&lt;a href="https://unsplash.com/photos/_4815u_ACqQ?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;José Alejandro Cuffia&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/prototype?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post appeared originally on the &lt;a href="https://medium.com/dolittle/proof-of-concept-mvp-just-tell-me-when-its-done-9d34ddb6b88"&gt;Dolittle blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;


</description>
      <category>agile</category>
      <category>ux</category>
      <category>productdevelopment</category>
      <category>userexperience</category>
    </item>
    <item>
      <title>Hitting refresh</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Wed, 16 May 2018 21:46:04 +0000</pubDate>
      <link>https://dev.to/pavsaund/hitting-refresh-3lig</link>
      <guid>https://dev.to/pavsaund/hitting-refresh-3lig</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RsddxI7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A8sQWAJE-NnO6TMMGgxk4HQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RsddxI7B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A8sQWAJE-NnO6TMMGgxk4HQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlearning is one of the hardest parts with any transition. You bring with you many years of experiences, expectations and biases. These have built up over time through different work situations you have adapted to. Past experiences allow you to hit the ground running when it comes to work and communication. They can also be heavy baggage, slowing you down. In a startup this baggage could be the very thing that’s holding you back. You’re looking at completely new problems with views that don’t match your situation.&lt;/p&gt;

&lt;p&gt;Here at Dolittle, we’re hitting refresh on many of our previous assumptions. Looking at old problems with fresh eyes. How we approach our coding practices. How we are working with customers. How we are approaching contracts. How we are building products. We’re re-learning, and allowing our culture to grow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If your mind is empty, it is always ready for anything, it is open to everything. In the beginner’s mind there are many possibilities, but in the expert’s mind there are few. ” -&lt;a href="https://www.goodreads.com/quotes/17022-if-your-mind-is-empty-it-is-always-ready-for"&gt;Shunryu Suzuki&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An example is communication. Coming from a very distributed team, a few of us wanted a more formal process. More documentation, more written communication. This is important down the line as we grow, but not so much in the beginning when priorities change almost daily.&lt;/p&gt;

&lt;p&gt;Hitting refresh is an important part of starting anything new. Making it explicit that you need to take a step back and reconsider your expectations. You’re going to have new problems and you can’t deal with them if your focusing on solving the problems you had in the past. At the same time, it’s importatnt to leverage universal learnings and principles. It’s also important to recognise the context in which those are valid.&lt;/p&gt;

&lt;p&gt;Are they &lt;strong&gt;really&lt;/strong&gt; valid to you now?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Photo by &lt;a href="https://unsplash.com/photos/qsCGtoDHNoM?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;rawpixel&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/reload?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This post appeared originally on the &lt;a href="https://medium.com/dolittle/hitting-refresh-9d5961370f1d"&gt;Dolittle blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>empathy</category>
      <category>startup</category>
      <category>communication</category>
    </item>
    <item>
      <title>Tribes — a search for belonging</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Tue, 27 Feb 2018 21:41:24 +0000</pubDate>
      <link>https://dev.to/pavsaund/tribes--a-search-for-belonging-4d43</link>
      <guid>https://dev.to/pavsaund/tribes--a-search-for-belonging-4d43</guid>
      <description>

&lt;p&gt;&lt;a href="https://cdn-images-1.medium.com/max/1024/1*gHxQaC66S9c5Oe51laYYKg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://cdn-images-1.medium.com/max/1024/1*gHxQaC66S9c5Oe51laYYKg.jpeg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finding your tribe isn’t easy. It’s a long journey of many missteps. You may be part of a tribe your entire life. You may wander to look for other tribes out there and dive back into your old tribe for safety. Other times you need to find another to call your own. Sometimes you need to start your own with your closest around you. Other times you need to just start, and hope others will follow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tribes
&lt;/h3&gt;

&lt;p&gt;But, what do I mean with a tribe? In this context I’m using it as a community where you feel a sense of belonging. Originally, tribes were defined by proximity, the land you belonged to. So changing tribes was a physical action. Moving from one area to another. Going through rituals and sacrifices to leave your original tribe and be accepted in your new one. It took a lot of friction.&lt;/p&gt;

&lt;p&gt;In society today the sense of belonging to a certain part of land isn’t what defines our tribe any longer. We define it in other ways like: race, nationality, gender, faith, community, workplace, hobbies etc. Some are hierarchical, like your team, that resides within your department in your organization and others are virtual, like social media groups, forums, interests, programming languages.&lt;/p&gt;

&lt;p&gt;In our digital age there is a lot less friction to switch between tribes. You can find a virtual tribe, where switching could be as simple as joining another group. You can physically move across the world and still stay in the same virtual tribe, even though you may change your physical one.&lt;/p&gt;

&lt;h3&gt;
  
  
  A sense of belonging
&lt;/h3&gt;

&lt;p&gt;As we grow and mature, we all go through our own versions of &lt;a href="https://en.wikipedia.org/wiki/Hero%27s_journey"&gt;“the hero’s journey”&lt;/a&gt;. Moving through life, searching for a place of belonging.&lt;/p&gt;

&lt;p&gt;My family tribe has always been important to me, it’s the most rock-solid tribe I belong to. Our shared values define the core of my belief and value system, and in extension is the lens I see the world through.&lt;/p&gt;

&lt;p&gt;Another tribe that gives me a sense of fulfilment is meaningful work alongside caring individuals. Working to make a change in this world for the better. It’s what’s guided me unconsciously so far, and now what I’m starting to become more aware of and act upon.&lt;/p&gt;

&lt;h3&gt;
  
  
  The search
&lt;/h3&gt;

&lt;p&gt;It’s become easier than ever to find and change tribes. It’s also easier than ever to get distracted in your search. The best we can do is follow our heart, and not settle. As we grow, so do our needs and finding a tribe that allows you to grow to your full potential is something I think is worth searching for.&lt;/p&gt;

&lt;p&gt;As I’ve become more aware of my journey and what is important to me, I’ve also been more aware of what I want from my tribe. I’m sure this will evolve and change as I grow, and I’m sure that no tribe will be a perfect match. I do know that when I see something that is closer to my own values I need to make the move. How else will I know if it’s what I need?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“If you haven’t found it yet, keep looking. Don’t settle. As with all matters of the heart, you’ll know when you find it. And, like any great relationship, it just gets better and better as the years roll on.” ― Steve Jobs&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, if you’ve found your tribe — cherish it, nourish it and consider yourself lucky. If not, work through the friction and &lt;strong&gt;don’t settle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://codingwithempathy.com/2018/02/27/tribes-search-belonging"&gt;&lt;em&gt;codingwithempathy.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on February 27, 2018.&lt;/em&gt;&lt;/p&gt;





</description>
      <category>career</category>
      <category>personaldevelopment</category>
      <category>softwaredevelopment</category>
      <category>community</category>
    </item>
    <item>
      <title>Coding with Empathy in 2017</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Sat, 30 Dec 2017 22:02:20 +0000</pubDate>
      <link>https://dev.to/pavsaund/coding-with-empathy-in-2017-5b1a</link>
      <guid>https://dev.to/pavsaund/coding-with-empathy-in-2017-5b1a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Empathy&lt;/strong&gt;  — the 4th most popular word in 2017, &lt;a href="https://www.merriam-webster.com/words-at-play/word-of-the-year-2017-feminism/empathy" rel="noopener noreferrer"&gt;according to Merriam-Webster&lt;/a&gt;. It’s interesting that this word has risen up in its popularity this year. Mirriam-Webster also points out the connection between politics in the USA, and the increase usage and searches for empathy.&lt;/p&gt;

&lt;p&gt;Here’s &lt;a href="https://trends.google.com/trends/explore?date=2004-01-01%202017-12-30&amp;amp;q=empathy,compassion,sympathy" rel="noopener noreferrer"&gt;Google’s take&lt;/a&gt; on how empathy is doing 2017. This is a trend graph compared to sympathy and compassion:&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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYqXAiGLpiPuQP1mjK2sxiA.png" 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%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AYqXAiGLpiPuQP1mjK2sxiA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, definitely something people are becoming more aware of, and possibly also exploring.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Blog
&lt;/h3&gt;

&lt;p&gt;This blog hasn’t been &lt;a href="http://codingwithempathy.com/2016/12/27/reflecting-on-2016/" rel="noopener noreferrer"&gt;as active as in 2016&lt;/a&gt;, but there has been some activity.&lt;/p&gt;

&lt;p&gt;3 of my most popular blog posts came out this year, and have been well-received both on this blog and on the great &lt;a href="https://dev.to/pavsaund"&gt;dev.to platform&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="http://codingwithempathy.com/2017/01/10/rituals-of-shaming-in-the-software-industry/" rel="noopener noreferrer"&gt;Rituals of Shaming in the Software Industry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingwithempathy.com/2017/01/24/efficiency-effectiveness-teams/" rel="noopener noreferrer"&gt;Efficiency and Effectiveness in Software Development Teams&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://codingwithempathy.com/2017/01/17/please-break-build/" rel="noopener noreferrer"&gt;Please, break the build!&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The PAVLOG
&lt;/h3&gt;

&lt;p&gt;As announced in the &lt;a href="http://codingwithempathy.com/2016/12/27/reflecting-on-2016/" rel="noopener noreferrer"&gt;2016 summary&lt;/a&gt;, I explored video this year, with a month of daily vlog episodes exploring daily reflections on &lt;a href="https://www.amazon.com/Daily-Stoic-Meditations-Wisdom-Perseverance/dp/0735211736" rel="noopener noreferrer"&gt;The Daily Stoic by Ryan Holiday&lt;/a&gt;. I was inspired by two of Ryan Holiday’s previous books; &lt;a href="https://www.amazon.com/Obstacle-Way-Timeless-Turning-Triumph/dp/1591846358" rel="noopener noreferrer"&gt;The Obstacle is the Way&lt;/a&gt; and &lt;a href="https://www.amazon.com/Ego-Is-the-Enemy/dp/B01GSIZ9EY" rel="noopener noreferrer"&gt;Ego is the Enemy&lt;/a&gt;. These introduced me to Stoicism, and how valuable this philosophy is. The 30 episodes of the Vlog was an eye-opening experience for me, on a personal and professional level. I found new joy in editing videos, learning about stoicism, and combining this with a daily journal that also doubled up as a vlog.&lt;/p&gt;

&lt;p&gt;Feel free to check out the results, and let me know what you think:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/-7RLkE8wkhA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Conference talks / Podcasts
&lt;/h3&gt;

&lt;p&gt;Empathy was also in focus on the conference scene this year, as I presented at NDC Oslo and QCon New York. Both talks are recorded and are available.&lt;/p&gt;

&lt;p&gt;I’m really happy with how these talks turned out, and the feedback from them. Though they are very similar, I think the second iteration at QCon NYC really struck home.&lt;/p&gt;

&lt;p&gt;I also had the chance to have a chat with Shawn Hastie for the InfoQ Engineering Culture Podcast where we dove into topics of team leadership and empathy. It was a good chat, and certainly something I’d love to do more of.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=qxeOo2jWoNM" rel="noopener noreferrer"&gt;NDC Oslo 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/presentations/empathy-burnout-impostor" rel="noopener noreferrer"&gt;QCon NYC 2017&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/podcasts/pavneet-saund" rel="noopener noreferrer"&gt;Pavneet Saund on Practical Empathy on the InfoQ Engineering Culture Podcast&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  #goofyreligion
&lt;/h3&gt;

&lt;p&gt;I can’t have a summary of 2017 without mentioning the &lt;a href="https://twitter.com/search?f=tweets&amp;amp;vertical=default&amp;amp;q=%23goofyreligion&amp;amp;src=tyah" rel="noopener noreferrer"&gt;#goofyreligion group on twitter&lt;/a&gt;. What started out as a joke by Dave Rael quickly escalated to a hash-tag a few of us rallied around to help motivate each other to take care of our health, physical and mental.&lt;/p&gt;

&lt;p&gt;The tweet that started it all: &lt;iframe class="tweet-embed" id="tweet-898018961798832128-419" src="https://platform.twitter.com/embed/Tweet.html?id=898018961798832128"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-898018961798832128-419');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=898018961798832128&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;To learn more about the #goofyreligion and also a great conversation on balance and functional programming check out Reid Evans on the Developer on Fire Podcast &lt;/p&gt;
&lt;div class="podcastliquidtag"&gt;
  &lt;div class="podcastliquidtag__info"&gt;
    &lt;a href="/developeronfire/episode-294--reid-evans--connected-mindset"&gt;
      &lt;h1 class="podcastliquidtag__info__episodetitle"&gt;Episode 294 | Reid Evans - Connected Mindset&lt;/h1&gt;
    &lt;/a&gt;
    &lt;a href="/developeronfire"&gt;
      &lt;h2 class="podcastliquidtag__info__podcasttitle"&gt;
        Developer on Fire
      &lt;/h2&gt;
    &lt;/a&gt;
  &lt;/div&gt;
  &lt;div id="record-episode-294--reid-evans--connected-mindset" class="podcastliquidtag__record"&gt;
    &lt;img class="button play-butt" id="play-butt-episode-294--reid-evans--connected-mindset" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fplaybutt-5e444a2eae28832efea0dec3342ccf28a228b326c47f46700d771801f75d6b88.png" alt="play"&gt;
    &lt;img class="button pause-butt" id="pause-butt-episode-294--reid-evans--connected-mindset" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fpausebutt-bba7cb5f432cfb16510e78835378fa22f45fa6ae52a624f7c9794fefa765c384.png" alt="pause"&gt;
    &lt;img class="podcastliquidtag__podcastimage" id="podcastimage-episode-294--reid-evans--connected-mindset" alt="Developer on Fire" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fpodcast%2Fimage%2F22%2Fdevonfireprofile.png"&gt;
  &lt;/div&gt;

  &lt;div class="hidden-audio" id="hidden-audio-episode-294--reid-evans--connected-mindset"&gt;
  
    
    Your browser does not support the audio element.
  
  &lt;div id="progressBar" class="audio-player-display"&gt;
    &lt;a href="/developeronfire/episode-294--reid-evans--connected-mindset"&gt;
      &lt;img id="episode-profile-image" alt="Episode 294 | Reid Evans - Connected Mindset" width="420" height="420" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fpodcast%2Fimage%2F22%2Fdevonfireprofile.png"&gt;
      &lt;img id="animated-bars" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fanimated-bars-4e8c57c8b58285fcf7d123680ad8af034cd5cd43b4d9209fe3aab49d1e9d77b3.gif" alt="animated volume bars"&gt;
    &lt;/a&gt;
    &lt;span id="barPlayPause"&gt;
      &lt;img class="butt play-butt" alt="play" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fplaybutt-5e444a2eae28832efea0dec3342ccf28a228b326c47f46700d771801f75d6b88.png"&gt;
      &lt;img class="butt pause-butt" alt="pause" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fpausebutt-bba7cb5f432cfb16510e78835378fa22f45fa6ae52a624f7c9794fefa765c384.png"&gt;
    &lt;/span&gt;
    &lt;span id="volume"&gt;
      &lt;span id="volumeindicator" class="volume-icon-wrapper showing"&gt;
        &lt;span id="volbutt"&gt;
          &lt;img alt="volume" class="icon-img" height="16" width="16" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fvolume-cd20707230ae3fc117b02de53c72af742cf7d666007e16e12f7ac11ebd8130a7.png"&gt;
        &lt;/span&gt;
        &lt;span class="range-wrapper"&gt;
          
        &lt;/span&gt;
      &lt;/span&gt;
      &lt;span id="mutebutt" class="volume-icon-wrapper hidden"&gt;
        &lt;img alt="volume-mute" class="icon-img" height="16" width="16" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fvolume-mute-8f08ec668105565af8f8394eb18ab63acb386adbe0703afe3748eca8f2ecbf3b.png"&gt;
      &lt;/span&gt;
      &lt;span class="speed" id="speed"&gt;1x&lt;/span&gt;
    &lt;/span&gt;
    &lt;span class="buffer-wrapper" id="bufferwrapper"&gt;
      &lt;span id="buffer"&gt;&lt;/span&gt;
      &lt;span id="progress"&gt;&lt;/span&gt;
      &lt;span id="time"&gt;initializing...&lt;/span&gt;
      &lt;span id="closebutt"&gt;×&lt;/span&gt;
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;h3&gt;
  
  
  Gratitude
&lt;/h3&gt;

&lt;p&gt;The second half of 2017 has been about gratitude for me. Not so much about external gratitude, but internal. Appreciating the people around me. Putting them in focus after a lot of focus on myself and my activities. I suppose it’s about balance, really. I spend time doing these things in public to help others, but at the end of the day I also need to be there for the people around me. So a special thank you to my wife, kids and family.&lt;/p&gt;

&lt;p&gt;I want to thank the wonderful people at &lt;a href="https://twitter.com/KomplettDev" rel="noopener noreferrer"&gt;KomplettDev&lt;/a&gt;. It’s a joy to work with so many individuals bringing their whole selves to work every day and building the best web-shops in Europe.&lt;/p&gt;

&lt;p&gt;I also want to thank the #goofyreligion gang (with friends). These people inspire with their actions, and their words. I’m lucky to have you, and looking forward to sharing the #goofyreligion with more people in 2018.&lt;/p&gt;

&lt;p&gt;A special thank you to &lt;a href="https://twitter.com/emilcardell" rel="noopener noreferrer"&gt;Emil Cardell&lt;/a&gt; for giving me a journal and pen after the NDC Oslo talk. I now journal every day and am better for it! 150 days of journaling so far this year.&lt;/p&gt;

&lt;h3&gt;
  
  
  Looking Forward
&lt;/h3&gt;

&lt;p&gt;I’m striving for balance, and finding a healthy way to push myself on all fronts. I’ve discovered this means tackling some bad habits I’ve built up through my life and understanding that changing my mindset is going to be hard. A keyword here is rewiring habits.&lt;/p&gt;

&lt;p&gt;There are also some new things happening, which have me really excited and I hope to share more of that in 2018!&lt;/p&gt;

&lt;p&gt;Finally I’d like to thank each and every one of you readers for putting empathy in your lives, and for those around you. I’ve seen a lot of positivity in our communities that give me a lot of hope of bringing safety into our profession. But there’s a long way to go yet. So, let’s continue our work in 2018.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="http://codingwithempathy.com/2017/12/30/coding-with-empathy-in-2017/" rel="noopener noreferrer"&gt;&lt;em&gt;codingwithempathy.com&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on December 30, 2017.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>gratitude</category>
      <category>habits</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
    </item>
    <item>
      <title>Controlling the source of truth - The value of better commit messages</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Mon, 08 May 2017 20:42:17 +0000</pubDate>
      <link>https://dev.to/pavsaund/controlling-the-source-of-truth---the-value-of-better-commit-messages</link>
      <guid>https://dev.to/pavsaund/controlling-the-source-of-truth---the-value-of-better-commit-messages</guid>
      <description>

&lt;p&gt;&lt;em&gt;Post originally published on &lt;a href="http://codingwithempathy.com/2016/06/28/controlling-the-source-of-truth/"&gt;codingwithempathy.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Working as a developer involves communication on many levels. We need to communicateÂ withÂ business stakeholders in a domain specific language, abstracting away much of the technical jargon. Team communicationÂ on the other hand is a lot more technical, and closer to our reality in code.&lt;/p&gt;

&lt;p&gt;AÂ lot of our communication is silent though. It happens through async tools like email, Skype or Slack. I'm sure that anyone that's attempted communicating this way has experienced how easy it is to under-communicate, leading to a ping-pong of messages before the intent and understanding is conveyed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The end goal of all this communication is software that delivers value to users.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Software isn't finished when it's been delivered. It changes over time and loses its original intent. This leads to even more async communication, which can go over months or years. I'm talking about the communication that happens through the code we write.&lt;/p&gt;

&lt;h2&gt;Breaking down communication in code&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What -Â &lt;/strong&gt;All written code explains &lt;strong&gt;what&lt;/strong&gt; it does. Functionally correct code that executes the right end-result through a compiler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How -Â &lt;/strong&gt;Some explains &lt;strong&gt;how&lt;/strong&gt; it's done. Code has to be readable and understandable. Clean code and focus around patterns and practices like BDD / DDD are all approaches of bringing the ubiquitous language of the problem domain into the code base. Making it easier to understand how logical business components work. The rules involved and how they interact with other bounded contexts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why -Â &lt;/strong&gt;Conveying &lt;strong&gt;why&lt;/strong&gt;Â code is how it is. The intent of the software written. Usually using code comments, separate documentation or even good tests / specifications.&lt;/p&gt;

&lt;h2&gt;Source control as context&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://xkcd.com/1597/"&gt;&lt;img class="size-full wp-image-4244 aligncenter" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ITIOTCwt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codingwithempathy.com/wp-content/uploads/2016/06/git.png" alt="git" width="330" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AÂ challenge with code over time, is that it evolves and changes based on requirements and needs. If a team has great discipline then tests / specifications / documentation will evolve with it, but there's always a tendency for that to rot, become stale or even be blatantly wrong.&lt;/p&gt;

&lt;p&gt;This is where we can turn to our source control to help. Any given commit in a repository is a snapshot code base, displaying changes to our code and the overall state of that repository. More importantly though, it shows the context in which code was changed.&lt;/p&gt;

&lt;p&gt;The context gives us information like when a change was made, who made it, which other files were involved, and where it fits in the history of the repository. This all aids us when trying to understand the context of how the code has evolved to where it is.&lt;/p&gt;

&lt;h2&gt;Dotting the i&lt;/h2&gt;

&lt;p&gt;The real magic trick of the source control is the commit message. This message has the power to convey context-aware information that &lt;strong&gt;will not change over timeÂ &lt;/strong&gt;(yes, you can rewrite source-history sometimes, try not to overdo it). But it can convey the intent of a change in a way that gives meaning to a developer.&lt;/p&gt;

&lt;p&gt;Writing a message that explains &lt;strong&gt;whyÂ &lt;/strong&gt;a change is being made will make it a lot easier for the next developer (often yourself) to understand the reasoning behind a change.&lt;/p&gt;

&lt;h2&gt;The message&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://xkcd.com/1296/"&gt;&lt;img class="size-full wp-image-4238 aligncenter" src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZTiQv8b0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://codingwithempathy.com/wp-content/uploads/2016/06/git_commit.png" alt="git_commit" width="439" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Herein lies a challenge for many developers. Either they don't really care about the value of good commits and commit messages, or they focus too much on the technicality around micro-commits with technical changes or the message format.&lt;/p&gt;

&lt;p&gt;Writing good commit messages is a skill alongside coding that needs to be practiced. Focusing on logical commits that convey thought and intent is where the value lies.&lt;/p&gt;

&lt;p&gt;How the messages are formed is a matter of opinion, taste and preferences for the given code base and team, but here are a few resources to get you started.&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://chris.beams.io/posts/git-commit/"&gt;How to write a Git Commit Message&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://arialdomartini.wordpress.com/2012/09/03/pre-emptive-commit-comments/"&gt;Preemptive commit comments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;A note on issue trackers&lt;/h2&gt;

&lt;p&gt;Issue trackers are awesome when connected to our source control. By explicitly connecting our commits to issues we can have proper discussions and capture a lot more of that said intent. But if you ever change issue-trackers without the possibility of moving history, all that valuable communication is "lost" in the context of reading code.&lt;/p&gt;

&lt;h2&gt;"Writing good messages is hard"&lt;/h2&gt;

&lt;p&gt;Writing good messages is hard the same way that writing goodÂ code is hard. You need to understand the "why". Look beyond the user story telling you what to do, and focus on why the change is required to begin with.&lt;/p&gt;

&lt;h2&gt;committing to it&lt;/h2&gt;

&lt;p&gt;Why this focus on understandable code through context and communication and writing skills? Unless you're not already convinced that communication and context are valuable to you and your team on a daily basis, there's the fact that developersÂ spend &lt;a href="https://blog.codinghorror.com/when-understanding-means-rewriting/"&gt;&lt;strong&gt;most of their time understanding code&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Look past the technical details of message lengths and how to format a commit message, but rather focus on the value of conveying intent of why changes are being made in a concise and understandable way.&lt;/p&gt;

&lt;p class="p1"&gt;At the end of the day, when all the original developers have moved on and the documentation is out-dated, our source control is where we can look to find the "truth".&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover-image:Â &lt;a href="https://www.flickr.com/photos/please/180892741/"&gt;yuankuei&lt;/a&gt; via &lt;a href="https://visualhunt.com/"&gt;Visualhunt / &lt;/a&gt;&lt;a href="http://creativecommons.org/licenses/by-nc-nd/2.0/"&gt;CC BY-NC-ND&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;


</description>
      <category>git</category>
      <category>sourcecontrol</category>
      <category>communication</category>
    </item>
    <item>
      <title>Efficiency and Effectiveness in Software Development Teams</title>
      <dc:creator>Pavneet Singh Saund</dc:creator>
      <pubDate>Wed, 25 Jan 2017 20:23:24 +0000</pubDate>
      <link>https://dev.to/pavsaund/efficiency-and-effectiveness-in-software-development-teams</link>
      <guid>https://dev.to/pavsaund/efficiency-and-effectiveness-in-software-development-teams</guid>
      <description>

&lt;p&gt;Efficiency and effectiveness. These two concepts are quite often mixed up. Each with their own strengths and weaknesses. Understanding these concepts will increase the impact of a software developers work.&lt;/p&gt;

&lt;p&gt;They come to play in the following quote Â from former Apple CEO, Gil Amelio &lt;a href="http://www.businessinsider.com/gil-amelio-steve-jobs-2011-10"&gt;who said&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Amelio: Â "Apple is like a ship with a hole in the bottom, leaking water, and my job is to get the ship pointed in the right direction."&lt;/p&gt;

&lt;p&gt;Smith/Jobs: Â "But what about the hole?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we take apart that quote, let's dig into &lt;a href="https://effectivesoftwaredesign.com/2010/09/12/efficiency-vs-effectiveness/"&gt;some definitions!&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Efficiency: Doing the thing right&lt;/p&gt;

&lt;p&gt;Effectiveness: Doing the right thing!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amelio is focusing on doing the thing right: "&lt;em&gt;...get the ship pointed in the right direction&lt;/em&gt;". But he isn't focused on doing the right thing: "&lt;em&gt;But what about the hole?&lt;/em&gt;". So he's focusing on efficiency, and not effectiveness.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Software Development&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have a grasp of the concepts, let's look at how this maps over to he realm of software development teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Efficiency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As a single developer, working in a team (or alone). It's easy to get caught up in a cycle of efficiency. Where the mindset and focus is on getting yourself up to a high level of productivity. Such as streamlining how you write code through patterns, practices and looking for repeatable processes. It could also mean having a strong focus on writing quality code. There may also be a tendency to take this too far and optimise code for terseness and not readability..&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Effectiveness&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The cycle of effectiveness entails more pragmatism and being aware of your context. An effective developer understandsÂ the context of the tasks they are working on. They are then able to make decisions in code based on that context. Such as when and how to make compromises when it comes to code quality / abstractions and implementation details.Â Sometimes whats needed is to take a step back and solve problems without code. Or even removing features.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Teams&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pair &amp;amp; Mob Programming&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Most developers have heard of the concept of pair-programming, and even mob-programming. Both are considered as good practices for many reasons. At the same time these practices are also scorned upon by others as inefficient and a waste of time.&lt;/p&gt;

&lt;p&gt;Pair-Programming involves 2 people (dev, tester, business etc) working on the same screen. There are many variants, including strong-pairing, driver /navigator, TDD-driven variants and some others. Eric Elliot has &lt;a href="https://medium.com/javascript-scene/stop-wasting-time-pair-programming-rocks-4a99604cb09d#.ol0ba8oki"&gt;a great breakdown on pair-programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mob-Programming is an approach that involves the entire team working on the same screen, and delivering the code in a similar way. The recommended approach is a driver / navigator style where the team serves as navigator and the driver writes what the navigators tell them. I &lt;a href="http://codingwithempathy.com/2016/09/06/trusting-in-the-mob-a-story-of-bringing-distributed-team-members-closer/"&gt;wrote a little about it here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These approaches sound wasteful and inefficient, especially mob-programming. Yet people argue that these are great way to deliver more value by being more effective. Why? How?&lt;/p&gt;

&lt;p&gt;The premise is more eyes on the code written, more knowledge sharing, and a shared sense of ownership. There's also a cross-pollination of disciplines, ideas and shared ownership. Understanding others' limitations and strengths will allow a team to grow even more.&lt;/p&gt;

&lt;p&gt;The fundamental drive for these approaches is about being more &lt;strong&gt;effective&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Slack and the Utilisation Trap&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Henrik Kniberg has producedÂ many articles andÂ videos about the balancing act of delivering value through teams. He's presented two concepts that illustrate the power of an effective mindset; Slack and the Utilisation Trap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slack&lt;/strong&gt; is the absence of work. Where people have Â the opportunity to decide how they want to spend their time for themselves. What may seem counter-intuitive is how much value there is in unplanned time. The idea is that this is where people have the opportunity to "do magic" or innovate. Basically, being &lt;strong&gt;effective&lt;/strong&gt;. Check out Henrik's &lt;a href="https://www.youtube.com/watch?v=k8DTUYfUOa0"&gt;video on the topic&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Utilisation Trap&lt;/strong&gt; relates to slack. It depicts the notion of achieving a highly &lt;strong&gt;efficient&lt;/strong&gt; team, which always has work to do. The focus is to achieve as close to 100% utilised as possible. By lowering the efficiency rate and introducing slack a team can achieve an optimal state of flow. &lt;a href="https://www.youtube.com/watch?v=CostXs2p6r0"&gt;Here's Henrik's video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Organisations and development processes tend to have a focus on efficiency in their systems. So it's very natural to get stuck in a mindset of efficiency, when what you want is effectiveness. In the rush to be over-effective, it's also easy to bypass efficiency, leading to poorer systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;My reflections&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Focusing on efficiency alone can lead to poor solutions that don't meet the needs of our systems. Focusing on effectiveness alone can lead to inefficient systems that are technically flawed.&lt;/p&gt;

&lt;p&gt;As I have grown and evolved as a person and a developer I've felt that my maturity / seniority level matches my focus on effectiveness. In my younger days, it was all about being as efficient as possible, where now I'm focused on being as effective as possible. As I further progress, understanding where and how to be both efficient and effective is where there is the most value. Growing a &lt;a href="http://codingwithempathy.com/2016/04/26/the-proactive-software-developer/"&gt;proactive mindset&lt;/a&gt; has been a way for me to realise my impact in the greater context.&lt;/p&gt;

&lt;p&gt;As earlier stated in this article, both are valuable, but there's a natural tendency to lean towards efficiency. Instead we should spend more time on practices that make us more effective. As developers, teams and organisations.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are your experiences with personal or team efficiency and effectiveness? Do you struggle to balance? Leave a comment below, and share this article with someone Â ðŸ’š
&lt;/h3&gt;




&lt;h4&gt;
  
  
  &lt;em&gt;This post was originally published on the &lt;a href="http://codingwithempathy.com/2017/01/24/efficiency-effectiveness-teams/"&gt;Coding with Empathy&lt;/a&gt; blog&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Inspired by conversations with &lt;a href="http://twitter.com/tomasekeli"&gt;Tomas&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover photo: &lt;a href="https://www.flickr.com/photos/danielmennerich/16660653571/"&gt;Daniel Mennerich&lt;/a&gt; via &lt;a href="https://visualhunt.com/"&gt;Visualhunt&lt;/a&gt; / &lt;a href="http://creativecommons.org/licenses/by-nc-nd/2.0/"&gt;CC BY-NC-ND&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;


</description>
      <category>agile</category>
      <category>teams</category>
      <category>mobprogramming</category>
      <category>pairprogramming</category>
    </item>
  </channel>
</rss>
