<?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: Jedidiah Weller 👑</title>
    <description>The latest articles on DEV Community by Jedidiah Weller 👑 (@jedihacks).</description>
    <link>https://dev.to/jedihacks</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%2F82519%2F23933713-393d-4dc4-a7f1-9a870f92e95c.jpg</url>
      <title>DEV Community: Jedidiah Weller 👑</title>
      <link>https://dev.to/jedihacks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jedihacks"/>
    <language>en</language>
    <item>
      <title>How We Cut 80 % of Our Backend Calls in Summon Worlds</title>
      <dc:creator>Jedidiah Weller 👑</dc:creator>
      <pubDate>Fri, 01 Aug 2025 17:40:00 +0000</pubDate>
      <link>https://dev.to/openforge/how-we-cut-80-of-our-backend-calls-in-summon-worlds-3jk7</link>
      <guid>https://dev.to/openforge/how-we-cut-80-of-our-backend-calls-in-summon-worlds-3jk7</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reduce redundant API calls by centralizing loading logic in a shared helper.
&lt;/li&gt;
&lt;li&gt;Always expose a domain model (class instance) instead of raw state slices.
&lt;/li&gt;
&lt;li&gt;Cache with &lt;code&gt;shareReplay&lt;/code&gt; so multiple subscribers share one request.
&lt;/li&gt;
&lt;li&gt;Dispatch only plain-object payloads—no class instances in actions.
&lt;/li&gt;
&lt;li&gt;Inspired by our experience in the &lt;a href="https://www.summonworlds.com" rel="noopener noreferrer"&gt;Summon Worlds&lt;/a&gt; AI world-building app.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  0. The Backstory 🏗️
&lt;/h2&gt;

&lt;p&gt;First things first - a story.  In September of last year, we took over an AI World Building App called &lt;a href="https://www.summonworlds.com" rel="noopener noreferrer"&gt;Summon Worlds&lt;/a&gt;.  The app was a cool idea, had an great community, and scratched that gaming itch that all developers have. &lt;/p&gt;

&lt;p&gt;So after we took it on, we rebuilt the (very hacky) flutter prototype in Ionic + Angular, and we decided to use NGRX to help with performance and storage calls.  Since we were in a hurry, that was about all the thought we put into the &lt;em&gt;pattern&lt;/em&gt; in which we were implementing NGRX and we &lt;em&gt;thought&lt;/em&gt; it would be an easy process.  &lt;/p&gt;

&lt;p&gt;It was not.&lt;/p&gt;

&lt;p&gt;So, fast forward till today - there were a &lt;em&gt;ton&lt;/em&gt; of architecture and pattern decisions that I wish we did differently, and I'd like to share some of them with you so that hopefully you do not make the same mistakes as we did. &lt;/p&gt;

&lt;p&gt;This particular article is focused on an "accidental" antipattern of NGRX + Clone Deep that caused major issues.  If you like it let me know, and I'll write a couple more about some other anti-patterns to avoid!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. How We Discovered The Antipattern 🏗️
&lt;/h2&gt;

&lt;p&gt;The State was managed via NgRx and persisted to Firebase. One morning we noticed our billing spike—and Cloud Functions logs revealed that loading our simple “feed” screen fired &lt;strong&gt;42&lt;/strong&gt; &lt;code&gt;loadEntity&lt;/code&gt; calls every time. On slower networks, users waited ages. We knew something had to change.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Recognizing the Anti-Pattern
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 The Over-eager Helper
&lt;/h3&gt;

&lt;p&gt;A common helper service looked like this:&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericHelperService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppState&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="c1"&gt;// Raw state slice used everywhere&lt;/span&gt;
  &lt;span class="nx"&gt;getEntityState&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EntityState&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;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectEntityState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Lightweight shortcut mapping to a class&lt;/span&gt;
  &lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EntityModel&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;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectEntityData&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EntityModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Dispatching class instances directly&lt;/span&gt;
  &lt;span class="nf"&gt;updateEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EntityModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;updateEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;model&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;Every component calling &lt;code&gt;getEntity$()&lt;/code&gt; would dispatch &lt;code&gt;loadEntity&lt;/code&gt; again and again, re-instantiate the model, and violate NgRx’s serialization rules.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Core Principles of the Fix
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Raw slice only for edge cases.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instantiate your domain model exactly once in a shared helper.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dispatch only plain JSON payloads—no class instances in actions.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These principles rescued our performance in Summon Worlds and will help any NgRx project.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. A Generic Refactor Recipe
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Strengthen the Helper
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericHelperService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppState&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="cm"&gt;/** Raw slice — cache and reuse sparingly */&lt;/span&gt;
  &lt;span class="nx"&gt;getEntityState&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EntityState&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;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectEntityState&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;shareReplay&lt;/span&gt;&lt;span class="p"&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="p"&gt;}&lt;/span&gt;

  &lt;span class="cm"&gt;/** Central loader + model emitter */&lt;/span&gt;
  &lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EntityModel&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;// Trigger load exactly once per id&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loadEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;combineLatest&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;selectEntityById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;selectEntityLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&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;!!&lt;/span&gt;&lt;span class="nx"&gt;data&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;loading&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EntityModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nf"&gt;shareReplay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;refCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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="cm"&gt;/** Mutations accept model, dispatch plain data */&lt;/span&gt;
  &lt;span class="nf"&gt;saveChanges&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EntityModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&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;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPlainObject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;updateEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;payload&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;ul&gt;
&lt;li&gt;
&lt;code&gt;shareReplay(1)&lt;/code&gt; shares one subscription, caching the latest value.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;combineLatest + filter&lt;/code&gt; waits until data is ready before emitting.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;toPlainObject()&lt;/code&gt; strips methods, leaving a serializable payload.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4.2 Use the Async Pipe Everywhere
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before (Summon Worlds style):&lt;/strong&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="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;ngOnDestroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&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="nx"&gt;value$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compute&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;{{ value$ | async }}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No manual subscriptions, no memory leaks, no boilerplate.&lt;/p&gt;




&lt;h3&gt;
  
  
  4.3 Remove Deep-Clone Workarounds
&lt;/h3&gt;

&lt;p&gt;Swap out:&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;safeData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawData&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For:&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;computed$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;optionalProp&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;defaultValue&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;TypeScript strict checks catch missing properties, eliminating the &lt;code&gt;cloneDeep&lt;/code&gt; band-aid.&lt;/p&gt;




&lt;h3&gt;
  
  
  4.4 Centralize Error Handling
&lt;/h3&gt;

&lt;p&gt;Instead of catching errors in every component:&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;catchError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;Handle failures in an effect:&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;loadEntityFailure$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;ofType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loadEntityFailure&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Load failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dispatch&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your components only worry about rendering the happy path.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Migration Checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Helper overhaul&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;shareReplay&lt;/code&gt; on raw-slice methods.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Implement &lt;code&gt;getEntity$()&lt;/code&gt; with load dispatch, &lt;code&gt;combineLatest&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, mapping, and &lt;code&gt;shareReplay&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Component cleanup&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace manual subscriptions with async-pipe streams.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Payload serialization&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add &lt;code&gt;.toPlainObject()&lt;/code&gt; to your models.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dispatch only JSON in actions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Remove &lt;code&gt;cloneDeep&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Delete all deep-clone code.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Centralize error flow&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Catch errors in effects only.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enable runtime checks&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;StoreModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;runtimeChecks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="na"&gt;strictStateImmutability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="na"&gt;strictActionImmutability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;h2&gt;
  
  
  6. Measuring Success
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend calls per view&lt;/td&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;−90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory on initial render (MB)&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;−36%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to first paint (s)&lt;/td&gt;
&lt;td&gt;4.2&lt;/td&gt;
&lt;td&gt;2.7&lt;/td&gt;
&lt;td&gt;−1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(These are some of the actual numbers we achieved, fyi)&lt;/p&gt;




&lt;h2&gt;
  
  
  7. FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Why not dispatch class instances?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; They break DevTools serialization, effect replay, and cross-tab sync. POJOs are the safest contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q:&lt;/strong&gt; Aren’t selectors memoized?&lt;br&gt;
&lt;strong&gt;A:&lt;/strong&gt; Yes—but extra &lt;code&gt;loadEntity&lt;/code&gt; dispatches before data arrives bypass selector caching. &lt;code&gt;shareReplay&lt;/code&gt; fixes that gap.&lt;/p&gt;


&lt;h2&gt;
  
  
  8. Generic Snippets to Copy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Model Skeleton&lt;/strong&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EntityModel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EntityData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;id&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* domain logic */&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;toPlainObject&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;EntityData&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="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Helper Skeleton&lt;/strong&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="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericHelperService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppState&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nx"&gt;getEntity&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&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;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;EntityModel&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;loadEntity&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;combineLatest&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;selectEntityById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;selectEntityLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&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;!!&lt;/span&gt;&lt;span class="nx"&gt;data&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;loading&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EntityModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
      &lt;span class="nf"&gt;shareReplay&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;bufferSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;refCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;h2&gt;
  
  
  9. Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Measure&lt;/strong&gt; your own before/after metrics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactor&lt;/strong&gt; one entity at a time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share&lt;/strong&gt; this guide and (of course) check out &lt;a href="https://www.summonworlds.com" rel="noopener noreferrer"&gt;Summon Worlds&lt;/a&gt; if you are into AI world-building.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy refactoring—and may your selectors be ever memoized!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>ngrx</category>
      <category>typescript</category>
      <category>performance</category>
    </item>
    <item>
      <title>What to Do After the Coding Academy</title>
      <dc:creator>Jedidiah Weller 👑</dc:creator>
      <pubDate>Wed, 19 Dec 2018 20:46:34 +0000</pubDate>
      <link>https://dev.to/openforge/what-to-do-after-the-coding-academy-4g3p</link>
      <guid>https://dev.to/openforge/what-to-do-after-the-coding-academy-4g3p</guid>
      <description>&lt;h2&gt;
  
  
  TOC
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction - What to Do After The Coding Academy&lt;/li&gt;
&lt;li&gt;Step 1 - Learn The True Fundamentals&lt;/li&gt;
&lt;li&gt;Step 2 - Create a very simple C++ application&lt;/li&gt;
&lt;li&gt;Step 3 - Translate that C++ Application into a Web Application&lt;/li&gt;
&lt;li&gt;Step 4 - Understand the Internet&lt;/li&gt;
&lt;li&gt;Step 5 - Understand your environment&lt;/li&gt;
&lt;li&gt;Step 6 - Go HAM on a Web Dev Framework - but be well-rounded too&lt;/li&gt;
&lt;li&gt;Step 7 - Practice Being Systematic&lt;/li&gt;
&lt;li&gt;Closing Remarks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What to Do After The Coding Academy &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Hello everyone!   For about 5 years now I've owned and operated a development shop, and in that time I have had the privilege of seeing many developers grow their skills (both professionally and personally) as they entered the workplace.  However; I quickly noticed some trends from individuals coming from Coding Academies and Bootcamps.&lt;/p&gt;

&lt;p&gt;While teaching our young padawans, I quickly learned that there is a lot of information missing from most Coding Academy curriculums.  I chalk it up to the programs being so short and attempting to cram so much knowledge into their brains at a time.  Most people gain the knowledge of "what is" software development, but lack the wisdom of "how to" use it.&lt;/p&gt;

&lt;p&gt;If this is you (or one of your team members) - you're not alone.  It's nearly impossible to become a full-fledged software engineer in 3-6 months, although places like NYDCA would like you to believe otherwise. &lt;a href="https://technical.ly/philly/2018/11/09/new-york-code-design-academy-is-shutting-down/"&gt;And perhaps that is why they shut down&lt;/a&gt;.  But fear not; there is hope!  Coding Academies are a great &lt;em&gt;start&lt;/em&gt; to your journey so long as they are followed by the right mentorship and guidance on where to go next.&lt;/p&gt;

&lt;p&gt;So, I'd like to provide exactly that - mentorship and guidance on "What to do next". I hope this article will graduates, as well as Senior Devs and Managers out there tasked with training them.  We're all in this career together, so let's help each other make it an amazing one for everyone.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S.  If anyone has additional items you think are useful; I'll update this article to be a culmination of best practices/wisdom.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Learn The True Fundamentals &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;You may have thought you learned the fundamentals at your coding academy; but alas you actually learned the fundamentals of web development.  What you did not yet learn is the fundamentals of the "how" and "why" of computer science.  Questions like "What is an IP address?", "What is a var (under the hood)?", and "How can I step-through debug this problem?" are never asked nor taught, so it's up to us to fix that.&lt;/p&gt;

&lt;p&gt;To get this understanding I'd recommend traveling to the past so that you can understand the future.  Scripting languages are NOT the place to learn fundamentals; however, C++ is built on the fundamentals.   You'll probably never use this language again - but I DO want you to take 2-3 days to go through the following tutorials.  I promise they'll be beneficial - so here's the steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download Visual Studio Code&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.learncpp.com/#Chapter0"&gt;Take yourself through this C++ tutorial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Complete chapters 0, 1, 2, 4, 5, 6, 7:&lt;/li&gt;
&lt;li&gt;While completing the Chapters answer the following questions:

&lt;ul&gt;
&lt;li&gt;What did you learn from this chapter?&lt;/li&gt;
&lt;li&gt;What questions/difficulties did you have during the chapter?&lt;/li&gt;
&lt;li&gt;What questions or things do you want to try, at the end of the chapter?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2 - Create a very simple C++ application.  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I'd recommend the following:&lt;/p&gt;

&lt;p&gt;Create an application that &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When launched via the command line, says 
"Hello, what would you like to create?  "1: A Dog", "2: A Cat""&lt;/li&gt;
&lt;li&gt;When the user types "1" and hits enter, a Dog class is created.&lt;/li&gt;
&lt;li&gt;In the Dog Class Constructor, have a print function "I am a dog, I am born"&lt;/li&gt;
&lt;li&gt;In the Cat Class Constructor, have a print function "I am a cat, I am born!"&lt;/li&gt;
&lt;li&gt;Abstract Dog and Cat class to be part of an Animal class, and inherit from it.&lt;/li&gt;
&lt;li&gt;Complete some other small changes to reflect what you've just learned in your tutorials&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3 - Translate that C++ Application into a Web Application. &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now, create a Web Application using the technology you've been taught at your coding academy - but instead of the command line, have a GUI through a web browser.  Either an Angular Application or a Rails Application will do just fine, then answer the following questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does C++ compare to javascript/ruby?
&lt;/li&gt;
&lt;li&gt;What are the differences?
&lt;/li&gt;
&lt;li&gt;Which parts were easier?  Which parts were harder?&lt;/li&gt;
&lt;li&gt;Have a friend introduce an error in both - but not show you where. Now, try to debug the error on both.  Do you see a difference in debugging?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4 - Understand the Internet.  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Most people don't understand what the internet actually is; and it's truly magic. &lt;br&gt;
 Did you know there is all this hidden data in every packet that's sent over the web?  Do you know how your ISP works?   Well, to get started let's read this &lt;a href="https://web.stanford.edu/class/msande91si/www-spr04/readings/week1/InternetWhitepaper.htm"&gt;Stanford whitepaper on what the Internet actually is.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5 - Understand your environment. &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This step is a controversial step and is best done on an old crappy computer you don't use anymore.  If you don't have one - make sure to back everything up on your current system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; (Assuming you're creating an Angular App) Download and install Homebrew, Node, NPM, Bower, and Grunt.
&lt;/li&gt;
&lt;li&gt; Try to install and run &lt;a href="http://mean.io/"&gt;A MEAN Stack sample app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Uninstall the current version of node, and install an older version.  Play with versioning through &lt;a href="https://github.com/creationix/nvm"&gt;NVM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Try to run the same app.&lt;/li&gt;
&lt;li&gt; Now, do the same thing on someone &lt;em&gt;else's&lt;/em&gt; computer.  Doesn't matter what type - there's learning on all OS :) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You may or may not have issues - guess what; version dependencies are a BIG BIG challenge for a lot of developers.  5 people with macs may all have different environments - and that's not even including all the variations of Windows / Windows + Ubuntu / Linux distros.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;(Bonus) Wipe your computer - and re-install everything.   That's the controversial part, but often when you're doing development and you don't quite understand filepaths and chmod/sudo consequences you'll mess up your dev environment.  You can spend hours debugging it, or you can wipe and restart - your choice.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, you must be thinking to yourself "There's got to be a way to standardize environments".  Yes, there are plenty of ways.  A well-known approach is a tool called &lt;a href="https://medium.com/phytochemia-tech-blog/how-docker-can-improve-your-development-environments-731cdfda0b9a"&gt;Docker&lt;/a&gt;.  I'll let you read up on the rest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6 - Go HAM on a Web Dev Framework - but be well-rounded too &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I personally love the Angular + Ionic combination for Web &amp;amp; Mobile apps, but there are a ton out there.  React.js is awesome and I'll be at the Vue.js conference in Amsterdam in February.  Once our interns at OpenForge are done with the above steps (and some 1-1 sessions), we ask them to start completing some online courses through Udemy.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; First, I'd take a quick debugging class here to learn about &lt;a href="https://www.udemy.com/mastering-web-and-mobile-debugging-using-chrome-dev-tools/learn/v4/overview"&gt;Chrome dev tools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Second, complete the entirety of this &lt;a href="https://www.udemy.com/the-complete-guide-to-angular-2/learn/v4/overview"&gt;Angular 7 course&lt;/a&gt;.  It covers a LOT&lt;/li&gt;
&lt;li&gt; Third, take appreciation for my array numbering to the left &amp;lt;-- If you know your basics, you know why I did this :) &lt;/li&gt;
&lt;li&gt; Fourth, practice creating a MEAN stack app and deploying it.  Here's some links&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.hongkiat.com/blog/node-js-server-side-javascript/"&gt;http://www.hongkiat.com/blog/node-js-server-side-javascript/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://devcenter.heroku.com/articles/mean-apps-restful-api"&gt;https://devcenter.heroku.com/articles/mean-apps-restful-api&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.modulus.io/build-your-first-http-server-in-nodejs"&gt;http://blog.modulus.io/build-your-first-http-server-in-nodejs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 7 - Practice Being Systematic &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;PAY ATTENTION TO THIS - This is the most important piece of advice I can give you. &lt;/p&gt;

&lt;p&gt;When you're working on a feature, debugging, or any type of development - commit after every meaningful change.  Do NOT wait for the feature/bug to be finished.&lt;/p&gt;

&lt;p&gt;Computer Science is a &lt;em&gt;science&lt;/em&gt;, and science is systematic.  We try, measure, and come to conclusions.  I promise you that if you break down large commits and large problems into super small ones; you will accomplish tasks 10x quicker and be happier for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Remarks &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I hope this is helpful - it's been the 'time-tested mother-approved' formula for us for a couple years now.  &lt;/p&gt;

&lt;p&gt;If anyone has anything else to add (or recommends modifications) I am all ears, please comment below!&lt;/p&gt;

&lt;p&gt;Best Regards,&lt;br&gt;
&lt;a href="https://dev.to~Jedi"&gt;www.twitter.com/jedihacks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>help</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Passion Projects are Fun - Except In Production</title>
      <dc:creator>Jedidiah Weller 👑</dc:creator>
      <pubDate>Sun, 25 Nov 2018 15:45:55 +0000</pubDate>
      <link>https://dev.to/openforge/passion-projects-are-fun---except-in-production-1lmj</link>
      <guid>https://dev.to/openforge/passion-projects-are-fun---except-in-production-1lmj</guid>
      <description>&lt;p&gt;Right around the time that the Ionic team came out with &lt;a href="https://stenciljs.com/"&gt;Stencil.js&lt;/a&gt; our company made a brand transition from Webjunto to &lt;a href="http://openforge.io"&gt;OpenForge&lt;/a&gt;.  Since we are all massively in love with all things technology; we said "OMG - An opportunity to play with Stencil!  Let's build our Website using Stencil as a web-component pre-compiler and scratch that Wordpress B.S. It will be &lt;em&gt;so&lt;/em&gt; much faster!".&lt;/p&gt;

&lt;p&gt;From a business owner's perspective, it was a perfect opportunity to transition from Wordpress to something that we built with our own hands. We could &lt;a href="https://github.com/openforge/OPENFORGE.IO"&gt;Open Source&lt;/a&gt; and talk about it.  It allowed us to train our team on a new technology while simultaneously applying it to something useful.  &lt;/p&gt;

&lt;p&gt;But - we were unprepared.  That's when the pain hit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Our Assumption
&lt;/h1&gt;

&lt;p&gt;We drastically underestimated how much is truly built into Wordpress that we never think about.  Between Blog, Page, User Management, and SEO capabilities - it's a huge set of features, and eliminates a lot of need for &lt;em&gt;process&lt;/em&gt; internally in the team between the design, dev, and business departments.&lt;/p&gt;

&lt;p&gt;We also assumed that anything that was in Wordpress we could easily build, and to our team's credit we &lt;strong&gt;can&lt;/strong&gt; build the features; however - what we don't have is the process for identifying &lt;strong&gt;what&lt;/strong&gt; needs to be reviewed across departments.&lt;/p&gt;

&lt;p&gt;For instance; how many business people think about the manifest.json file? How many people (in a full design &amp;amp; dev team) are qualified to identify SEO mismatches between content and url routing?  These things are automatically provided and identified by Wordpress and Yoast, and we didn't even realize it.&lt;/p&gt;

&lt;p&gt;The benefit was that it created a need to more tightly integrate the 3 major departments at our company (Design, Dev, Business); however, the down side was that we had to create a process for this and we were &lt;strong&gt;completely&lt;/strong&gt; unprepared.&lt;/p&gt;

&lt;h1&gt;
  
  
  My Advice
&lt;/h1&gt;

&lt;p&gt;Was it worth it?  I &lt;em&gt;think&lt;/em&gt; so due to the training to the team, PWA expertise, and lessons learned; however, on a scale of 'how worth it' it was not as clearly a win as I expected.&lt;/p&gt;

&lt;p&gt;I'll break down my advice into a bulleted list of what was worth it, and what pieces we missed.  My hope is if you would like to try the same thing for your company, you'll have a bit of a headstart on what troubles may arise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worth It
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The experience &amp;amp; training (as we move into single-source PWA's)&lt;/li&gt;
&lt;li&gt;The speed (It feels like the road-runner compared to WP)&lt;/li&gt;
&lt;li&gt;The control (fully customizable, without any plugin development)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Harder Than Expected / Unexpected
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;SEO Management.  What's the replacement for Yoast?

&lt;ul&gt;
&lt;li&gt;Robots.txt&lt;/li&gt;
&lt;li&gt;Manifest File&lt;/li&gt;
&lt;li&gt;URL Routing Strategy (and who reviews this?)&lt;/li&gt;
&lt;li&gt;404 Page for old I.E. (we just redirect)&lt;/li&gt;
&lt;li&gt;Canonical Links&lt;/li&gt;
&lt;li&gt;Alt Text to images (we keep forgetting - need to update process)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Polyfills&lt;/li&gt;
&lt;li&gt;Lighthouse Optimizations (local vs. deployed)&lt;/li&gt;
&lt;li&gt;Smooth Scrolling&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There were some more items that didn't make it into our &lt;a href="https://github.com/openforge/OPENFORGE.IO/blob/master/CHANGELOG.md"&gt;changelog&lt;/a&gt;, as I think of them I'll update the post.&lt;/p&gt;

&lt;p&gt;Hope this helps folks!&lt;/p&gt;

&lt;p&gt;&lt;a href="//www.twitter.com/jedihacks"&gt;~Jedi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>devops</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Tutorial 1,000 - A Real Production App</title>
      <dc:creator>Jedidiah Weller 👑</dc:creator>
      <pubDate>Wed, 24 Oct 2018 14:25:42 +0000</pubDate>
      <link>https://dev.to/openforge/tutorial-1000---a-real-production-app-134b</link>
      <guid>https://dev.to/openforge/tutorial-1000---a-real-production-app-134b</guid>
      <description>&lt;p&gt;Hey everyone,&lt;/p&gt;

&lt;p&gt;Yesterday we released (and open-sourced) a full production mobile app, and wrote a guest blog about it through Ionic's Blog.  It's not everyday we get to see the 'nuts-and-bolts' of a full app, so I figured I'd share it with the community here as well :) &lt;/p&gt;

&lt;p&gt;It took around 400 hours to design and build the Ionic 3 app.  We used a serverless architecture, Firebase, and Ionic 3.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Why we built it
&lt;/h2&gt;

&lt;p&gt;We're developers - although we always scope work the scoping process can get messy.   &lt;/p&gt;

&lt;p&gt;It's very easy to be 'peer pressured' (even unknowingly) into changing your estimates when your friends and colleagues think differently.  This is exacerbated when you have junior and senior developers in the same room providing estimates together.  The junior devs are often afraid to provide real estimates, because they are much longer than the senior's.&lt;/p&gt;

&lt;p&gt;We used to use planningpoker.com for scoping sessions; but everyone could see each others estimates and then during a session team members would change their answers to avoid confrontation.  This often leads to inaccurate scopes; because the person who's answer wins is not always the person tasked with completing the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we open-sourced it
&lt;/h2&gt;

&lt;p&gt;It's aggravatingly difficult to find examples of real production applications that are open sourced (but still simple to follow).  When I train new team members, I find that going from Angular's "tutorial 101" to building a full application is about a 10 foot step, and no one has 10 foot legs. &lt;/p&gt;

&lt;p&gt;So, when the dev team proposed designing and building this tool we agreed to open source it and write about it.  It's got some cool features, such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teamwork Projects integration&lt;/li&gt;
&lt;li&gt;Serverless architecture&lt;/li&gt;
&lt;li&gt;Ionic 3 application&lt;/li&gt;
&lt;li&gt;Live scoping via Firebase&lt;/li&gt;
&lt;li&gt;Firebase. Firebase. Firebase.  We're loving Firebase :D &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We wrote a full guest blog post about the architecture and decisions we made on &lt;a href="https://blog.ionicframework.com/built-with-ionic-juntoscope/"&gt;Ionic's Blog&lt;/a&gt;, so rather than re-invent the wheel I'd encourage everyone to read the full breakdown there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you download it?
&lt;/h2&gt;

&lt;p&gt;No - you should &lt;a href="https://github.com/openforge/JuntoScope"&gt;Clone it from Github&lt;/a&gt; and use it yourself.  However; we figured it may be hard to get some project managers on board if it didn't have a least a semblance of an established app.  So go ahead, use it if you'd like, but seriously - feel free to take it as well :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;We had a lot of positive feedback from the product; so we'll be releasing another full production app next month (open sourced) and blogging about the process.   We don't intend to build any more integrations besides Teamwork because that's what we use internally at &lt;a href="https://openforge.io"&gt;OpenForge.io&lt;/a&gt;; however, if you are using another tool and would like to create a PR we'd be happy to help support it.&lt;/p&gt;

&lt;p&gt;Thanks everyone, stay cool and dev on!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://twitter.com/jedihacks"&gt;Jedi&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
