<?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: Hamed Farag</title>
    <description>The latest articles on DEV Community by Hamed Farag (@hamed_farag).</description>
    <link>https://dev.to/hamed_farag</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%2F151873%2F8e302154-c053-4e73-87ee-7531d50827ec.jpeg</url>
      <title>DEV Community: Hamed Farag</title>
      <link>https://dev.to/hamed_farag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hamed_farag"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Fri, 05 Jun 2026 11:31:30 +0000</pubDate>
      <link>https://dev.to/hamed_farag/-3od6</link>
      <guid>https://dev.to/hamed_farag/-3od6</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575" class="crayons-story__hidden-navigation-link"&gt;Micro-Frontends, One Year On: The Workarounds That Made Single-SPA Reliable for Us&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/hamed_farag" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F151873%2F8e302154-c053-4e73-87ee-7531d50827ec.jpeg" alt="hamed_farag profile" class="crayons-avatar__image" width="237" height="237"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hamed_farag" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Hamed Farag
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Hamed Farag
                
              
              &lt;div id="story-author-preview-content-3797164" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/hamed_farag" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F151873%2F8e302154-c053-4e73-87ee-7531d50827ec.jpeg" class="crayons-avatar__image" alt="" width="237" height="237"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Hamed Farag&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575" id="article-link-3797164"&gt;
          Micro-Frontends, One Year On: The Workarounds That Made Single-SPA Reliable for Us
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/architecture"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;architecture&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/frontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;frontend&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/singlespa"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;singlespa&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/microfrontend"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;microfrontend&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            23 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Micro-Frontends, One Year On: The Workarounds That Made Single-SPA Reliable for Us</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Mon, 01 Jun 2026 16:57:55 +0000</pubDate>
      <link>https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575</link>
      <guid>https://dev.to/hamed_farag/micro-frontends-one-year-on-the-workarounds-that-made-single-spa-reliable-for-us-2575</guid>
      <description>&lt;p&gt;A year ago, &lt;a href="https://hamedfarag.dev/posts/one-year-microfontend" rel="noopener noreferrer"&gt;I wrote about our first year with micro-frontends&lt;/a&gt;. It was a frank retrospective: the win was framework autonomy and independent deploys, the cost was 20 GB of RAM during local dev, 15–20 minute deploy cycles, and a monorepo that became its own coordination tax. The closing line was the honest one — &lt;em&gt;if I could choose again, I would think carefully about using Microfrontend or not.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This article is the follow-up the previous one didn't write: &lt;strong&gt;what we actually built around Single-SPA to make it work.&lt;/strong&gt; Not the architecture diagram. The workarounds. The dead code that's not really dead. The regexes we wish we didn't need. The .NET app no Single-SPA tutorial mentions. The browser-side singletons we use as message buses. The dev experience we documented and the parts we didn't.&lt;/p&gt;

&lt;p&gt;If you're evaluating Single-SPA in 2026, this is the article I wish I'd had a year ago.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where we left off
&lt;/h2&gt;

&lt;p&gt;The platform is a Single-SPA monorepo with seven in-repo apps and five shared packages. On top of that sit roughly ten standalone repositories for newer features, loaded at runtime via SystemJS import maps. Shared dependencies — React 18.2, ReactDOM, axios, react-bootstrap, single-spa 5.9.5 — are served from CDN and externalized in every webpack config. The architecture is textbook.&lt;/p&gt;

&lt;p&gt;The reality, a year in, is that the textbook stops where the workarounds start.&lt;/p&gt;




&lt;h2&gt;
  
  
  The shell isn't where you think it is
&lt;/h2&gt;

&lt;p&gt;If you read our frontend repo you'd conclude the shell is whatever directory has &lt;code&gt;single-spa&lt;/code&gt; in its &lt;code&gt;package.json&lt;/code&gt;. That's where Single-SPA gets configured. That's where &lt;code&gt;start()&lt;/code&gt; is called. There's even a webpack entry that, until recently, was producing an &lt;code&gt;index.ejs&lt;/code&gt; HTML template.&lt;/p&gt;

&lt;p&gt;That HTML template is dead code. The real shell — the HTML the browser actually receives, in every environment — is rendered by an ASP.NET MVC application, in a Razor view. The frontend repo ships JavaScript modules. The .NET host ships the page that loads them.&lt;/p&gt;

&lt;p&gt;That's the unlock. Once you see this, every other workaround in this article makes sense.&lt;/p&gt;

&lt;p&gt;Here is what the Razor view actually does, in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs the OIDC handshake and sets auth cookies server-side.&lt;/li&gt;
&lt;li&gt;Calls the Identity API to pre-fetch the user's orgs, projects, available tools, and module-level permissions.&lt;/li&gt;
&lt;li&gt;Fetches a &lt;strong&gt;runtime config&lt;/strong&gt; from an internal endpoint — that response includes the SystemJS import map and the entry-point module URL for the shell.&lt;/li&gt;
&lt;li&gt;Renders the page with the import map and the pre-fetched data both inlined.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two consequences matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Micro-app version bumps don't redeploy the shell.&lt;/strong&gt; The import map is data, not code. New version of a feature app? Update the runtime config endpoint. The next page render picks it up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first paint already knows who you are and what you can do.&lt;/strong&gt; No spinners over "loading your account." That data is in the HTML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Single-SPA documentation tells you to put your shell in a webpack project. We do, but only for the JavaScript. The HTML is owned by the backend. This is the single biggest decision we made, and the one Single-SPA tutorials don't prepare you for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 1: The regex dispatch
&lt;/h2&gt;

&lt;p&gt;Single-SPA's routing is built on activity functions: a predicate per app that returns true when the app should be mounted. With &lt;code&gt;single-spa-layout&lt;/code&gt;, you can write those declaratively as &lt;code&gt;&amp;lt;route path="..."&amp;gt;&lt;/code&gt; elements. Both APIs assume routes don't overlap meaningfully.&lt;/p&gt;

&lt;p&gt;Ours overlap. One app is the default catch-all for &lt;code&gt;/project/:id/*&lt;/code&gt;. Another app owns &lt;code&gt;/project/:id/site/*&lt;/code&gt;. Without intervention, both mount on &lt;code&gt;/project/abc-123/site/view&lt;/code&gt; — and the catch-all's router then 404s because the path doesn't exist in its tree.&lt;/p&gt;

&lt;p&gt;What we wanted was an &lt;code&gt;exclude&lt;/code&gt; rule on the catch-all's activity function. Single-SPA doesn't have one. The comment block at the top of our routing file documents that exact wish:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WE NEED FROM SINGLE-SPA TO SUPPORT ATTRIBUTE CALLED EXCLUDE FOR EXAMPLE,&lt;/span&gt;
&lt;span class="c1"&gt;// AND TO BE ARRAY OF STRING&lt;/span&gt;
&lt;span class="c1"&gt;// SO, WE ARE USING WORKAROUND TO ACHIEVE THIS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workaround is a 250-line &lt;code&gt;registerRoute(flags)&lt;/code&gt; function. One UUID-aware regex per micro-app, ordered specific-first, with the catch-all as a negative-lookahead fallback:&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;// EVERYTHING ELSE IS THE DEFAULT APP, TILL WE HAVE FOURTH APP .....&lt;/span&gt;
&lt;span class="k"&gt;if &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;project&lt;/span&gt;&lt;span class="se"&gt;\/[&lt;/span&gt;&lt;span class="sr"&gt;UUID&lt;/span&gt;&lt;span class="se"&gt;]\/(?!&lt;/span&gt;&lt;span class="sr"&gt;site&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;.+$/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;application name="@org/default-app"&amp;gt;&amp;lt;/application&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;It works. It also costs us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every new micro-app needs a shell redeploy.&lt;/strong&gt; Even though the bundle is loaded dynamically, the regex stanza isn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The file scales linearly with the catalogue.&lt;/strong&gt; We're at 17 stanzas. Adding the 30th will be the same shape as adding the 18th.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public URLs needed a parallel function.&lt;/strong&gt; A separate &lt;code&gt;registerPublicRoute()&lt;/code&gt; does the same thing for unauthenticated paths that bypass the nav shell.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The friction is small per change. It's the accumulation that bites.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 2: Shared dependencies live in the import map
&lt;/h2&gt;

&lt;p&gt;If every micro-app bundled its own React, we'd ship multiple Reacts to the browser, hooks would silently break across boundaries, and the payload would balloon. The solution is in two parts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Layer one&lt;/strong&gt;, the import map in the Razor view, declares the shared libraries:&lt;br&gt;
&lt;/p&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;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"systemjs-importmap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;imports&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&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;https://cdn.../react@18.2.0/...&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;react-dom&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;https://cdn.../react-dom@18.2.0/...&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;react-bootstrap&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;https://cdn.../react-bootstrap@2.8.0/...&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;axios&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;https://cdn.../axios@1.5.0/...&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;single-spa&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;https://cdn.../single-spa@5.9.5/...&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="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Layer two&lt;/strong&gt;, every micro-app's webpack config marks those plus our internal shared libraries (&lt;code&gt;helpers&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt;) as &lt;code&gt;externals&lt;/code&gt;. They're not bundled into the app. They're expected to come from the import map at runtime.&lt;/p&gt;

&lt;p&gt;The mechanism is elegant when it works. The cost is procedural: adding a new shared dependency requires touching the import map (a backend repository) &lt;strong&gt;and&lt;/strong&gt; marking it external in every consumer's webpack config. Miss one of either and you get a runtime crash. Our git history shows it happening — a third-party SDK was added to the import map and reverted four days later because the rollout wasn't atomic.&lt;/p&gt;

&lt;p&gt;There's a related quirk in one of our apps' webpack configs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/* force prod React in dev */&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exists because &lt;code&gt;import-map-overrides&lt;/code&gt; (more on it later) can swap in a local development bundle whose React-mode disagrees with the shell. The alias forces production React in dev so the modes line up. A workaround within a workaround.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 3: CORS, everywhere
&lt;/h2&gt;

&lt;p&gt;Every micro-app's &lt;code&gt;devServer&lt;/code&gt; block has these headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Origin&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;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Methods&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;GET, POST, PUT, DELETE, PATCH, OPTIONS&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason is mundane and load-bearing: locally, the shell runs at &lt;code&gt;:4000&lt;/code&gt;, but it pulls each app's bundle from a different port — apps live on &lt;code&gt;:4003&lt;/code&gt;, &lt;code&gt;:4007&lt;/code&gt;, &lt;code&gt;:4009&lt;/code&gt;, &lt;code&gt;:4010&lt;/code&gt;, libraries on &lt;code&gt;:4006&lt;/code&gt; and &lt;code&gt;:4008&lt;/code&gt;, and so on. SystemJS does cross-origin fetches. Without wildcard CORS the shell can't load any micro-app.&lt;/p&gt;

&lt;p&gt;It's a one-liner per webpack config. It's also nontrivial to discover the first time you build a new app from scratch. New micro-app, first day, every request fails — and the answer isn't "your code is broken," it's "your dev server doesn't allow cross-origin requests from a port you didn't even know mattered."&lt;/p&gt;

&lt;p&gt;Worth being explicit: this is dev-only. In production, every bundle lives on the same CloudFront domain. But that means the &lt;em&gt;production&lt;/em&gt; network model and the &lt;em&gt;development&lt;/em&gt; network model are different in a way the docs don't surface. Two mental models, one codebase.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 4: The bootstrap chain
&lt;/h2&gt;

&lt;p&gt;The shell's bootstrap entry doesn't call Single-SPA's &lt;code&gt;start()&lt;/code&gt; until five things have happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server-rendered user data (the envelope, more soon) is parsed.&lt;/li&gt;
&lt;li&gt;Mixpanel / Sentry / Hotjar are initialized if conditions allow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;initializeAbility()&lt;/code&gt; resolves user permissions from the Identity API.&lt;/li&gt;
&lt;li&gt;LaunchDarkly flags resolve (&lt;code&gt;await initializeFeatureFlags(...)&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;buildFrontendLayout()&lt;/code&gt; computes the layout config with those flags in hand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Only then are &lt;code&gt;constructRoutes / constructApplications / registerApplication / start&lt;/code&gt; invoked. A splash screen painted before any of this covers the gap.&lt;/p&gt;

&lt;p&gt;Naïve Single-SPA bootstraps register apps synchronously and let them race the user data. We tried that. The catch-all app would mount, fire a permission-gated query before permissions had loaded, 401, retry, 401 again, and present a permission-denied page to a user who in fact had permission. The fix was to push everything async-first and to guard the user from seeing intermediate states with the splash.&lt;/p&gt;

&lt;p&gt;A small shave we made later: LaunchDarkly is initialized with &lt;code&gt;bootstrap: "localStorage"&lt;/code&gt;. Flags from the previous session are used immediately; LD's network call updates them in the background. Without this, every page load adds a hard wait on a remote LD call before &lt;code&gt;start()&lt;/code&gt; can fire. Net effect: the splash disappears in under a second on a warm session.&lt;/p&gt;

&lt;p&gt;A small honest note: if LaunchDarkly's CDN is down, our try/catch returns the default flag set rather than blocking. Flag-gated routes silently disappear during LD outages. Failure mode chosen deliberately. The user sees a working product with fewer features instead of a blank screen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 5: Feature flags as route gates (and the window-global flag bus)
&lt;/h2&gt;

&lt;p&gt;Three of our micro-apps are gated by LaunchDarkly flags directly inside the route dispatcher:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFeatureAEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/feature-a/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFeatureBEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/feature-b/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFeatureCEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="sr"&gt;/feature-c/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can merge new micro-apps to main without exposing them. The same flags decide whether the sidebar icon renders. When we needed to roll back a feature app recently, the revert was a one-file change.&lt;/p&gt;

&lt;p&gt;One of those flags gets an extra layer: &lt;code&gt;client.variation("ft-enable-feature-a", false) &amp;amp;&amp;amp; ALLOWED_ORG_IDS.has(data.organizationId)&lt;/code&gt;. The org allowlist is a hardcoded &lt;code&gt;Set&lt;/code&gt; in shared helpers — meaning a new org requires a frontend deploy. Belt-and-braces, deliberately. LaunchDarkly is the soft kill-switch; the allowlist is the hard one. Useful when compliance requires a guarantee that no flag misconfiguration can leak the feature.&lt;/p&gt;

&lt;p&gt;Once the flags are resolved, we put them on the window:&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="kr"&gt;declare&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Window&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;__FEATURE_FLAGS__&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;FeatureFlags&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;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setFeatureFlags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FeatureFlags&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="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__FEATURE_FLAGS__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;flags&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="nf"&gt;getFeatureFlags&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;FeatureFlags&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__FEATURE_FLAGS__&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_FEATURE_FLAGS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern is everywhere in micro-frontend codebases and almost never explained as a deliberate choice. The reason we use &lt;code&gt;window&lt;/code&gt; instead of a module-level &lt;code&gt;let&lt;/code&gt; is &lt;code&gt;import-map-overrides&lt;/code&gt;. In local dev, two copies of the helpers library can sneak into memory if you override one but not the other; module-level state breaks. The window is the only truly global escape hatch the runtime guarantees. Naming the global &lt;code&gt;__FEATURE_FLAGS__&lt;/code&gt; and writing it through a setter is the cheapest way to say "this is shared mutable state, on purpose."&lt;/p&gt;

&lt;p&gt;LaunchDarkly itself is bundled into the shell — not externalized. Only the shell evaluates flags. Every micro-app reads them via &lt;code&gt;getFeatureFlags()&lt;/code&gt;. Single source of truth, single LD client instance. The natural micro-frontend instinct would be "each app does its own LD init"; we explicitly didn't, because that means N clients × N flag evaluations × N analytics events.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 6: The envelope
&lt;/h2&gt;

&lt;p&gt;There is a comment in one of our shared-helpers utilities that explains the most important pattern in this codebase better than any paragraph I could write:&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;// THE SECRET HERE IS THE BACKEND TEAM INJECT SOME DATA IN A HIDDEN INPUT FROM&lt;/span&gt;
&lt;span class="c1"&gt;// THE SERVER SIDE&lt;/span&gt;
&lt;span class="c1"&gt;// SO, DUE TO THIS WAY WE ARE 100% SURE THAT DATA WILL BE AVAILABLE BEFORE&lt;/span&gt;
&lt;span class="c1"&gt;// RENDERING THE FRONTEND APP&lt;/span&gt;
&lt;span class="c1"&gt;// SO, FROM OUR SIDE WE ARE GET THE DATA IN COMPONENTDIDMOUNT&lt;/span&gt;
&lt;span class="c1"&gt;// (useEffect without dependencies)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userDataJSON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zarf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// "zarf" means `envelop` in arabic :D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Zarf&lt;/em&gt; is Arabic for envelope. The .NET host pre-fetches the user, organizations, projects, available tools, and module permissions during the Razor render, serializes each one to JSON, and drops them into hidden inputs in the body:&lt;br&gt;
&lt;/p&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;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zarf"&lt;/span&gt;                  &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@ViewData["&lt;/span&gt;&lt;span class="na"&gt;userInfo&lt;/span&gt;&lt;span class="err"&gt;"]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zarf_organizations"&lt;/span&gt;    &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@ViewData["&lt;/span&gt;&lt;span class="na"&gt;organizations&lt;/span&gt;&lt;span class="err"&gt;"]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zarf_projects"&lt;/span&gt;         &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@ViewData["&lt;/span&gt;&lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="err"&gt;"]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zarf_tools"&lt;/span&gt;            &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@ViewData["&lt;/span&gt;&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="err"&gt;"]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"zarf_user_modules"&lt;/span&gt;     &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"@ViewData["&lt;/span&gt;&lt;span class="na"&gt;userModulesPermissions&lt;/span&gt;&lt;span class="err"&gt;"]"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SPA opens the envelope on bootstrap. There are no spinners over "loading your account." That data was always there, sitting in the DOM, before a single byte of JavaScript executed.&lt;/p&gt;

&lt;p&gt;This isn't SSR. We don't render React on the server. We ship the &lt;em&gt;data&lt;/em&gt; server-side and let the SPA mount as usual. SSR's win — no extra round-trips — without SSR's costs — no isomorphic React, no streaming, no hydration mismatches. Server-rendered context, client-rendered UI.&lt;/p&gt;

&lt;p&gt;What's in the envelope, and why each is in there:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Why it can't wait for JS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;#zarf&lt;/code&gt; (user)&lt;/td&gt;
&lt;td&gt;Mixpanel and Sentry need the user before React mounts, or the first events go anonymous.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#zarf_organizations&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The nav's org switcher renders synchronously; nav is the first app to mount.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#zarf_projects&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The redirection engine (next section) decides where to go from this.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#zarf_tools&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The sidebar icons render immediately — no flash of empty sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;#zarf_user_modules&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Permission-gated routes need a synchronous answer before mounting.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The cost lives in the host. Pre-loading does &lt;code&gt;Task.WaitAll(...)&lt;/code&gt; on four parallel HTTP calls before rendering. If Identity is slow, the whole page is slow — and there's no streaming, so the user sees nothing, not even a splash. We've traded "many fast JS fetches" for "one fat server fetch." On a warm cache, the trade is excellent. On a cold cache or a degraded Identity, it's worse than client-side. We accept that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 7: The redirection engine
&lt;/h2&gt;

&lt;p&gt;A sixty-line module sits in the shell that can short-circuit the entire bootstrap. The file's TODO header is the most honest documentation in the repo:&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;// - GET TOOLS FROM THE ZARF, NOT THE API (FOR A FASTER SOLUTION) [DEPRECATED]&lt;/span&gt;
&lt;span class="c1"&gt;// - HOW TO HANDLE 404, 500, AND OTHER ERROR CASES&lt;/span&gt;
&lt;span class="c1"&gt;// - TRY NOT TO LAND ON THE 404 PAGE (THIS HAPPENS BECAUSE THE DEFAULT APP 404s)&lt;/span&gt;
&lt;span class="c1"&gt;//   // SINCE IT IS THE CATCH-ALL MICRO-APP&lt;/span&gt;
&lt;span class="c1"&gt;// - DECIDE WHEN TO RUN THE REDIRECTION LOGIC&lt;/span&gt;
&lt;span class="c1"&gt;// - THIS LOGIC SHOULD ONLY RUN FOR THE "PORTAL" APPLICATION&lt;/span&gt;
&lt;span class="c1"&gt;// - RETEST ALL SCENARIOS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bolded line — &lt;em&gt;TRY NOT TO LAND ON THE 404 PAGE (THIS HAPPENS BECAUSE THE DEFAULT APP 404s)&lt;/em&gt; — is the workaround in one sentence. The default app is registered as the catch-all in our regex dispatch. A user landing on &lt;code&gt;/&lt;/code&gt; mounts the default app, which then 404s inside its own router because there's no project context. The redirect engine exists &lt;em&gt;to compensate for the catch-all.&lt;/em&gt; It's a Single-SPA limitation laundered through the envelope.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read user and projects from the envelope.&lt;/li&gt;
&lt;li&gt;Inspect the URL — if there's no module path, pick a sensible default.&lt;/li&gt;
&lt;li&gt;If the URL has a &lt;code&gt;projectId&lt;/code&gt; that's a valid UUID, use it; otherwise grab the first project the user owns.&lt;/li&gt;
&lt;li&gt;Hard-navigate to &lt;code&gt;/project/&amp;lt;id&amp;gt;/dashboard&lt;/code&gt; via &lt;code&gt;window.open(url, "_self")&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step matters. We use a full reload, not Single-SPA's &lt;code&gt;navigateToUrl&lt;/code&gt;, because the .NET host needs to re-render with the new path so the envelope gets refilled with that project's context, tools, and permissions. A SPA-level navigation wouldn't refill the envelope. The redirect is, in effect, asking the &lt;em&gt;server&lt;/em&gt; to re-stamp the page.&lt;/p&gt;

&lt;p&gt;The redirection engine is the first consumer of the envelope, and it uses the envelope to decide whether to throw the rest of the bootstrap away. There's also a charming one-liner that survived to production:&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;// onLoadingOff(); // USELESS :D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm keeping it. It explains more about the codebase than the comment intends to.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 8: The errors we don't tell Sentry about
&lt;/h2&gt;

&lt;p&gt;Our Sentry init is short. The filter list is the load-bearing part:&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;isCanceledRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CanceledError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// WE NEED TO SUPPORT RETRY MECHANISM&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isUnAuthorizedException&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AxiosError&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status code 401&lt;/span&gt;&lt;span class="dl"&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;isCanceledRequest&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;isUnAuthorizedException&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// drop the event&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two categories of error never make it to the dashboard. Both are micro-frontend-shaped:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Canceled requests&lt;/strong&gt; are normal when Single-SPA unmounts an app mid-flight. Every in-progress fetch in one app throws &lt;code&gt;CanceledError&lt;/code&gt; the moment the user navigates to another. Without this filter, every cross-app navigation spammed Sentry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;401s are silenced globally&lt;/strong&gt;, with the candid TODO right above. Translation: until we have proper token refresh, we're hiding the symptom. This is the kind of pragmatic debt micro-frontends accrue because no single app owns the HTTP layer. The auth flow lives in the .NET host; the cookies are set there; the SPA reads them; nobody in the SPA owns the retry semantics, so we drop the noise.&lt;/p&gt;

&lt;p&gt;The cost is paid in dev: auth bugs locally don't surface as Sentry events. You see a "request failed" toast with no stack trace, no breadcrumb, no clean repro. Engineers re-enable Sentry locally to find what's broken. It's a feature for prod, a bug for dev, and we live with the asymmetry.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workaround 9: Cross-app coordination through SystemJS singletons
&lt;/h2&gt;

&lt;p&gt;Our two shared library packages ship as SystemJS modules alongside the micro-apps, but they're not Single-SPA apps. They expose no &lt;code&gt;bootstrap/mount/unmount&lt;/code&gt; lifecycle. They're libraries. We use &lt;code&gt;webpack-config-single-spa-ts&lt;/code&gt; / &lt;code&gt;webpack-config-single-spa-react-ts&lt;/code&gt; not because they're apps, but because that's the easiest way to produce a SystemJS-compatible library bundle.&lt;/p&gt;

&lt;p&gt;The trick is load-bearing. SystemJS de-duplicates module loads by URL, so the shared library bundles are &lt;strong&gt;runtime singletons&lt;/strong&gt; across all seventeen-plus micro-apps. Every import of the helpers library returns the same instance. That singleton-ness is what makes the next three patterns possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Permissions as a Zustand store inside the components library.&lt;/strong&gt; The Ability context lives in the shared components package, wrapped in a redux-style reducer that the comments cheerfully label "MINI REDUX PATTERN." The shell calls &lt;code&gt;setAbilityPermissionsAction(permissions)&lt;/code&gt; once; every &lt;code&gt;&amp;lt;Ability.Can module="X" action="Y"&amp;gt;&lt;/code&gt; in every micro-app reads from the same store. It works only because the components library is one instance in memory. If a standalone repo bundles the components library locally — which is what some of our newer apps do — that micro-app gets its own Zustand store, and the permissions set by the shell aren't visible to it. &lt;strong&gt;This is the silent cost of bundling shared libs locally that nobody puts in the trade-off doc.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;i18n initializes at module-import time.&lt;/strong&gt; &lt;code&gt;i18n.use(initReactI18next).init({...})&lt;/code&gt; runs when the components library is imported. Whichever micro-app imports first triggers it. The comment is the cleanest admission of a side-effecting module's fragility I've seen in production code:&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;// HOW TO USE:&lt;/span&gt;
&lt;span class="c1"&gt;// label={t(`server|translation.proj:view`)}&lt;/span&gt;
&lt;span class="c1"&gt;// LIMITATION: NOT WORKING IN routes.tsx, because it loaded before this file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a single-app world, side effects at module scope work. In a micro-frontend world, the meaning of "first" depends on the import map traversal order, which isn't stable. We chose convenience and ate the limitation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;QueryProvider&lt;/code&gt; defaults to &lt;code&gt;cacheTime: 0&lt;/code&gt; and a per-mount QueryClient.&lt;/strong&gt; &lt;code&gt;cacheTime: 0&lt;/code&gt; is the tell. Normally you'd set it to several minutes. Setting it to zero means as soon as a query has no observers, it's GC'd. Combined with &lt;code&gt;useState(() =&amp;gt; new QueryClient(...))&lt;/code&gt;, each provider mount gets a fresh client. Why? Because when Single-SPA unmounts an app, you don't want its React Query cache to live on in memory — and you definitely don't want a stale &lt;code&gt;["projects"]&lt;/code&gt; from one app showing up in another. The defaults exist to &lt;strong&gt;defend the boundary between micro-apps.&lt;/strong&gt; No React Query tutorial would recommend this for a normal app. In micro-frontend land it's correct.&lt;/p&gt;

&lt;p&gt;There's also a contradiction worth naming. Inside the monorepo, we rely on the SystemJS singleton model for shared state. Newer apps in standalone repos bundle the same libraries locally and rebuild that state from scratch. Both are pragmatic. They're also incompatible with each other. The day a standalone-repo app needs to talk to the shell's Ability state, someone will have to invent a new pattern. We haven't yet. We will.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it actually feels like to work in this stack
&lt;/h2&gt;

&lt;p&gt;Architecture diagrams are tidy. The day-to-day isn't.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first thirty minutes
&lt;/h3&gt;

&lt;p&gt;A new contributor clones the repo. &lt;code&gt;pnpm install&lt;/code&gt; runs for three-to-six minutes and produces 12 GB of &lt;code&gt;node_modules&lt;/code&gt;, distributed across thirteen nested workspace directories. They copy &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;, set roughly a dozen variables, and run the default app's start script. That single script spins up &lt;strong&gt;eight webpack dev servers in parallel&lt;/strong&gt;: the shell, the nav, the default app, plus all five shared libraries.&lt;/p&gt;

&lt;p&gt;They open &lt;code&gt;http://localhost:4000&lt;/code&gt;. Nothing happens.&lt;/p&gt;

&lt;p&gt;They missed the .NET host. Or they missed the &lt;code&gt;import-map-overrides&lt;/code&gt; step. Or they have a wrong CDN URL in &lt;code&gt;.env&lt;/code&gt; and the shell loads but &lt;code&gt;getServerUserData()&lt;/code&gt; returns null and the redirect engine bails. The first successful render is five to ten minutes in, and only if everything aligns.&lt;/p&gt;

&lt;p&gt;The minimum viable mental model on day one is: monorepo, eight dev servers, .NET host, SystemJS import map, runtime config endpoint, LaunchDarkly, OIDC. That's a lot of moving parts before writing a line of code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three dev modes (and the one we actually use)
&lt;/h3&gt;

&lt;p&gt;Standalone repos run in two visible modes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;start:standalone&lt;/code&gt; runs the app on its own. No shell, no nav, no envelope, no auth. Fast, isolated, and a fantasy world where the platform doesn't exist. &lt;code&gt;getServerUserData()&lt;/code&gt; returns &lt;code&gt;null&lt;/code&gt;. Permission-gated UI either no-ops or crashes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;start:micro&lt;/code&gt; hot-reloads the app into the &lt;strong&gt;deployed test portal&lt;/strong&gt; via &lt;code&gt;import-map-overrides&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;import-map-override:@org/some-app&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;http://localhost:4009/some-app.js&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real shell, real auth, real envelope. Closest to prod. Depends on test environment being healthy. The localStorage incantation is per-browser, per-app, and every "did you clear the override?" debugging session is two minutes of confusion.&lt;/p&gt;

&lt;p&gt;But the mode engineers actually use is &lt;strong&gt;the third one&lt;/strong&gt;, and it's the one nobody documents prominently. Every shell — dev and prod — ships with &lt;code&gt;&amp;lt;import-map-overrides-full&amp;gt;&lt;/code&gt;, a custom element from the &lt;code&gt;import-map-overrides&lt;/code&gt; library that registers a floating overlay. Setting &lt;code&gt;localStorage.devtools = true&lt;/code&gt; and reloading makes the overlay appear. From there, swapping a deployed micro-app for a local build is a button click. The programmatic equivalent is &lt;code&gt;importMapOverrides.enableUI()&lt;/code&gt;. This is the load-bearing piece of DX between "I'm working on my app" and "I'm seeing my work in the real shell." It gets the least mention in onboarding.&lt;/p&gt;

&lt;p&gt;That same overlay element ships to production. The denylist meta tag exists as commented-out boilerplate in our HTML and has never been activated. Anyone with a valid prod session and access to DevTools can type &lt;code&gt;localStorage.devtools = true&lt;/code&gt; and serve their own JS bundle into the real user's session. We trust the network boundary to keep non-employees out. That is a values trade-off we made implicitly. I'm going to be honest about it here, because the article would be dishonest without it: an attacker who gets a session cookie can run arbitrary JavaScript on our domain by adding an override. The fix is one uncommented line. We haven't shipped it because the convenience for engineers exceeds the perceived risk. That trade-off should at least be explicit.&lt;/p&gt;

&lt;h3&gt;
  
  
  The triage tree
&lt;/h3&gt;

&lt;p&gt;A "splash screen never resolves" report can live in seven layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The .NET host (OIDC config, sync HTTP hung on Identity).&lt;/li&gt;
&lt;li&gt;The runtime config endpoint (stale import map, points to a broken JS bundle).&lt;/li&gt;
&lt;li&gt;The SystemJS module load (CDN 404, CORS, version mismatch).&lt;/li&gt;
&lt;li&gt;The shell bootstrap (LD timeout, ability rejection).&lt;/li&gt;
&lt;li&gt;The redirection engine (envelope malformed, no projects, regex didn't match).&lt;/li&gt;
&lt;li&gt;The regex dispatch (URL doesn't match any micro-app).&lt;/li&gt;
&lt;li&gt;The micro-app itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A new hire who only knows React will look at layer 7 for three days before someone tells them about layer 2. Documenting the triage path is the single highest-leverage DX improvement we've never written.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a new micro-app
&lt;/h3&gt;

&lt;p&gt;Walk a new contributor through adding a new feature app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register a regex stanza in the shell's routing file, ordered before the catch-all.&lt;/li&gt;
&lt;li&gt;Add the app's URL to &lt;code&gt;.env.example&lt;/code&gt; and to CI environment variables across all four environments.&lt;/li&gt;
&lt;li&gt;Update the &lt;strong&gt;runtime config endpoint&lt;/strong&gt; — different repo, different team — to include the new entry.&lt;/li&gt;
&lt;li&gt;Add a LaunchDarkly flag if rollout is gated.&lt;/li&gt;
&lt;li&gt;Optionally: add a sidenav icon, register a permission module in Identity, add an i18n bundle.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Six places. Three repositories. Two teams. No tool prevents you from forgetting step 3. The first time anyone shipped a new micro-app in this codebase, they hit "module not found in SystemJS" at runtime — and that error message tells you nothing about the runtime config endpoint being the source of truth.&lt;/p&gt;

&lt;h3&gt;
  
  
  The other taxes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branch names are validated by a Husky hook.&lt;/strong&gt; Must start with one of a small set of prefixes, must contain a Jira ticket from one of several allowed projects, must use hyphens. A new contributor types &lt;code&gt;git commit&lt;/code&gt; for the first time, hook rejects, thirty seconds of "is git broken?"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three CSS frameworks coexist.&lt;/strong&gt; Tailwind 3.4 (with mandatory &lt;code&gt;tw-&lt;/code&gt; prefix to avoid collisions), Bootstrap 5.3, FontAwesome Pro, plus CSS Modules per component. A styling decision starts with "which framework am I in." Our internal docs include a "When to Use What" table. &lt;em&gt;That table existing is a DX confession.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The lockfile is shared across twelve-plus packages.&lt;/strong&gt; A bump in one app and a bump in a shared library, merged the same day, conflict. The standard fix — delete, reinstall, recommit — costs five minutes per conflict and runs every install hook. The standalone-repo split is the strongest argument we have for &lt;em&gt;not&lt;/em&gt; sharing a lockfile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Source maps in prod are sometimes uploaded, sometimes not.&lt;/strong&gt; Recent CI commits have flip-flopped: one removed &lt;code&gt;.map&lt;/code&gt; files from S3 uploads to save bandwidth; another four days later put them back because production stack traces became unreadable. A production stack trace might be human-readable or might be &lt;code&gt;t.a is not a function&lt;/code&gt;. You don't know until the bug fires.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning runs through an internal API.&lt;/strong&gt; Every deploy hits an internal version-management service twice. Service down means deploys blocked. Single-SPA doesn't ship a version coordination layer. Every org invents one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What Single-SPA's tooling doesn't help with
&lt;/h3&gt;

&lt;p&gt;The framework gives you &lt;code&gt;single-spa-react&lt;/code&gt;, route activity functions, and a SystemJS app preset. It doesn't give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A way to run all your micro-apps from one command (we rolled &lt;code&gt;run-p start:*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A dev-mode shell that fakes auth and the envelope (we don't have one).&lt;/li&gt;
&lt;li&gt;A way to declare "app A depends on lib B" so the import map enforces load order (we rely on implicit traversal).&lt;/li&gt;
&lt;li&gt;A way to test a micro-app inside a realistic shell without a deployed environment (the override overlay).&lt;/li&gt;
&lt;li&gt;A migration path for a shared library evolving alongside the apps that consume it (we have two scopes for the same library and a half-broken story for which apps see which version).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every gap above is documented as a workaround in this article. Naming them as DX gaps, not just architectural choices, is the honest thing to do. The reader on the other side of this article — possibly evaluating micro-frontends for their own org — should leave knowing the daily cost, not just the architectural neatness.&lt;/p&gt;




&lt;h2&gt;
  
  
  From one monorepo to one monorepo plus eight repos
&lt;/h2&gt;

&lt;p&gt;The architecture is now hybrid, and the arc is worth telling because it answers the question every reader wants to ask: &lt;em&gt;would you do it the same way again?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why monorepo first
&lt;/h3&gt;

&lt;p&gt;Real reasons, in the order they mattered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomic cross-cutting changes.&lt;/strong&gt; One PR updates the shell, the nav, a shared component, and a feature app together. The lockfile reflects exactly what's deployed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared packages live next to consumers.&lt;/strong&gt; Refactoring a hook in the shared helpers types-checks against every micro-app in the same TS run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One ESLint, one Prettier, one Jest, one Husky.&lt;/strong&gt; A new contributor learns the conventions once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A single start script orchestrates eight dev servers&lt;/strong&gt; via &lt;code&gt;run-p&lt;/code&gt;. Onboarding is &lt;code&gt;pnpm install &amp;amp;&amp;amp; pnpm run start&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are real wins. They're also the reason the install is 12 GB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where it broke
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install cost.&lt;/strong&gt; Cold &lt;code&gt;pnpm install&lt;/code&gt; is multi-minute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build cost.&lt;/strong&gt; &lt;code&gt;build:all&lt;/code&gt; is sequential by design: shared libraries first, then their dependents, then the apps. CI runs with low concurrency. One file changed in the shared helpers rebuilds twelve packages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Devserver RAM.&lt;/strong&gt; Eight webpack dev servers in parallel is the official setup. On a 16 GB laptop, it's not sustainable once apps grow past ~20 MB each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lockfile coordination.&lt;/strong&gt; Already covered.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why new apps live in their own repos
&lt;/h3&gt;

&lt;p&gt;Apps written in the last year live in standalone repositories. They consume our shared libraries as &lt;strong&gt;npm-versioned dependencies&lt;/strong&gt;, not via the SystemJS singleton. They have their own CI, their own lockfile, their own tooling autonomy — one of them added Storybook; another added Playwright. The shell loads them via import map URLs from the runtime config endpoint.&lt;/p&gt;

&lt;p&gt;One of those repos has a webpack comment that, more than any architecture doc, explains the inflection point. Paraphrased: &lt;em&gt;we want the shared helpers to be bundled with each micro frontend rather than shared via the SystemJS import map.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That team turned off the &lt;code&gt;orgPackagesAsExternal&lt;/code&gt; setting. They explicitly chose to &lt;strong&gt;duplicate the helpers bundle into their app&lt;/strong&gt; rather than depend on the SystemJS singleton. Three benefits and one cost:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Independent upgrade clock. Helpers ships a breaking change? Doesn't matter — your bundled version is frozen.&lt;/li&gt;
&lt;li&gt;Independent CI. No monorepo lockfile thrash.&lt;/li&gt;
&lt;li&gt;Independent deploy cadence. Ship without coordinating with the platform team.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You lose access to the cross-app state&lt;/strong&gt; the singleton enabled. The Ability Zustand store, the &lt;code&gt;window.__FEATURE_FLAGS__&lt;/code&gt; bus — those are now redundantly re-implemented. We haven't hit the consequence yet. We will.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The hybrid
&lt;/h3&gt;

&lt;p&gt;In the monorepo today: the platform plumbing — shell, nav, default app, the original feature apps, plus the five shared packages. The things that &lt;em&gt;must&lt;/em&gt; change together.&lt;/p&gt;

&lt;p&gt;Out of the monorepo: every feature app added in the last year. Loaded via SystemJS import map URLs pointing to CloudFront. Gated by LaunchDarkly. Registered in the shell's routing file by adding a regex stanza.&lt;/p&gt;

&lt;p&gt;The takeaway nobody put in a slide deck:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Single-SPA didn't make monorepo-vs-multirepo a one-time decision. The import map is the seam. Anything reachable through it doesn't need to live next to the shell. We use the monorepo for the things that change together, and ship everything else from its own repo.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the rule. It took a year to figure out.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note about the maintainer
&lt;/h2&gt;

&lt;p&gt;Before the wishlist, the part of this story I didn't know when I started writing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/single-spa/single-spa/issues/1361" rel="noopener noreferrer"&gt;Single-SPA issue #1361&lt;/a&gt;, "Why does this project feel abandoned? (Part 2 — Checking in for 2026)," was opened in February 2026. The OP noted that v7.0 development had paused after September 2025, that the last core-logic merge to &lt;code&gt;main&lt;/code&gt; was late 2024, that the Slack invitation links were broken. No maintainer had replied. It is Part 2 because Part 1 also went unanswered.&lt;/p&gt;

&lt;p&gt;On 3 March 2026, &lt;a href="https://github.com/single-spa/single-spa/issues/1361#issuecomment-3991093643" rel="noopener noreferrer"&gt;a commenter in that thread&lt;/a&gt; explained why:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Single-spa's creator, Joel Denning, sadly passed away last November. This understandably may have affected the project's recent activity. Rest in peace.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Joel was the original author of single-spa. He also authored &lt;code&gt;single-spa-layout&lt;/code&gt;, the &lt;code&gt;webpack-config-single-spa-*&lt;/code&gt; presets, and &lt;code&gt;import-map-overrides&lt;/code&gt; — the four packages this entire article has been describing our use of. He carried the practical surface of micro-frontend tooling on his own, for years, and many of us — including me — built production architectures on top of his work without ever sending him a thank-you note.&lt;/p&gt;

&lt;p&gt;The corollary is unsentimental and worth saying clearly: the ecosystem doesn't have a successor. There is no v2 in the pipeline. The wishlist below is not a roadmap request — it's a description of the gaps for anyone who picks the work up, or for anyone deciding whether to start building on the framework today.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we'd ask of Single-SPA, if anyone is listening
&lt;/h2&gt;

&lt;p&gt;The list, for the record:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;First-class &lt;code&gt;exclude&lt;/code&gt; semantics on activity rules.&lt;/strong&gt; The regex dispatch in the shell's routing file exists only because there's no clean way to say "the catch-all catches everything except these other apps."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A runtime-config import map as a documented pattern.&lt;/strong&gt; We built ours in .NET. Every org with multiple micro-app teams will end up doing this. It deserves a chapter in the official docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bootstrap-ordering primitives.&lt;/strong&gt; A way to say "don't &lt;code&gt;start()&lt;/code&gt; until these N async things resolve" without rolling your own promise chain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A documented "host my shell server-side" pattern.&lt;/strong&gt; Everyone large does this. The framework should acknowledge it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A migration path for a shared library evolving alongside the apps that consume it.&lt;/strong&gt; We have two scopes for the same library and a half-broken story for which apps see which version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are real engineering problems. They are not going to be solved by waiting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;The workarounds in this article — the .NET shell, the envelope, the regex dispatch, the cross-app singleton state, the floating override overlay — aren't transitional patches anymore. They are the architecture. We were already heading toward that conclusion before March 2026; the news of Joel's passing made it final.&lt;/p&gt;

&lt;p&gt;That doesn't make the original choice wrong. Single-SPA's worldview — independent micro-apps, sharable React via import map, lifecycle hooks for mount/unmount — still pays for itself for us. We ship features independently. Teams pick their own React Query and form library. New micro-apps land in their own repos and don't touch the platform.&lt;/p&gt;

&lt;p&gt;But the gap between what the framework provides and what production needs is bigger than the framework's surface area would suggest. We filled the gap with C#, with hand-rolled regex, with a window global, with a Zustand store labelled "MINI REDUX PATTERN," with a sidebar of dev-tool comments, and with one Razor view that quietly does more work than any single page in our frontend. None of that was the framework's fault. All of it was the cost of running the framework at production scale.&lt;/p&gt;

&lt;p&gt;If I were starting over today — knowing what I now know about both the architecture and the upstream situation — I'd think harder than I did the first time. Micro-frontends still make sense for some org shapes. Single-SPA is still a coherent design. But you'd be adopting a frozen framework, building the orchestration around it yourself, and committing to maintain it indefinitely without expecting upstream help. For some teams, that's fine. For most teams asking "should we use micro-frontends?", the right answer is probably: not yet, and probably not this way.&lt;/p&gt;

&lt;p&gt;A year ago I wrote that I'd think carefully about choosing micro-frontends again. I still would. The answer might still be yes for the right project. It just isn't a casual yes anymore — and now, sadly, it can't be.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>singlespa</category>
      <category>microfrontend</category>
    </item>
    <item>
      <title>I Built a Browser UI for Claude Code — Here's Why</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Mon, 16 Mar 2026 08:15:44 +0000</pubDate>
      <link>https://dev.to/hamed_farag/i-built-a-browser-ui-for-claude-code-heres-why-4959</link>
      <guid>https://dev.to/hamed_farag/i-built-a-browser-ui-for-claude-code-heres-why-4959</guid>
      <description>&lt;p&gt;I started using Claude Code a few months ago. Terminal-first, no nonsense, incredibly powerful. But after weeks of juggling sessions, losing track of costs, and wishing I could approve tool calls from my phone while grabbing coffee — I started building something for myself.&lt;/p&gt;

&lt;p&gt;That something became &lt;strong&gt;Claudeck&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It started on March 1st as a quick experiment I called "shawkat-ai" — a simple WebSocket bridge between my browser and the Claude Code SDK so I could chat without squinting at terminal output. Then I added cost tracking because I wanted to know where my money was going. Then session persistence. Then workflows. Then agents. Then a plugin system. Then Telegram integration. Then autonomous agent DAGs.&lt;/p&gt;

&lt;p&gt;Two weeks later — yes, two weeks — it was a full-featured browser UI with 50+ features, renamed to Claudeck, published on npm, and somehow competing with tools backed by YC and teams of engineers. 55 commits in 15 days, each one adding a major feature.&lt;/p&gt;

&lt;p&gt;This is the story of why I built it, what makes it different, and why you might want to try it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Claude Code in the Terminal
&lt;/h2&gt;

&lt;p&gt;Don't get me wrong — Claude Code in the terminal is excellent. It's fast, it's powerful, and it gets out of your way. But there are real friction points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't see the big picture.&lt;/strong&gt; How much have you spent today? This week? Which sessions burned the most tokens? The terminal doesn't tell you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context switching is painful.&lt;/strong&gt; You're mid-conversation, need to check something in another session, and now you've lost your place. No tabs, no background sessions, no parallel conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can't walk away.&lt;/strong&gt; Claude asks for permission to run a bash command. You're making coffee. The session just... waits. Anthropic recently shipped &lt;a href="https://code.claude.com/docs/en/changelog" rel="noopener noreferrer"&gt;Remote Control&lt;/a&gt; — scan a QR code and approve from your phone via claude.ai. It's a step forward, but it's Max-only ($100–$200/mo), requires your terminal to stay open, and gives you approval control without the broader context — no cost tracking, no session management, no workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No visual tools.&lt;/strong&gt; File diffs are raw text. There's no file explorer. No git panel. No way to drag a file into the conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No workflows.&lt;/strong&gt; Every PR review starts with the same three prompts. Every repo onboarding follows the same pattern. But you type them out fresh each time.&lt;/p&gt;

&lt;p&gt;I kept a mental list of these annoyances. On March 1st, 2026, I decided to fix them. What I thought would be a weekend project turned into a two-week sprint that I couldn't stop.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Claudeck?
&lt;/h2&gt;

&lt;p&gt;Claudeck is a browser-based UI for Claude Code. One command to launch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx claudeck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It connects to the official Claude Code SDK running on your machine. Your API key, your local files, your git repos — nothing goes through a third-party server. It's a local web app that gives Claude Code a proper interface.&lt;/p&gt;

&lt;p&gt;Think of it as what VS Code is to vim — the same power, but with a visual layer that makes certain things dramatically easier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfsr3hj1xh0kse69hz05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyfsr3hj1xh0kse69hz05.png" alt="Claudeck Home — AI Activity heatmap, cost analytics, and project dashboard" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d1y8i60vujw7csr0j97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d1y8i60vujw7csr0j97.png" alt="Claudeck Chat — Real-time streaming with session sidebar, Whaly mascot, and status bar" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Landscape: Why Not Use Something Else?
&lt;/h2&gt;

&lt;p&gt;When I started building on March 1st, I wasn't thinking about alternatives. By the time I looked up two weeks later with a fully shipped product, there were at least a dozen. Here's the honest picture:&lt;/p&gt;

&lt;h3&gt;
  
  
  Opcode (20K+ stars, YC-backed)
&lt;/h3&gt;

&lt;p&gt;A polished desktop app built with React and Tauri. Great session management, usage analytics, and custom agent creation. But it's &lt;strong&gt;desktop-only&lt;/strong&gt; — no mobile, no PWA, no browser access. And it requires installing a native app.&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudCLI (7.9K stars)
&lt;/h3&gt;

&lt;p&gt;The multi-CLI Swiss Army knife. Supports Claude Code, Cursor CLI, Codex, and Gemini CLI. Has a file explorer and git integration. But &lt;strong&gt;no cost dashboard&lt;/strong&gt;, no workflows, no prompt templates, and no parallel chat mode.&lt;/p&gt;

&lt;h3&gt;
  
  
  CodePilot (3.1K stars)
&lt;/h3&gt;

&lt;p&gt;Electron + Next.js desktop app with model switching and permission controls. Solid, but again — &lt;strong&gt;desktop-only&lt;/strong&gt;, no workflows, no cost analytics, no prompt templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anthropic's Remote Control
&lt;/h3&gt;

&lt;p&gt;Anthropic's own answer: run &lt;code&gt;claude remote-control&lt;/code&gt;, scan a QR code, control from your phone via claude.ai/code. But it's &lt;strong&gt;Max-only&lt;/strong&gt; ($100–$200/mo), the terminal must stay open, and there's no file explorer, no analytics, no multi-session management.&lt;/p&gt;

&lt;h3&gt;
  
  
  So why Claudeck?
&lt;/h3&gt;

&lt;p&gt;Because none of them scratched every itch. I wanted:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Browser-based&lt;/strong&gt; — open a tab, start working. No Electron, no Tauri, no native install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost visibility&lt;/strong&gt; — know exactly what I'm spending, per session, per day, per project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflows and templates&lt;/strong&gt; — stop retyping the same prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent orchestration&lt;/strong&gt; — not just one agent, but chains, DAGs, and an auto-orchestrator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AFK approval&lt;/strong&gt; — approve tool calls from my phone via Telegram while away from my desk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero bloat&lt;/strong&gt; — vanilla JS, 6 npm dependencies, no build step.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No existing tool offered all of these. So I built it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Features That Matter
&lt;/h2&gt;

&lt;p&gt;I'm not going to list all 50+ features. Here are the ones that changed how I work:&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallel Mode (2x2 Grid)
&lt;/h3&gt;

&lt;p&gt;Four independent Claude conversations running simultaneously in a grid layout. I use this constantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pane 1: refactoring a module&lt;/li&gt;
&lt;li&gt;Pane 2: writing tests for it&lt;/li&gt;
&lt;li&gt;Pane 3: reviewing a PR&lt;/li&gt;
&lt;li&gt;Pane 4: exploring documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each pane has its own session, its own context, its own streaming output. No competitor has this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cost Dashboard
&lt;/h3&gt;

&lt;p&gt;A full analytics dashboard with daily cost charts, per-session breakdowns, input/output token counts, and error pattern analysis. I can see at a glance that Tuesday's refactoring session cost $4.20 across 47 turns, and that 30% of my errors are "File Not Found."&lt;/p&gt;

&lt;p&gt;This is the feature that convinced me to make Claudeck public. Every Claude Code user deserves to know where their money goes.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Workflows
&lt;/h3&gt;

&lt;p&gt;Pre-built multi-step pipelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Review PR&lt;/strong&gt; — analyze diff, identify issues, suggest improvements (3 steps, context carries forward)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboard Repo&lt;/strong&gt; — map structure, explain architecture, generate dev guide&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration Plan&lt;/strong&gt; — audit dependencies, assess impact, create plan&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Health&lt;/strong&gt; — identify tech debt, suggest improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can create your own workflows with full CRUD. Each step carries context from the previous one, so Claude builds on its own analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Autonomous Agents
&lt;/h3&gt;

&lt;p&gt;Four built-in agents (PR Reviewer, Bug Hunter, Test Writer, Refactoring) that run as high-turn autonomous sessions. But the real power is in composition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent Chains&lt;/strong&gt; — sequential pipelines: Bug Hunter finds issues, then PR Reviewer analyzes the fixes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent DAGs&lt;/strong&gt; — visual dependency graphs: Bug Hunter and Test Writer run in parallel, then PR Reviewer synthesizes both&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestrator&lt;/strong&gt; — describe a task in plain language, and it auto-decomposes into specialist agent calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built a full visual DAG editor with an SVG canvas where you drag agents and draw connections. It feels like a simplified version of a CI/CD pipeline builder, but for AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Telegram Integration (Two-Way)
&lt;/h3&gt;

&lt;p&gt;This is the one people don't expect. Configure a Telegram bot, and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Outbound&lt;/strong&gt;: Every session completion, agent run, workflow step, and error sends a rich notification to your phone with metrics (cost, tokens, duration).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inbound&lt;/strong&gt;: When Claude needs permission to run a tool, you get an inline keyboard on Telegram with Approve/Deny buttons. Approve from your phone, and the web UI modal auto-dismisses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built this because I run long agent sessions and walk away. Now I approve bash commands from my couch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Templates with Variables
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Code Review"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Review {{file_path}} for {{concern}}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Click the template, fill in the form, send. Sixteen built-in templates, plus it auto-discovers &lt;code&gt;.claude/commands/&lt;/code&gt; and &lt;code&gt;.claude/skills/&lt;/code&gt; from your project directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  File Explorer, Git Panel, and Code Diffs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lazy-loaded file tree with syntax-highlighted preview&lt;/li&gt;
&lt;li&gt;Git panel with branch switching, staging, commit, and log&lt;/li&gt;
&lt;li&gt;LCS-based code diff viewer with green/red line highlighting for Edit and Write tool outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't groundbreaking individually, but having them integrated into the same interface where you're chatting with Claude eliminates constant context switching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugin System
&lt;/h3&gt;

&lt;p&gt;Full-stack plugin architecture. Drop files in &lt;code&gt;~/.claudeck/plugins/my-plugin/&lt;/code&gt; with a &lt;code&gt;client.js&lt;/code&gt; and optionally a &lt;code&gt;server.js&lt;/code&gt;, and it appears in the marketplace. Built-in plugins include Linear integration, a todo list with brag tracking, and even a couple of games for when you're waiting on a long agent run.&lt;/p&gt;

&lt;p&gt;The best part? You can &lt;strong&gt;extend Claudeck using Claude Code itself&lt;/strong&gt;. I published a &lt;a href="https://github.com/hamedafarag/claudeck-skills" rel="noopener noreferrer"&gt;Claude Code skill&lt;/a&gt; that lets you scaffold new plugins with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the skill (one-time)&lt;/span&gt;
npx skills add https://github.com/hamedafarag/claudeck-skills

&lt;span class="c"&gt;# Then in Claude Code, just describe what you want:&lt;/span&gt;
/claudeck-plugin-create my-widget A dashboard showing system metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude generates the full plugin — &lt;code&gt;client.js&lt;/code&gt;, &lt;code&gt;client.css&lt;/code&gt;, and optionally &lt;code&gt;server.js&lt;/code&gt; with Express routes — directly into &lt;code&gt;~/.claudeck/plugins/&lt;/code&gt;. Refresh the page and your plugin is live in the marketplace. No fork needed, no build step, no PR. You describe it, Claude builds it, Claudeck loads it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Technical Philosophy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Zero Framework, Six Dependencies
&lt;/h3&gt;

&lt;p&gt;Claudeck's frontend is vanilla JavaScript ES modules. No React. No Vue. No Svelte. No bundler. No build step.&lt;/p&gt;

&lt;p&gt;The entire backend runs on Express, WebSocket (ws), better-sqlite3, web-push, dotenv, and the Claude Code SDK. That's it. Six npm dependencies.&lt;/p&gt;

&lt;p&gt;Why? Because I wanted to iterate fast. No waiting for builds. No fighting with framework upgrade cycles. No 200MB &lt;code&gt;node_modules&lt;/code&gt;. Change a file, refresh the browser.&lt;/p&gt;

&lt;p&gt;This choice is a big reason the entire project went from zero to 50+ features in 15 days. When you're building something for yourself, every minute spent on tooling is a minute not spent on features. Vanilla JS with ES modules and CSS custom properties is surprisingly productive when you're not fighting abstractions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everything is Local
&lt;/h3&gt;

&lt;p&gt;No cloud. No accounts. No telemetry. Your data lives in &lt;code&gt;~/.claudeck/&lt;/code&gt; — a SQLite database, some JSON config files, and your plugins. Delete the directory and it's gone.&lt;/p&gt;

&lt;p&gt;This was non-negotiable for me. I'm sending code to Claude — I'm not also sending my usage patterns to a third party.&lt;/p&gt;

&lt;h3&gt;
  
  
  PWA with Offline Fallback
&lt;/h3&gt;

&lt;p&gt;Install it as a PWA from Chrome's address bar. It runs in a standalone window, supports push notifications (even when the browser is closed), and has an offline fallback page. On mobile, it's fully responsive with tablet and phone breakpoints.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Claudeck Doesn't Do
&lt;/h2&gt;

&lt;p&gt;Honesty matters. Here's where alternatives beat Claudeck:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No authentication&lt;/strong&gt; — anyone on your local network can access it. This is the biggest gap and the next thing I'm building.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No multi-CLI support&lt;/strong&gt; — CloudCLI supports Claude Code, Cursor CLI, Codex, and Gemini CLI. Claudeck is Claude Code only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No desktop app&lt;/strong&gt; — if you want a native macOS/Windows experience, Opcode and CodePilot are better choices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No live file editing&lt;/strong&gt; — CloudCLI lets you edit files directly in the UI. Claudeck shows file previews but doesn't have an editor (that's what your IDE is for).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Who is Claudeck For?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Solo developers&lt;/strong&gt; who use Claude Code daily and want visibility into costs, reusable workflows, and a visual interface without leaving the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developers who work AFK&lt;/strong&gt; — the Telegram integration means you can kick off a long agent run, walk away, and approve tool calls from your phone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power users&lt;/strong&gt; who want parallel conversations, agent pipelines, and prompt templates — features that the terminal simply can't offer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Teams evaluating Claude Code&lt;/strong&gt; who need cost analytics to justify the spend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx claudeck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command. No install. Opens in your browser. Your first session is free (well, you're paying Anthropic — Claudeck itself is free and open source).&lt;/p&gt;

&lt;p&gt;The source is on GitHub: &lt;a href="https://github.com/hamedafarag/claudeck" rel="noopener noreferrer"&gt;github.com/hamedafarag/claudeck&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, star the repo. If you build a plugin, let me know. If you find a bug — definitely let me know.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>opensource</category>
      <category>devex</category>
    </item>
    <item>
      <title>The File Structure Dilemma</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Mon, 29 Jan 2024 15:56:26 +0000</pubDate>
      <link>https://dev.to/hamed_farag/the-file-structure-dilemma-4f63</link>
      <guid>https://dev.to/hamed_farag/the-file-structure-dilemma-4f63</guid>
      <description>&lt;h2&gt;
  
  
  Introduction and A Fact
&lt;/h2&gt;

&lt;p&gt;In this discussion, we'll delve into file structure within the realm of frontend development, with a particular focus on React. React, at its core, is a library, not a framework. It primarily operates within the view layer, enabling its integration into applications like Angular for managing the UI. This integration involves referencing React through CDNs and creating components in JavaScript or JSX, which are then incorporated into Angular seamlessly.&lt;/p&gt;

&lt;p&gt;React, distinct from Angular (specifically Angular version 1), doesn't adhere to the traditional Model-View-Controller (MVC) pattern. While Angular incorporates elements of MVC, React positions itself solely as a view layer library. This unique stance brings with it distinct concepts and approaches.&lt;/p&gt;

&lt;p&gt;Given React's nature as a library, setting up a project involves careful planning and selection of additional libraries to supplement its capabilities. Tasks such as routing require specific libraries like React Router DOM. For state management, developers might opt for external libraries. The necessity to explore the React ecosystem for libraries catering to basic requirements is a fundamental aspect of working with React.&lt;/p&gt;

&lt;p&gt;Ultimately, React doesn't function in isolation for production-grade projects. It necessitates a combination of complementary libraries to form a complete framework. The React documentation even suggests pairing with tools like Vite or NextJS. The essence of React lies in its coexistence with its ecosystem, proving that React alone isn't sufficient for building substantial projects.&lt;/p&gt;

&lt;p&gt;The crux of the matter lies in determining the optimal file structure. Decisions regarding the hierarchical arrangement of files and their interrelationships require strategic planning from the outset, influenced by various factors. This article explores potential file organization strategies for your project, helping you make informed decisions about structuring your files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Determining File Structure Factors
&lt;/h2&gt;

&lt;p&gt;When deciding on your file structure for a project, several key factors come into play. The primary consideration is the project's size. This could range from a small, personal project to a complex one with multiple modules and numerous pages.&lt;/p&gt;

&lt;p&gt;The second crucial factor is the team size working on the project. It could be a solo endeavor, a small team of two to five members, or larger groups divided into multiple teams. The team size significantly influences how the file structure should be organized, as larger teams require more systematic and clear file structures to ensure efficient collaboration.&lt;/p&gt;

&lt;p&gt;It's important to note that there is no universally prescribed method for naming and organizing files. The approach can vary, often involving common folder names like 'components', 'hooks', 'pages', 'styles', and 'UI', among others.&lt;/p&gt;

&lt;p&gt;In summary, the structure of your files will largely depend on the project's scale and the team's size. It could range from a simple setup with just a few folders to a complex structure dividing the project into sub-projects or micro-frontends for larger-scale applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step by Step Approach
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic File Structure
&lt;/h3&gt;

&lt;p&gt;In the simplest form, such as those generated by boilerplates or CLI tools like create-react-app, Vite, or Next.js without using templates, the structure typically includes an entry point and a 'components' folder. This basic setup offers a foundational framework which can be expanded as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detailed Components Folder
&lt;/h3&gt;

&lt;p&gt;The 'components' folder can be subdivided into two main categories:&lt;/p&gt;

&lt;p&gt;UI Components: This folder, possibly named 'ui', would contain stateless UI components like buttons, tabs, and accordions. These components may have internal states but don't rely on external states, functioning primarily through props.&lt;/p&gt;

&lt;p&gt;Logic or Business Components: The other subdivision, possibly named 'business' or 'logic', would house components that are more complex and intertwined with the application's logic or business aspects. An example would be a user card component with detailed information like avatar, name, email, and job description. These components might also interact with APIs and are reused across different parts of the project.&lt;/p&gt;

&lt;p&gt;The categorization of components into 'ui' or 'logic/business' depends on their complexity and functionality. A UI-focused component like a simple button would fit into the 'ui' category, whereas a component involving more complex logic and data interaction would be more suited for the 'logic/business' category.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkltaevlgag6a1qsjmn2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkltaevlgag6a1qsjmn2j.png" alt="Components Folder" width="674" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hooks!
&lt;/h3&gt;

&lt;p&gt;Alongside the 'components' folder within the source directory, another essential folder named "hooks" can be established. This folder is particularly relevant in React development, as it houses custom hooks. Ideally, these hooks should be universally applicable across the entire project. However, if a hook is intrinsically linked to a specific module, page, or substantial entity, it can be placed within that respective context. This flexibility underlines the absence of a rigid structure; adaptability is key, but with careful management to prevent disarray in the project.&lt;/p&gt;

&lt;p&gt;The 'hooks' folder typically contains various custom hooks, each serving a distinct purpose. A common and highly useful example is the 'useClickOutside' hook. This hook is designed to detect clicks outside of a component, enabling specific actions in response. For instance, in a custom dropdown menu, this hook helps in automatically closing the menu when a click is detected outside its boundaries. The implementation of this hook may vary, but its function is clear from its name: it reacts to external clicks to close or modify elements accordingly. Such a custom hook, like 'useClickOutside', would be located within the 'hooks' folder, readily accessible for integration into components like dropdowns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organizing Styles
&lt;/h3&gt;

&lt;p&gt;In our exploration of file organization within a React project, a crucial aspect to address is the 'styles' folder. This area, often vast and multifaceted, requires careful division. In my experience, particularly with projects utilizing SASS, the approach to organizing styles is twofold.&lt;/p&gt;

&lt;p&gt;Firstly, there are global or shared styles that transcend individual components. These include mixins, functions, and overrides for third-party tools. Such styles don't belong to any single component but rather need a broader scope, hence the creation of a dedicated 'styles' folder. This higher-level repository ensures that overarching styles have a proper place within the project structure.&lt;/p&gt;

&lt;p&gt;Working with SASS, I prefer adhering to the 7-1 SASS pattern, which effectively segments the 'styles' folder into seven sub-folders: 'base', 'components', 'pages', 'layout', 'vendors', 'utils', and 'themes'. This structured approach to managing styles is not just about segregating files arbitrarily; it follows a deliberate pattern to enhance organization and maintainability. This systematic arrangement allows any new team member to quickly grasp the structure and logic behind the style organization.&lt;/p&gt;

&lt;p&gt;Regarding component-specific styles, the component architecture approach recommends a slightly different strategy. When a component has its own unique styles, and you're working with SASS, CSS, or LESS, it's advisable to place the style file directly adjacent to the component's logic file. For instance, a 'Button' component would have a corresponding folder named 'Button', containing two files: one with the React logic and the other with its associated styles. This methodology ensures that component-level styles are tightly coupled with their respective components, fostering a more modular and intuitive structure.&lt;/p&gt;

&lt;p&gt;Overall, whether dealing with project-level styles in the 'styles' folder or component-specific styles alongside their logic files, the key is to establish a logical, documented structure. This approach not only aids in current project maintenance but also ensures that future contributors can easily understand, navigate, and extend the project's styling architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F932spxor2wklwdabt1rh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F932spxor2wklwdabt1rh.png" alt="Hooks and Styles Folders" width="666" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Average File Structure
&lt;/h3&gt;

&lt;p&gt;In the realm of project organization, particularly for moderate-sized projects, there's a common practice of having a 'pages' folder. This folder is structured such that each subfolder represents a distinct page of the application, like the home page, about us page, contact us page, and so on. Each page is appropriately named and nested within the 'pages' folder, ensuring an organized and intuitive layout for the project's various pages.&lt;/p&gt;

&lt;p&gt;Additionally, these pages often share a common layout, leading to the necessity of a 'layouts' folder. Positioned alongside the 'pages' folder, 'layouts' contains the shared layout templates used across different pages. For instance, a typical layout might include a header, footer, and a central content area. When a new page is created in a React-based project, it is composed with this main layout, incorporating the header and footer by default. The content area is what each specific page uniquely provides. Therefore, the introduction of a 'layouts' folder complements the 'pages' folder, streamlining the structure and design of each page.&lt;/p&gt;

&lt;p&gt;Furthermore, some project structures distinguish between 'components' and 'containers'. This distinction harks back to the early days of React, where the concept of 'dumb' (stateless) components and 'smart' (stateful) components, or containers, was prevalent. In this context, a 'container' is typically a stateful component that represents a page or a significant part of it. This approach sees the 'container' as a large component comprising several smaller, stateless components, possibly including shared state elements. The choice between using a 'containers' folder versus a 'pages' folder varies among developers, but ultimately, both serve to organize larger, more complex components within the project.&lt;/p&gt;

&lt;p&gt;In summary, the choice of folders like 'components', 'layouts', and 'containers' or 'pages' reflects different schools of thought in project organization. Each serves a specific purpose: 'pages' for individual pages, 'layouts' for shared design elements across pages, and 'containers' or 'components' for managing stateful and stateless elements respectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba3o9b1qnlyh8th9ulyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba3o9b1qnlyh8th9ulyh.png" alt="Pages, Containers and Layous" width="666" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature-First (Module-First) File Structure
&lt;/h3&gt;

&lt;p&gt;As a project expands, its structure often evolves to accommodate larger and more complex components, leading us to consider concepts like 'modules' and 'features'. In a structure often referred to as 'feature-first' or 'module-first', these two terms are essentially interchangeable. This approach significantly alters the traditional organization of folders such as components, styles, and hooks, which are now shared across various features or modules.&lt;/p&gt;

&lt;p&gt;For instance, a universally used UI component, like a 'Button', would reside in a shared, accessible location outside specific modules. With the introduction of this 'feature-first' or 'module-first' approach, the existence of a separate 'pages' folder becomes redundant. This is because modules or features, as newly introduced entities, are more comprehensive and encompass aspects like pages.&lt;/p&gt;

&lt;p&gt;To illustrate, let's take a module named 'CRM' (Customer Relationship Management), representing a business feature in a project. This module isn't just a single element; it's akin to a mini-project within the larger project. It includes multiple pages, reusable components specific to CRM, and its unique business and workflow processes.&lt;/p&gt;

&lt;p&gt;When delving into a module like CRM, you'll discover a structure mirroring the main project source folder. Inside, there are subfolders named 'components', 'hooks', 'layouts', 'pages', and 'styles', all specific to the CRM module. Additionally, there's a central file, such as 'index.js', 'crm.js', 'jsx', or 'tsx' (depending on the programming language), serving as the module's entry point. Alongside this, a 'routes' file details the internal routes of the CRM module. Each module manages its own routing, reflecting its specific functionalities.&lt;/p&gt;

&lt;p&gt;This 'module-first' or 'feature-first' structure effectively creates a self-contained ecosystem within each module, ensuring that every aspect of a module, from components to styles, is organized and easily navigable. This approach is particularly beneficial for large-scale projects, where clear segregation and modularization of features or business areas are essential for maintainability and scalability.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At times, it's practical to blend the 'feature-first' or 'module-first' approach with the use of 'containers' or 'pages'. This is particularly relevant when dealing with shared pages that are universally applicable across all modules or features. For instance, a 404 error page is a common requirement that doesn't warrant individual versions for each module or feature. It's more sensible to place such universal pages at the top level of the project structure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwlxlbjrztbp2wj7ourd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhwlxlbjrztbp2wj7ourd.png" alt="Feature-First" width="345" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Essential Folders
&lt;/h2&gt;

&lt;p&gt;In the projects I develop, I typically consider incorporating several essential folders, each serving a distinct purpose in building a robust file structure. These folders are integral to answering common structural questions, like where to place utility functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;helpers&lt;/strong&gt;: This folder contains core helper functions used throughout the project. Examples include "httpClient", "XHRResolver", "Logger", etc., which provide fundamental support across various components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;utils&lt;/strong&gt;: Here, I place small, pure functions that perform specific tasks. Functions like "convertHexToRGBA" and "buildQueryString" are examples of utility functions that handle precise operations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;data &amp;amp; services along with transformers&lt;/strong&gt;: This setup aligns with the three-tier architecture principle, with transformers adding an extra layer for modifying or reshaping payload or response data. It's a structured way to manage data processing and service interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;types or interfaces&lt;/strong&gt;: This folder is dedicated to storing types and interfaces, crucial for ensuring type safety and clear contract definitions within the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;configs&lt;/strong&gt;: For static configurations used throughout the project, such as default values for certain variables or a default date format, this folder is the designated place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;enums&lt;/strong&gt;: I use the enums folder to store enumeration types, which helps in defining a set of named constants, improving the readability and maintainability of the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;translations&lt;/strong&gt;: If the project supports multiple languages, this folder contains the translation files necessary for internationalization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These folder names and their usage can be adapted as needed. Depending on the specific requirements and scale of your project, you might choose to use all of these folders or only a selection. The flexibility to modify and tailor these folders to your project's needs is a key aspect of this structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rare (Extrem) File Structure
&lt;/h2&gt;

&lt;p&gt;The most complex file structure I'll discuss is for exceptionally large projects, often managed by multiple teams, each focusing on a distinct business segment. This setup is known as a micro front-end architecture.&lt;/p&gt;

&lt;p&gt;Previously, I wrote an article about &lt;a href="https://www.hamedfarag.dev/posts/one-year-microfontend" rel="noopener noreferrer"&gt;Micro-Frontend&lt;/a&gt;, explaining that this concept involves different teams handling separate parts of a product, from the front-end to the database. These distinct segments are then integrated under a container or shell to form a cohesive application. In the context of front-end development, each team might adopt different file structures, such as a focus on pages and layouts or adopting a feature-first or module-first approach. The choice of structure depends on the project's scale and the specific business area each team is responsible for.&lt;/p&gt;

&lt;p&gt;Another scenario I covered in previous article involves managing a large project through a monorepo, which presents its unique file structure challenges. In a monorepo setup, there's typically a root folder named 'packages'. Within 'packages', you find various subfolders for different segments like 'helpers', 'utilities', 'CRM', 'project management', 'UI', and 'components'. The division of these packages is flexible, depending on the project's needs, and each package essentially functions as a standalone project. For example, expanding the 'CRM' folder under 'packages' reveals a complete project setup, with its components, hooks, styles, and other elements. If extracted from the monorepo, it should be able to operate independently.&lt;/p&gt;

&lt;p&gt;In some cases, a monorepo might not be structured as a micro front-end but simply as a collection of packages. These packages could include reusable components, shared styles, or distinct projects. Each package, while conforming to the overarching monorepo structure, follows its internal organization. This could range from a basic setup with components and containers to more elaborate structures incorporating features or modules. For instance, a package named 'project management' might contain a 'features' folder, managing all aspects related to project management within that package.&lt;/p&gt;

&lt;p&gt;In summary, the file structure in a micro front-end or a monorepo is multifaceted, catering to the complexity and scale of large projects. Each package or segment within this setup is organized in a way that allows it to function both as part of the larger whole and as an independent entity, ensuring modularity and flexibility in the project's architecture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcx66aokxvfrmd9fefqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frcx66aokxvfrmd9fefqo.png" alt="Packages" width="624" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Outro
&lt;/h2&gt;

&lt;p&gt;There is no universally accepted school of thought or definitive catalog dictating file structure in project development. Instead, the organization of files is largely influenced by factors such as the size and scope of the team, the business objectives, and the project's anticipated lifespan. This variability underscores the importance of collaboration between the front-end lead or senior front-end developers and the business and architectural teams. Such engagement is crucial for understanding the project's vision, pipeline, and end goals, which could range from a few months to several years.&lt;/p&gt;

&lt;p&gt;The involvement of the front-end team from the outset is essential. It allows them to align their approach with the broader objectives, influencing key aspects like the file structure. Foreknowledge of the project's trajectory – whether it's adding features over four years or just one – is vital for designing a scalable and adaptable structure from day one. However, it's important to recognize that no structure is permanent. Flexibility and periodic adjustments are necessary, though frequent overhauls should be avoided to prevent disruptions.&lt;/p&gt;

&lt;p&gt;The goal is to establish a file structure that is robust enough to last for several years, anticipating significant feature expansions. This proactive approach is preferable to a reactive one, where the structure becomes cumbersome and intertwined, necessitating major restructuring. As the project evolves, various factors, such as performance enhancements, team expansion, or shifting business requirements, may necessitate revisiting and modifying the file structure.&lt;/p&gt;

&lt;p&gt;It's crucial to understand that a file structure is not static. It evolves, potentially changing every six months or even every three months, based on numerous variables: team dynamics, business goals, feature complexity, and team expansion. These factors dictate how the file structure should be adapted or divided to create a conducive environment for efficient work and future extensions.&lt;/p&gt;

&lt;p&gt;In summary, while there is no one-size-fits-all approach to file structuring in project development, the key lies in maintaining a balance between flexibility and foresight. The structure should be adaptable to accommodate changes yet thoughtfully planned to sustain the project's growth and evolution over time.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>react</category>
      <category>structure</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture - Summary</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Sat, 23 Sep 2023 11:42:07 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-summary-3nn1</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-summary-3nn1</guid>
      <description>&lt;h2&gt;
  
  
  What is Frontend Architecture after all this?
&lt;/h2&gt;

&lt;p&gt;Frontend architecture refers to the structure and organization of the client-side part of a web application and converting the architectural drivers into a technical solution, technical roadmap, communicating the vision to a number of stakeholders both inside and outside the software development team, and introducing the technical leadership.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the difference between Architecture and design?
&lt;/h2&gt;

&lt;p&gt;"Architecture" typically refers to the high-level structural decisions that have a significant impact on the system and are difficult to change once made. On the other hand, "design" encompasses the detailed decisions and implementations that are more flexible and can be adjusted without major consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the Architectural Drivers?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Functional Requirements&lt;/strong&gt;: The technical functions that represent the main product features. These functions describe how the system behaves and what it should do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality Attributes&lt;/strong&gt;: Quality Attributes are a set of criteria that describe how a software system should behave and perform rather than specifying specific functionalities or features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints&lt;/strong&gt;: Constraints can encompass various factors, such as technical limitations, resource constraints, or environmental considerations. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principles&lt;/strong&gt;: The Standards or the Guidelines that should be applied while implementing and creating the Frontend solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Book: &lt;strong&gt;Software Architecture for Developers&lt;/strong&gt; by &lt;a class="mentioned-user" href="https://dev.to/simonbrown"&gt;@simonbrown&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Book: &lt;strong&gt;Frontend Architecture for Design System&lt;/strong&gt; by Micah Godbolt&lt;/li&gt;
&lt;li&gt;Youtube: GOTO Conferences&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 6)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Sat, 23 Sep 2023 08:42:04 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-6-ae0</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-6-ae0</guid>
      <description>&lt;h1&gt;
  
  
  4. Principles
&lt;/h1&gt;

&lt;p&gt;Okay, each one of us wants to establish a standard or utilize a pre-existing one to ensure consistency in the frontend solution. This standard should also facilitate a quick onboarding process for new team members, enabling them to understand it quickly.&lt;/p&gt;

&lt;p&gt;Creating standards and principles for your development team is a crucial step in ensuring consistency and efficiency in your projects. We have two pillars, development, and architecture, let's explore how we can build standards around each of them:&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Principles
&lt;/h2&gt;

&lt;p&gt;The principle that many frontend engineers instantly think of relates to the way in which software should be developed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Coding Guidelines&lt;/strong&gt;: Establish clear coding conventions and style guides for your team. This includes naming conventions, code formatting, and commenting standards. Tools like ESLint and Prettier can help enforce these guidelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Style Guidelines&lt;/strong&gt;: The method by which your team approaches styling can encompass CSS, involve a pre-processor language, incorporate CSS-in-JS, or make use of a utility-first CSS library. Depending on your choice, it is imperative to carefully select the appropriate methodology, design an effective file structure, and determine whether to utilize existing reusable styles or craft a customized solution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document your work&lt;/strong&gt;: How to document your work to communicate it to your teammates. You will create reusable components. helpers, utils, write comments for the complex parts, etc. All these parts you should care about documenting them in a proper way using basic documentation files and comments or using a powerful documentation tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging and Monitoring&lt;/strong&gt;: How will you monitor your application to measure performance and to monitor for production bugs?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: Define testing standards, including unit tests, integration tests, and end-to-end tests. Decide on testing frameworks and coverage targets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;: Define a version control strategy using Git. Set rules for branching, committing, and merging code. Consider using a branching model like Gitflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Reviews&lt;/strong&gt;: Implement a process for peer code reviews to catch issues early and maintain code quality. Specify who should review the code and the criteria for approval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JS &amp;amp; UI Frameworks&lt;/strong&gt;: Which JavaScrip Framework you will use in your next project, would you like to use a ready-made UI framework, you have options and you have to choose one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD&lt;/strong&gt;: Establish automated build and deployment pipelines to ensure code is consistently built, tested, and deployed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsiveness&lt;/strong&gt;: Your application will be mobile-first or desktop-first? it will be better if you know this information from day one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: You should care about Semantic HTML and ARIA attributes from day one. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSR, SSR, SSG&lt;/strong&gt;: Considering the specific requirements of your project, you should decide whether to opt for Client-Side Rendering (CSR) or if there is a need to prioritize Search Engine Optimization (SEO), in which case Server-Side Rendering (SSR) or Static Site Generation (SSG) would be more suitable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Languages&lt;/strong&gt;: Should your project support more than one language? Make sure you do not write static 
content directly into the code or into the HTML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design System&lt;/strong&gt;: Do you have a centralized location for reusable components, guidelines, and well-defined standards? Having this is crucial for constructing a clean application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs&lt;/strong&gt;: One of the critical aspects to consider is establishing a robust foundation for consuming backend APIs in a standardized and efficient manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management&lt;/strong&gt;: Do we truly need to adopt a state management library and use it in general, or is it necessary only to use it for sharing specific pieces of data? Determining whether to use it or not is a crucial decision.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default Configuration&lt;/strong&gt;: It's advisable to centralize all default and shared values and configurations; otherwise, it can become chaotic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Principles
&lt;/h2&gt;

&lt;p&gt;There are also some principles that relate to how the frontend should be structured. For example&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Main Architecture (Micro-frontend vs. Monolithic)&lt;/strong&gt;: When comparing monolithic frontends and micro-frontends, there are several factors to consider. Scalability and modularity are critical for large projects, and micro-frontends are better suited for these types of projects. However, monolithic front ends are more uncomplicated and more straightforward to develop and maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MVC vs. CBA&lt;/strong&gt;: When React was published to the public in 2013, it came with the CBA (Component-Based Architecture), CBA is an approach where you build an application by creating self-contained and reusable components, with each component encapsulating its logic and UI. MVC (Model-View-Controller) is an architectural pattern where you separate an application into three main components: Model (data and logic), View (user interface), and Controller (handles user input and updates Model and View).
You can go with one of them based on your chosen framework or even you can combine them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo Type: Polyrepo vs. Monorepo&lt;/strong&gt;: Polyrepo architecture is a software development approach in which each project or component is housed in its own individual repository. This stands in contrast to Monorepo architecture, where all the source code for a project or a group of related projects resides within a single repository. Your choice between these approaches should be determined by factors such as the size of your frontend project, your business requirements, team size, deployment processes, and the need to share code. Each approach has its own set of advantages and disadvantages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layering Strategy&lt;/strong&gt;: One of the most popular architectural patterns worth discussing is the Three-tier architecture. This architecture is a design pattern that separates applications into UI layers (client layers), application layers, and database layers. Each layer has a specific responsibility and communicates with the other layers through well-defined interfaces. This is the definition, but usually, I tweak this pattern and use it in a little different way:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database Layer (Data Layer)&lt;/strong&gt;: This layer is responsible for making API calls using promise-based HTTP Clients like Axios or Fetch. Regardless of the approach you choose, this is the sole location for API calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Layer (Service Layer)&lt;/strong&gt;: After creating the function responsible for fetching data in the Data Layer, you should invoke this function in the Service Layer to either receive or send data. In this layer, you may execute business logic, modify the data's structure before sending or after receiving it using Transformer functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transformer Layer (Normalization or Mapping Layer)&lt;/strong&gt;: This is an optional layer that contains functions responsible for altering the data's structure. For example, you can use this layer to change date formats, adjust property names in received objects, or reshape the data you intend to send to the data layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Layer&lt;/strong&gt;: This layer typically comprises UI components, containers, pages, and layouts. Additionally, it should interact with the Service Layer solely to retrieve data for binding and rendering purposes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bw8s52ami25o48h57wd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5bw8s52ami25o48h57wd.png" alt=" " width="745" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Placement of business logic&lt;/strong&gt;: As mentioned above, we should place the business logic in the Service layer or, any other place, but with one condition, to be a centralized place and not to be a part of something else (Part of a Component for example).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable Component (Dump Component)&lt;/strong&gt;: Use ready-made components to build your application or build these components from scratch based on the need and to be well-documented and not have a side-effect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature-First vs. Type-First vs. Container(Page)-First File Structure&lt;/strong&gt;: How you can organize your file, there are several approaches for organizing your files inside your frontend project. Choose one or combine more than one, organize your file, and stick with it.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 5)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Mon, 11 Sep 2023 19:31:00 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-5-1p42</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-5-1p42</guid>
      <description>&lt;h1&gt;
  
  
  3. Constraints
&lt;/h1&gt;

&lt;p&gt;Software is a part of our life, and our life is a part of this world, and this world has constraints, For example, human can not fly like Superman, and that is why software application also faces some constraints, These constraints can drive shape and influence the architecture of a software system and that is why there is not a standard or guidelines for each type of software, like if you are planning to develop a finance application, you have to apply standard called (The Only Guidelines of how to implement and deliver a finance software applications), based on the constraints and what we are facing per environment we have to take different decisions based on the situation.&lt;/p&gt;

&lt;p&gt;We have different constraints in shape and size, let's take a look at them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Time to deliver, Scope, and Budget constraints
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time and budget&lt;/strong&gt; are probably the constraints that most software developers are familiar with, and most of the time we usually ask about when to deliver this feature and whether can we buy this library or that framework or not&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a funny story about a unique situation. I was once on a team called "the midnight team." To understand how we got there, let's go back a bit.&lt;br&gt;
In one of my past projects, our project manager made a deal with a client. They agreed that our company would finish the project six months after we started it, which happened during a meeting between our project manager and the client's team. When our project manager came back to our company, they told our bosses that we got the project, but there was a small problem: we didn't have a team ready!&lt;br&gt;
So, our bosses had to act fast. They gathered some developers from different parts of the company to create a team, which we called "the midnight team." These developers worked on the project after their normal work hours. No matter what challenges we faced or how late we worked, we were determined to finish the project in six months. Surprisingly, we did it, but we all felt a bit crazy by the end!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the &lt;strong&gt;Scope constraint&lt;/strong&gt;, usually, the scope is defined during the discovery phase where the business analyst extracts all the business goals and requirements and learns about the business processes to determine the best functionality for solving a particular issue for both the business and its customer, this for the service projects (custom solution for a client), and for the product projects at least we have a list of features we need to implement and we can prioritize them by adding some tags like MVP, must-have, nice-to-have and so on, and then create a pipeline and after that we can start the sprints and etc.&lt;br&gt;
Of course, as the development process goes, and business goals change, the scope can change as well. However, if you have a manager who lacks maturity or doesn't have a technical background (or both), they might alter the project based on market or client demands without considering the original deadline. I've worked with some managers like this. They modify the scope but still expect us to deliver by the same deadline. They often abuse Agile methods to the extreme. In the end, upper management is wondering why the team couldn't meet the agreed-upon deadline!&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Budget constraints&lt;/strong&gt; may affect some aspects, One of them, we don't have a budget to buy a library or a framework that will accelerate the development process, we don't have a good budget for hiring good developers, we have only some local servers for deployments and also for testing the software application, and later on will deploy on the cloud before the delivery date!.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology constraints
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I strongly dislike React! We should go with Angular instead. One of our clients insisted on this, and another client completely avoided open-source libraries with community support. They wanted us to use commercial libraries and software so we could get formal support in case of issues.&lt;br&gt;
Additionally, some organizations have specific lists of approved technologies for building software. They do this for various reasons, like reducing the variety of technologies they need to manage, maintain, operate, and purchase licenses for.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrating with some existing systems&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In the past, I worked on a product mainly designed for large organizations. One crucial aspect our clients were concerned about was how well our product could work with their existing systems, such as HR systems and knowledge base systems, etc. To address this vital requirement, we began modifying our product. We exposed certain APIs and developed a UI framework that allowed external teams to create custom widgets and pages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Target deployment platform&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it comes to Cloud versus On-premises, imagine this scenario: You're working on a frontend solution, and naturally, you're using some third-party libraries hosted on Content Delivery Networks (CDNs). Additionally, you're relying on an external service to get some information, like a weather forecasting service or a currency rate service.&lt;br&gt;
Now, here's the plot twist: One of your clients - and this is a real one with some huge government entities - has a strong distrust for cloud services. And they insist that you deploy this software on servers located within their own network (On-premises).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I faced this situation 3 times with 3 different products. Clients had their own internal network and one of them had his own cloud without internet access!, except for critical software and operating system updates. This posed several challenges. &lt;br&gt;
For example, how to update your deployed software application periodically. Is it by using VPN access or by using a flash drive?  Another challenge arises when dealing with third-party libraries - you have to download them separately and include them in your solution.&lt;br&gt;
For the external services, we have two options, deprecate these features or make an exceptional policy through the firewall to enable access to them. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fear from the Unknown&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some organizations and even some people, and they are a lot, fear of latest technologies, libraries, or frameworks, The comfort zone here is controlling the situation, and fear of the unknown is the engine, they are used to working with certain technologies and frameworks and they don't want to take the risk for trying new things even if these things will make their life easier.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I remember when I began my career as a frontend engineer and first started working with React. This was back in 2016, and I was employed at a software company with nearly 300 developers. Interestingly, my team mate and I were the only ones using React, while the entire company primarily used Microsoft Technologies, Angular, and a few teams were working with Java technologies. We sort of felt like we were outcasting people.&lt;br&gt;
Also, in 2013, I had some experience with a UI library called knockout.js. I recommended it to my team leader at the time, especially since we were creating a Proof of Concept (POC) for one of our clients. The POC involved a Mobile Web App, a listing, and two forms. My team leader, however, insisted on using asp.net web forms to build this POC, while I created my part, the page, with knockout.js. It was quite an unusual experience&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Internal intellectual property&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you need to find a library or framework to solve some problem you are facing, there is a high probability there is an open-source or commercial product out there that suits your needs. But this is not good enough for some people though, and it is not uncommon to find organizations with their own internal libraries, frameworks, and code generators that you must use, despite whether they actually work properly. Back in 2012, I used an internal code generator tool - used internally in my previous organization and built by senior developers and was like CodeSmith Generator - for generating some pages with CRUD operations from UI to the database, but I remember that the UI option was not working fine, and you need to alter some columns in the database, some copy/paste here and there. &lt;/p&gt;

&lt;h2&gt;
  
  
  People constraints
&lt;/h2&gt;

&lt;p&gt;One of the main constraint from my point of view is your capability of your work mate. For Example&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How large is your development team?&lt;/li&gt;
&lt;li&gt;What skills do they have?&lt;/li&gt;
&lt;li&gt;How quickly can you scale your development team if needed?&lt;/li&gt;
&lt;li&gt;Are you able to provide training, consulting, and specialists if needed?&lt;/li&gt;
&lt;li&gt;If you are handing over your software after delivery, will the supporting team have the same skills as your development team or you will handle both sides?&lt;/li&gt;
&lt;li&gt;Is there a mentor or a senior engineer you can consult in case you are using a new technology?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There will be an overhead if you ask a React team to build an Angular project, so you need to take people into account whenever you are architecting a frontend project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organizational constraints
&lt;/h2&gt;

&lt;p&gt;There are sometimes other constraints that you will need to be aware of, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the software system part of a strategic implementation? The answer to this question can either add or remove constraints.&lt;/li&gt;
&lt;li&gt;Organizational politics can sometimes prevent you from implementing the solution that you really want to.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I have something funny here to talk about, One of the products I was working on, was very successful, and we already have five clients using it. It was based on React and .Net Technologies. Due to some politics and top-management decisions, we should be a partner with a very well-known Enterprise company that developing an enterprise platform, The top management decided to close our successful product, terminated all contracts with the five clients, and re-built our product again from scratch based on this Enterprise platform and they offered to the five clients to upgrade to the new product but they should pay 20x (literally it was 20x without exaggeration), and of course, all clients rejected this "upgrade"!.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final Word
&lt;/h2&gt;

&lt;p&gt;Generally, constraints usually seem "bad", but they are often imposed for a good reason. For example, large organizations want to limit the number of tools and technologies because they don't want to support and maintain all these technologies.&lt;/p&gt;

&lt;p&gt;You should know most of the constraints as early as you can because these constraints will impact your architecture directly and will make you take significant decisions. Also, the constraints are like the non-functional, some constraints are more important than others.&lt;/p&gt;

&lt;p&gt;In the end, constraints are usually obstacles that you need to work around but sometimes you can trade off against one other.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 4)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Sun, 27 Aug 2023 17:42:06 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-4-2ko</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-4-2ko</guid>
      <description>&lt;h1&gt;
  
  
  2. Architectural Drivers (Part 2)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  2. Non-Functional Requirements (Quality Attributes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  11. Usability
&lt;/h3&gt;

&lt;p&gt;Usability is all about how easy it is for people to use a website or app and get the results they want. Think of it like this: when someone uses a platform, it should work well, be efficient, and make them happy.&lt;/p&gt;

&lt;p&gt;For example, let's say you are building a website using React, like a travel blog where you showcase your landscape photography. Usability in this context means that visitors to your website should be able to easily navigate through your posts, see your pictures, and find the information they're looking for without getting frustrated.&lt;/p&gt;

&lt;p&gt;Now, the technical side of usability involves making your website accessible to everyone, including those with disabilities. You can do this by using things like assistive technology, which helps people who use screen readers or other tools to access your site. Also, it's important to provide text descriptions for images and any multimedia content you have. This way, even if someone can't see the images, they'll still understand what's going on.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. Responsiveness
&lt;/h3&gt;

&lt;p&gt;Responsiveness can indeed refer to both aspects in the context of web development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Responsive Web Design: It's about making websites that work well on different devices like phones, tablets, and computers. So when you open a website on your phone, it looks good and works smoothly.&lt;/li&gt;
&lt;li&gt;Quick and Smooth: It also means that when you use a website, like clicking buttons or typing things, it should respond quickly without any delays. Imagine using an app that feels really fast and doesn't make you wait, and so on.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We've already covered ways to make your app run smoothly and perform better in general. Now, let's talk about Responsive Web Design.&lt;/p&gt;

&lt;p&gt;Responsive Web Design (RWD) is a web design approach to make web pages render well on all screen sizes and resolutions while ensuring good usability. It is the way to design for a multi-device web.&lt;/p&gt;

&lt;p&gt;Around 10 years ago, you might have come across this method while using Facebook on your phone's browser. Back then, web developers used to make a separate website for small screens. These sites usually started with m. or mobile. in the domain. So, as a web developer, you had to take care of two websites - the main one for desktop computers and another for small devices like phones.&lt;/p&gt;

&lt;p&gt;Things changed when &lt;strong&gt;Ethan Marcotte&lt;/strong&gt; published an article on &lt;a href="https://alistapart.com/article/responsive-web-design/" rel="noopener noreferrer"&gt;Responsive Web Design&lt;/a&gt;. This article illuminated the entire industry by building upon existing disciplines and concepts. He introduced these principles to guide the creation of websites that could adapt to the user's device size and shape themselves according to the viewport.&lt;/p&gt;

&lt;p&gt;Responsive Web Design was not some new or emerging technology, but it just is collection of tools and techniques as follow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fluid grids&lt;/strong&gt;: Use percentage-based widths rather than fixed pixel dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible images&lt;/strong&gt;: image to be 100%-width to fill the container, and the container will adapt it with the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media queries&lt;/strong&gt;: specify different styles for different viewport sizes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before Ethan wrote his article about responsive web design (RWD), the methods he talked about were already present in web browsers for many years. However, Ethan's explanation of RWD made the solution that everyone was urgently seeking very clear and understandable.&lt;/p&gt;

&lt;h3&gt;
  
  
  13. Compatibility
&lt;/h3&gt;

&lt;p&gt;In this context (Frontend Architecture) we will focus on the Browser Compatibility.&lt;/p&gt;

&lt;p&gt;Browser compatibility is the ability of a website or web application to function across different web browsers and operating systems. Moreover, having a cross-browser-compatible website ensures you’re providing a consistent and optimal user experience across different browsers. Users should be able to access and interact with a website or web application regardless of the browser they prefer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I remember back when I worked as a .Net developer. I had a client who insisted that their web application had to work perfectly on Internet Explorer 8 and 9. It was quite a tough task. But nowadays, Internet Explorer is no longer used because it couldn't keep up with the latest web standards and caused compatibility issues. Getting rid of it was definitely one of the best decisions in the field of web development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But now, browser compatibility has become easier to handle in recent years due to several factors:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Standardization&lt;/strong&gt;: The development and adoption of web standards by major browser vendors have improved consistency across different browsers. Organizations like the World Wide Web Consortium (W3C) help create and maintain these standards, ensuring that browser behavior aligns more closely.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modern Browsers&lt;/strong&gt;: Modern browsers are built with better compliance to web standards, which reduces the need for complex workarounds or browser-specific code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polyfills and Transpilers&lt;/strong&gt;: Tools like Babel and polyfills help bridge the gap between older and newer browser versions by enabling the use of new features in older browsers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Tools&lt;/strong&gt;: Modern browsers offer comprehensive developer tools that help identify and fix compatibility issues more efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Tools&lt;/strong&gt;: There are various testing tools available that simulate different browsers and platforms, making it easier to catch compatibility problems during development.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Resources&lt;/strong&gt;: The web development community actively shares best practices, guides, and solutions for browser compatibility challenges, making it easier for developers to find help when needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Component Libraries and Frameworks&lt;/strong&gt;: Frameworks like React offer abstractions that help manage browser inconsistencies, enabling developers to focus on building features rather than worrying about compatibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Feature Detection&lt;/strong&gt;: Developers can use feature detection techniques to determine whether a certain browser supports a specific feature before implementing it, reducing the likelihood of compatibility issues.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  14. Testability
&lt;/h3&gt;

&lt;p&gt;Testability refers to how easily developers and others can test the application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've personally encountered codebases where the design didn't prioritize making it easy to test, especially when it comes to React-based components. A lot of developers tend to build these components as one big piece to handle many business needs, instead of breaking them into smaller parts that can be tested more easily. For Example, Creating a Table component that lists data by fetching it from an external resource (API), and also contains a form to add a new item in the table and to be synced with the backend through another API. We can break this puffy component by creating a component for listing, component for the form, and service functions for each API so that we can create some unit testing for all of them without much pain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, to achieve testability, It's a good idea to make sure that a big part of your frontend code is tested – aiming for around 70% to 80% coverage is ideal. These tests are meant to check individual parts, like components and functions, all on their own. This helps ensure everything works well.&lt;/p&gt;

&lt;h3&gt;
  
  
  15. Reliability
&lt;/h3&gt;

&lt;p&gt;Reliability refers to the quality of being trustworthy and consistent over time. It often pertains to the ability of a system, product, or process to consistently perform its intended functions without failures or errors.&lt;/p&gt;

&lt;p&gt;Sometimes, we call this MTBF/MTTF, which stands for Mean Time Between/To Failures. It's about how consistent software behaves. When software doesn't do what we expect, it becomes unreliable.&lt;/p&gt;

&lt;p&gt;A common way to check reliability is by counting software problems (bugs) and comparing them to the amount of code.&lt;/p&gt;

&lt;p&gt;To make software better and more reliable, the key is to test it a lot. So, software that's easy to test is usually more dependable than software that's harder to test.&lt;/p&gt;

&lt;h3&gt;
  
  
  16. Disaster Recovery
&lt;/h3&gt;

&lt;p&gt;What steps would you take if access to your files (assets) was restricted in certain locations, or if you experienced data loss due to a hard disk failure or server issues? How would you go about developing a disaster recovery plan to minimize potential risks that could arise at any moment?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A while ago, we faced a strange problem.  Some third-party libraries we used in our project, which we get from a certain place (CDN Provider), were suddenly not working in a certain country. We couldn't change where we got these third-party libraries from right then. So, we fixed this problem by changing the addresses of these libraries (pointing to a custom proxy server)  in our frontend project, and we used this proxy server to route these URLs to the CDN provider again!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One way to prevent your project from failing due to unexpected errors or new updates is to have a backup plan. This means having a plan to go back to a stable version of your project if something goes wrong.&lt;/p&gt;

&lt;p&gt;There are different ways to do this. One method is to use versioning and create labels (tags) for each update. This way, if there's a problem with the latest update, you can go back to the previous stable version of your project.&lt;/p&gt;

&lt;p&gt;It's also important to store your code in a safe place. You can use a cloud service like GitHub or BitBucket to keep your code safe. It's a good idea to have a clear process for adding your code to these services, like creating different branches for different features. This helps prevent loss of code in case of server failures or other problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a story to share: In a previous company, we used a tool called TFS (Team Foundation Server) to store our code before using Git. TFS was hosted on our own servers. Once, one of the servers had a hard disk failure, and we lost the source code of one of our projects. We had to gather the latest code from developers' machines, manually combine it, and found out that six days of work was lost. We had to redo everything from scratch! This situation taught us the importance of proper code storage and backup plans.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Working with Non-fucntional requirements
&lt;/h2&gt;

&lt;p&gt;After listing a set of quality attributes that could be relevant to a frontend project, what should I pay attention to? Should I aim to incorporate all of them into my next project? Are these attributes equally important?&lt;/p&gt;

&lt;p&gt;Firstly, it's important to note that these quality attributes don't hold the same level of importance. Some might be more suitable than others based on your work environment and the nature of the frontend project you're working on. To begin with, familiarize yourself with the prevalent quality attributes in your field. Prioritize those when you begin on creating a new system or making changes to an existing one.&lt;/p&gt;

&lt;p&gt;Non-functional requirements (Quality Attributes) can be a bit challenging, as they differ in nature from functional requirements. When you're collecting requirements, your client typically provides a wish-list of what they want the software system to accomplish. There are established methods for capturing this information, such as user stories, use cases, traditional requirement specifications, acceptance criteria, and more. But, this is not the case with Quality attributes though.&lt;/p&gt;

&lt;p&gt;There are three phases to get the actual non-functional requirements from the client&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capture &lt;/li&gt;
&lt;li&gt;Filter &amp;amp; Refine&lt;/li&gt;
&lt;li&gt;Challenge&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Capture
&lt;/h3&gt;

&lt;p&gt;Usually, clients give a lot of requests for what they want a software system to do. But they often forget to mention things about Quality Attributes, like wanting the system to load pages in less than 2 seconds, which is about performance. You have to ask about these Quality Attributes to know what they want. But it can be tricky. For example, if you ask about how easy it should be to use the system, they might just say "make it as easy as possible" and not give you more details. So, you need to ask the right questions&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Throughout my career, there was only one case where someone directly asked for a non-functional requirement. This request was related to performance. The requirement was quite demanding: "Ensure that all pages of the system load in less than one second!" This was a challenging task since the project, built on a pre-existing product, naturally had performance issues and loaded pages rather slowly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Refine
&lt;/h3&gt;

&lt;p&gt;Back again to ask the right questions, these questions must be tricky enough to get the non-functional requirements or you might be lucky enough to receive this information within the functional requirements. Once you receive the these non-functional requirements, you have to discuss them with the client to make sure that the client understand these requirements and also to set the expectations.&lt;br&gt;
For Example, the client may access to support the accessibility and that is it. So it is a wide requirement and we need to ask some question to refine it&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What are the categories of users with disabilities that need to be considered to ensure accessibility support?&lt;/li&gt;
&lt;li&gt;What are the recommended screen resolutions that a system should be designed to support?&lt;/li&gt;
&lt;li&gt;Do you have existing accessibility guidelines?&lt;/li&gt;
&lt;li&gt;Can we prioritize accessibility features?&lt;/li&gt;
&lt;li&gt;Can we include accessibility in QA testing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consequently, we now have a foundation for initiating discussions. Should you be able to assign specific measures to the non-functional aspects, you can then formulate acceptance criteria and assess them in an objective manner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge
&lt;/h3&gt;

&lt;p&gt;The "Trade-Off" is the secret key, imagine the following scenario, you are asking the client about a specific feature, and without any hesitation, his answer will be "Yes"! so one by one every user  stories will be important and will be hard for the team to set the priority for each one. In the end, everything will be very important and should be included in the product in the first release!&lt;/p&gt;

&lt;p&gt;Indeed, the concept of "Trade-Off" holds significance here. For example, when a client requests a particular feature, after your assessment and team deliberation, the feature might come with a cost of X. However, there's a possibility to provide a simpler version in phases, reducing the cost to X/2. Upon presenting this option to the client, they might agree to proceed with this approach.&lt;/p&gt;

&lt;p&gt;In our domain, nearly everything can be achieved, but each choice involves a trade-off. By explaining these trade-offs, we can determine the optimal solution for a given situation.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 3)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Sat, 19 Aug 2023 16:11:19 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-3-40of</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-3-40of</guid>
      <description>&lt;h1&gt;
  
  
  2. Architectural Drivers
&lt;/h1&gt;

&lt;p&gt;Once we know what Frontend Architecture means, we must consider what we need when designing a frontend project. No matter the approach we take, whether it's traditional and planned or more flexible and adaptable, certain common factors influence the final Frontend Architecture. These factors guide how we structure and build the frontend part of a software project.&lt;/p&gt;

&lt;p&gt;Architectural drivers are important things that we must consider when designing a software system (Significant decisions). They have a big impact on how the software will be built. These drivers help shape and guide the design of the software's architecture. They basically tell us what we need to do and why we need to do it. When we create the software's architecture, we make sure it meets these important drivers. By doing that, we ensure that the software will work well and meet the goals we have set for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Functional Requirements
&lt;/h2&gt;

&lt;p&gt;The technical functions that represent the main product features. These functions describe how the system behaves and what it should do.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For Example, we have web-based to-do list application as the product, and we'll focus on the frontend technical functions that represent its main features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Interface (UI)&lt;/strong&gt;:
The frontend should provide a user-friendly and visually appealing interface for users to interact with the to-do list application.
It should have a clear layout with sections for displaying tasks, adding new tasks, marking tasks as completed, and deleting tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Display&lt;/strong&gt;:
The frontend should fetch and display the list of tasks from the backend server or local storage.
Each task should show relevant details such as title, due date, and status (completed or pending).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add Task&lt;/strong&gt;:
The frontend should allow users to enter new tasks with titles and optional due dates.
It should validate the input and prevent users from adding empty tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Completion&lt;/strong&gt;:
The frontend should provide a way for users to mark tasks as completed.
Completed tasks should be visually distinguished from pending tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Deletion&lt;/strong&gt;:
The frontend should enable users to delete tasks they no longer need.
It should prompt users for confirmation before permanently removing a task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Editing&lt;/strong&gt;:
The frontend could allow users to edit task details, such as updating the title or due date.
It should provide a smooth and intuitive editing experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Filtering and Sorting&lt;/strong&gt;:
The frontend could include options for users to filter tasks based on completion status (completed/pending) or due date.
It could also allow users to sort tasks based on different criteria, such as alphabetical order or due date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;:
The frontend should handle errors gracefully and display meaningful error messages if something goes wrong, such as failed server requests or validation errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design&lt;/strong&gt;:
The frontend should be designed to work well on different devices and screen sizes, such as desktops, tablets, and mobile phones.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Non-Functional Requirements (Quality Attributes)
&lt;/h2&gt;

&lt;p&gt;Non-Functional Requirements (NFRs), also known as Quality Attributes or quality concerns, are a set of criteria that describe how a software system should behave and perform rather than specifying specific functionalities or features. While functional requirements deal with what the system should do, non-functional requirements address how well it should do it. These requirements are essential for defining the overall quality, usability, and performance of a software application. NFRs help ensure that the system meets the desired levels of reliability, scalability, maintainability, security, and other crucial aspects. &lt;/p&gt;

&lt;p&gt;Here are some common Non-Functional Requirements as follow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Performance
&lt;/h3&gt;

&lt;p&gt;Performance is about loading something fast, without lagging and without much time to load.&lt;br&gt;
We have two main thing we can talk about within this topic, &lt;strong&gt;Rendering the Web Page&lt;/strong&gt; and &lt;strong&gt;load data and files&lt;/strong&gt; (assets).&lt;/p&gt;

&lt;h4&gt;
  
  
  Web Page Rendering
&lt;/h4&gt;

&lt;p&gt;If you are concerned with an application that targets low-performance machines, you should take care of rendering your website at a minimum cost.&lt;br&gt;
The Key here is the** Critical Rendering Path (CRP)**. CRP cares about converting the HTML, CSS, and JavaScript into pixels on the screen. And by optimizing the critical render path we can improve render performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Load Data and Files
&lt;/h4&gt;

&lt;p&gt;Back again to the Performance definition - about loading something fast - usually we are talking about the response time or the latency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Response Time: Response time refers to the time it takes for a system to respond to a user's action or request.&lt;/li&gt;
&lt;li&gt;Latency: Latency refers to the delay or time lag between sending a request and receiving a response. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Lets explain it in simple example, Imagine there are 2 people who want to print something using a printer. The printer takes 10 seconds to print each paper.&lt;br&gt;
The first person's paper gets printed right away, so he wait for 10 seconds. he don't have to wait before their paper starts printing.&lt;br&gt;
The second person waits for 10 seconds for his turn and then his paper takes 10 seconds to print. So, they wait a total of 20 seconds (10 seconds for waiting and 10 seconds for printing).&lt;br&gt;
So, We conclude that that Response Time = Latency + Process Time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Based on the above explanation we have a lot of areas we can enhance and optimize as follow&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Optimize Images&lt;/strong&gt;: Use compressed and appropriately sized images to reduce load times without sacrificing quality. Consider using responsive images and modern formats like WebP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize HTTP Requests&lt;/strong&gt;: Reduce the number of external resources (CSS, JavaScript, fonts) to minimize the number of HTTP requests the browser needs to make.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use CSS and JavaScript Minification&lt;/strong&gt;: Minify your CSS and JavaScript files to remove unnecessary whitespace and comments, reducing their file size and improving loading times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage Browser Caching&lt;/strong&gt;: Set proper cache headers for static assets to enable browser caching, allowing returning visitors to load the page faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prioritize Above-the-Fold Content&lt;/strong&gt;: Load critical above-the-fold content first to provide users with a fast initial rendering experience while other assets load in the background.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt;: Implement lazy loading for images and other non-essential resources. This defers loading until the user scrolls to the content, saving bandwidth and improving performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce Render-Blocking Resources&lt;/strong&gt;: Minimize the use of render-blocking CSS and JavaScript that can delay the rendering of the page content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Content Delivery Networks (CDNs)&lt;/strong&gt;: Distribute assets across geographically distributed CDNs to reduce latency and ensure faster delivery to users around the world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server-Side Rendering (SSR) or Static Site Generation (SSG)&lt;/strong&gt;: Consider implementing SSR or SSG techniques for faster initial rendering and improved SEO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Audits and Monitoring&lt;/strong&gt;: Regularly perform performance audits using tools like Lighthouse or PageSpeed Insights to identify bottlenecks and monitor performance over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive Web Apps (PWAs)&lt;/strong&gt;: Explore building PWAs to provide an app-like experience, including offline access and fast loading even in low network conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduce Third-Party Dependencies&lt;/strong&gt;: Minimize the number of third-party scripts and services, as they can introduce additional HTTP requests and potential performance issues.
13.** Optimize Fonts**: Use web-safe fonts or consider loading fonts asynchronously to prevent font rendering delays.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. Extensibility
&lt;/h3&gt;

&lt;p&gt;Extensibility refers to the ability of the codebase to be easily extended and modified without causing significant disruptions or requiring major rework. There are some principles regarding the extensibility as follows&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modular Architecture&lt;/strong&gt;: Design the frontend using modular components that can be added, removed, or replaced without affecting other parts of the application. This allows for easy integration of new features or changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use of Design Patterns&lt;/strong&gt;: Implement design patterns such as the Module Pattern or Component-Based Architecture (like React components) that promote code reusability and clear separation of concerns. This makes it easier to introduce new functionality without impacting existing parts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Well-Structured Code&lt;/strong&gt;: Write clean, well-documented, and maintainable code that adheres to best practices and coding standards. This helps other developers (or your future self) to understand and extend the codebase effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plugin System&lt;/strong&gt;: Consider implementing a plugin system that allows third-party developers to create and integrate extensions into your application. This can be especially useful if you're developing web applications that might need customizable features for different clients.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs and Interfaces&lt;/strong&gt;: Define clear APIs and interfaces for different modules or components. This helps establish a contract between different parts of the application and ensures that changes can be made without breaking existing functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing and Testability&lt;/strong&gt;: Maintain a strong suite of automated tests that cover different aspects of the application. This ensures that new extensions or modifications don't introduce regressions and can be confidently integrated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control and Collaboration&lt;/strong&gt;: Use version control systems (e.g., Git) effectively to manage changes and collaborate with other team members. Proper branching and merging strategies can help keep the codebase extensible while managing feature development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: Document your codebase, including its architecture, design decisions, and guidelines for extending it. This helps new developers quickly understand how to work within the project's framework.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Scalability
&lt;/h3&gt;

&lt;p&gt;Scalability refers to the ability of the application's user interface to handle increased load and demand without compromising performance. Scalability ensures that your application can accommodate growing user bases and increased traffic while maintaining responsiveness and user experience.&lt;/p&gt;

&lt;p&gt;When designing for scalability, you might consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Performance Optimization&lt;/strong&gt;: Implement techniques such as lazy loading, code splitting, and caching to ensure that the application loads quickly and efficiently even as it grows in complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design&lt;/strong&gt;: Create layouts that work seamlessly across various screen sizes and devices to cater to a diverse user base.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser Compatibility&lt;/strong&gt;: Test your application across various browsers to ensure consistent performance and functionality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable Architecture&lt;/strong&gt;: Choose a modular and maintainable architecture (like component-based architecture in React) that allows for easy addition of new features and components.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt;: If your project is part of a larger application ecosystem, ensure that the load is distributed evenly among servers to prevent bottlenecks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching and CDN&lt;/strong&gt;: Utilize Content Delivery Networks (CDNs) to distribute static assets and cached content closer to users, reducing server load and improving performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal Scaling&lt;/strong&gt;: Design your application so that you can scale out horizontally by adding more frontend servers as the user base grows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized Assets&lt;/strong&gt;: Optimize images, fonts, and other assets to minimize loading times and bandwidth usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Updates&lt;/strong&gt;: If your application requires real-time updates (e.g., social media feeds), consider implementing efficient techniques like WebSocket connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring and Analytics&lt;/strong&gt;: Set up monitoring tools to track performance metrics, identify bottlenecks, and proactively address issues as the application scales.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4. Availability
&lt;/h3&gt;

&lt;p&gt;Availability is about the degree to which your software is operational and available to service the users. Maybe it is an infrastructure concern to publish or deploy the frontend application on a stable infrastructure but still, we have some concerns we should care about, for example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fault Tolerance&lt;/strong&gt;: Designing the frontend to gracefully handle errors, crashes, and other issues without causing a complete disruption to users' experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching&lt;/strong&gt;: Utilizing caching mechanisms to store and deliver frequently requested content, reducing the load on the backend and improving response times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring and Alerting&lt;/strong&gt;: Implementing monitoring tools that track the health and performance of the frontend application and provide alerts to administrators in case of anomalies or outages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Content Delivery Networks (CDNs)&lt;/strong&gt;: Distribute assets across geographically distributed CDNs to reduce latency and ensure faster delivery to users around the world.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Downtime Maintenance&lt;/strong&gt;: Planning and communicating scheduled maintenance windows to minimize the impact on users while performing necessary updates or maintenance tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Feedback and Support&lt;/strong&gt;: Providing channels for users to report availability issues and ensuring a responsive support system to address any concerns promptly.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  5. Flexibility
&lt;/h3&gt;

&lt;p&gt;Flexibility is to enable your application to perform more than one task or perform that single task in a number of different ways.&lt;/p&gt;

&lt;p&gt;For Example, enable your application the ability for non-techincal people to modify the business rules used within the software.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For Example, Imagine you're developing a task management application using React. Users can create tasks, set deadlines, and assign priority levels. Flexibility in this context could involve allowing users to customize their task management experience in different ways:&lt;br&gt;
In your application, you can offer users the flexibility to sort their tasks in multiple ways to suit their preferences. Here's how you could implement this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Due Date Sorting: Users can choose to sort tasks based on their due dates. This would help users prioritize tasks that are approaching their deadlines.&lt;/li&gt;
&lt;li&gt;Priority Sorting: Users can opt to sort tasks by priority, displaying the most critical tasks at the top of their list.&lt;/li&gt;
&lt;li&gt;Creation Date Sorting: Users can also sort tasks based on when they were created. This can be useful for reviewing recently added tasks.&lt;/li&gt;
&lt;li&gt;Custom Sorting: Provide an option for users to manually reorder their tasks by dragging and dropping them. This way, users can create their own customized task order.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  6. Monitoring
&lt;/h3&gt;

&lt;p&gt;Monitoring is important as it concerns how your user interacts and accesses your entire application. For example, if your users can't make use of your website's features because of a UI error, then your application has failed to fulfill its purpose regardless of how performant it is. We can achieve that by integrating the application with platform-specific monitoring capabilities.&lt;br&gt;
We have several platforms we can integrate with, like Sentry, one of the most used tools that allows you to report rendering errors by wrapping your component tree within the Sentry error-reporting service.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Security
&lt;/h3&gt;

&lt;p&gt;Security is the degree to which the software protects information and data so that people, other products, or systems have data access appropriate to their types and levels of authorization.&lt;/p&gt;

&lt;p&gt;Here are some ways you can apply security measures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Input Validation and Sanitization&lt;/strong&gt;: Ensure that user inputs are properly validated and sanitized to prevent common security vulnerabilities like Cross-Site Scripting (XSS) attacks. Implement client-side validation and use frameworks or libraries that offer built-in protection against such attacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Encryption&lt;/strong&gt;: When transmitting sensitive data between the client and the server, use encryption protocols like HTTPS to ensure that the data remains confidential and cannot be easily intercepted or tampered with.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Coding Practices&lt;/strong&gt;: Follow secure coding practices, such as avoiding hardcoded secrets in your code, escaping user-generated content, and using libraries with a good security track record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular Updates and Patching&lt;/strong&gt;: Keep your frontend libraries and frameworks up to date with the latest security patches. Vulnerabilities can be discovered over time, so staying current is crucial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Dependency Management&lt;/strong&gt;: Be cautious when including third-party dependencies in your project. Only use well-maintained and trusted libraries, and regularly audit them for vulnerabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: Avoid exposing sensitive information in error messages that could potentially aid attackers. Provide generic error messages to users and log detailed error information securely on the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Design Reviews&lt;/strong&gt;: Conduct regular security design reviews to identify potential vulnerabilities in your frontend architecture and codebase.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  8. Maintainability
&lt;/h3&gt;

&lt;p&gt;Maintainability is a crucial aspect and it is hard to quantify, but we can guarantee somehow the maintainability by following some strategies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Code Structure and Organization&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Follow a modular and component-based architecture, like React components. Divide your code into smaller, reusable components with clear responsibilities.&lt;/li&gt;
&lt;li&gt;Use meaningful names for files, folders, and components. This makes it easier for both you and other developers to understand the codebase.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Coding Standards&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Establish and enforce coding standards and guidelines for the project. This ensures a consistent coding style throughout the codebase, making it easier for developers to read and maintain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Write thorough and up-to-date documentation for your codebase. This includes high-level architecture diagrams, component documentation, and inline comments.&lt;/li&gt;
&lt;li&gt;Document the purpose of each component, its props, and any expected behaviors. This helps new developers understand and modify the codebase more effectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version Control&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Utilize version control systems like Git to track changes and collaborate with other developers. Follow a branching strategy (like Gitflow) to manage feature development, bug fixes, and releases.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing and Test Automation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Implement a comprehensive testing strategy using tools like Jest and React Testing Library. Write unit tests, integration tests, and end-to-end tests to catch bugs early and prevent regressions.&lt;/li&gt;
&lt;li&gt;Set up automated testing pipelines to run tests on each code commit and before deploying to production.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Reviews&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Conduct regular code reviews to ensure code quality and maintainability. Code reviews provide opportunities to catch issues, share knowledge, and maintain consistent coding standards.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactoring&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Regularly revisit your codebase to identify areas that need refactoring. Refactoring helps eliminate technical debt, improve performance, and enhance maintainability.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency Management&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Keep track of third-party libraries and dependencies used in the project. Regularly update them to the latest versions to benefit from bug fixes, security patches, and performance improvements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Optimization&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Optimize the performance of your frontend application. This includes minimizing the use of costly operations, optimizing network requests, and handling memory efficiently.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling and Logging&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Implement robust error handling mechanisms to gracefully handle unexpected situations. Use logging to capture errors and debugging information, which aids in diagnosing issues.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design Patterns&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Familiarize yourself with design patterns relevant to frontend development, like MVC, MVVM, or Flux. These patterns can provide a structured approach to building maintainable applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuous Learning&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Stay updated with the latest frontend technologies, best practices, and tools. Continuous learning helps you adapt to changes and incorporate new techniques into your projects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  9. i18n &amp;amp; l10n
&lt;/h3&gt;

&lt;p&gt;How can you make your application work with different languages, including those that are written from right to left? This is called internationalization (i18n). And what about localization (l10n)? Localization means showing things like numbers, money, and dates in ways that make sense to the user's culture. When you put these together, it's called "Globalization".&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Accessibility
&lt;/h3&gt;

&lt;p&gt;Accessibility usually refers to things like the W3C accessibility standards, which refer to designing and building digital products, such as websites and applications, in a way that ensures they can be used and navigated by people with disabilities. &lt;br&gt;
It's about creating a user experience that is inclusive and accommodating to individuals who may have visual, auditory, motor, or cognitive impairments. This involves using proper HTML semantics, providing alternative text for images, ensuring keyboard navigation, and incorporating ARIA roles and attributes to make your web applications usable by a diverse range of users, including those who rely on assistive technologies. By making your frontend projects accessible, you contribute to a more inclusive online environment and enhance the user experience for everyone.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>tutorial</category>
      <category>essentials</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 2)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Thu, 17 Aug 2023 07:11:54 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-2-28hj</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-2-28hj</guid>
      <description>&lt;h2&gt;
  
  
  Architecture Vs Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the difference between Architecture and Design?
&lt;/h3&gt;

&lt;p&gt;Most people think that the two words are the same or lead to the same thing.&lt;br&gt;
But there is a trick here. When I share a problem with different developers, they think differently and each one of them has a valid solution for my problem, and this is normal. Each one has his own experience and based on that; he offers a solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Grady_Booch" rel="noopener noreferrer"&gt;&lt;strong&gt;Grady Booch&lt;/strong&gt;&lt;/a&gt; says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All architecture is design but not all design is architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this makes sense because creating a solution and "architecting" is essentially a design exercise. It is about filtering the options that you have and making decisions. &lt;/p&gt;

&lt;p&gt;And also, regarding this point, &lt;strong&gt;Grady Booch&lt;/strong&gt; says,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Architecture represents the significant design decisions that shape a system, where significance is measured by the cost of change.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What is that mean?&lt;br&gt;
The Significant decisions are "architecture" and anything else is "design". I know it is still not clear enough the distinction between "architecture" and the "design", but we have some examples that may help us to understand the difference.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frameworks **and **languages&lt;/strong&gt; (here it will be JS or TS), are "architectural" decision.&lt;/li&gt;
&lt;li&gt;Choosing the suitable &lt;strong&gt;File Structure&lt;/strong&gt; is "architectural" not just "design" decision.&lt;/li&gt;
&lt;li&gt;Http Manager - the centralize block that helps us to consume APIs - is "design" decision not "architectural".&lt;/li&gt;
&lt;li&gt;Styling is "architectural" decision, CSS, SASS, LESS, CSS-in-JS or CSS utility library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Micro-frontend&lt;/strong&gt; or &lt;strong&gt;Monolith&lt;/strong&gt; Solution is "architectural" decision.&lt;/li&gt;
&lt;li&gt;Documentation tool is "architectural" decision.&lt;/li&gt;
&lt;li&gt;Passing Data through layers is "architectural" decision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I think you have now an image of how to differentiate the "architectural" or "design" decision when you have to take a decision to solve a problem.&lt;br&gt;
But in the end, we can say that Architectural decisions are those that you cannot reverse without some degree of effort, in other words, they are the things that you would find hard to refactor in an afternoon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Software Architecture important in general?
&lt;/h3&gt;

&lt;p&gt;Let's ask some questions and based on you answer you will know, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does your application have a well-defined structure (File Structure, Design Pattern, etc.)?&lt;/li&gt;
&lt;li&gt;Is everybody in your team implementing features in a consistent way?&lt;/li&gt;
&lt;li&gt;Is there a consistent level of quality across the codebase?&lt;/li&gt;
&lt;li&gt;Do your team members share the same vision for how the application will be built?&lt;/li&gt;
&lt;li&gt;Does everybody on your team have the necessary amount of technical guidance?&lt;/li&gt;
&lt;li&gt;Is there an appropriate amount of technical guidance and leadership?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your answer is &lt;strong&gt;no&lt;/strong&gt; for any point, and already delivered some applications, I think there will be a re-writing process that will be happening or already happening. Or it might be you already delivered an application for a client, and you will not support it again or not doing any changes in the future, so it is fine to not care about some points already mentioned above.&lt;/p&gt;

&lt;p&gt;The technical guidance or leadership is very important at any level (code level and above it) because most software projects and products start with the best of intentions, and it is easy for them to veer off the track.&lt;/p&gt;

&lt;p&gt;Personally, I worked on some projects without anyone caring about the architecture, just someone caring about it in the early phase of the project, adding the structure and the technology, then disappearing. Here it is, some of the problems I list in points.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File Structure not predictable.&lt;/li&gt;
&lt;li&gt;Many methods to consume APIs (Axios, fetch).&lt;/li&gt;
&lt;li&gt;Heavy usage of redux for every single component.&lt;/li&gt;
&lt;li&gt;A cocktail of CSS and LESS styles.&lt;/li&gt;
&lt;li&gt;Two different libraries for handling dates and times.&lt;/li&gt;
&lt;li&gt;"Any" as a type is used everywhere.&lt;/li&gt;
&lt;li&gt;Sensitive keys pushed to the repository (.env file).&lt;/li&gt;
&lt;li&gt;Different components with the same logic and functionalities.&lt;/li&gt;
&lt;li&gt;Zero Documentation.&lt;/li&gt;
&lt;li&gt;Very huge files (some files reached +1000 lines of code).&lt;/li&gt;
&lt;li&gt;Unbelievable Git flow, deploying code into an environment then creating PR with these changes!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, without technical leadership, many codebases also end up looking like the stereotypical "big ball of mud" or "spaghetti code". And no one want to work with these codebases.&lt;/p&gt;

&lt;p&gt;Most of these problems are relatively easy to solve with the application of some good technical leadership, resulting in a team that therefore understands and thinks about the software architecture and even ask some questions that will affect the project in general. In summary, this can provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A clear vision and roadmap for the team to follow.&lt;/li&gt;
&lt;li&gt;Technical leadership and better coordination.&lt;/li&gt;
&lt;li&gt;Encouragement to talk to people in order to ask questions relating to significant decisions, non-functional requirements, constraints, and other cross cutting concerns.&lt;/li&gt;
&lt;li&gt;Standards and guidelines, leading to a well-structured codebase.&lt;/li&gt;
&lt;li&gt;A set of firm foundation for the project being built.&lt;/li&gt;
&lt;li&gt;A structure with which to communicate the solution at different levels of abstraction to different audiences.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Let's consider the architecture of an e-commerce website as an example for the last previous point. The different levels of abstraction and the audiences they cater to might be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;High-Level Abstraction: For non-technical stakeholders (e.g., business executives, investors):

&lt;ul&gt;
&lt;li&gt;The frontend of the e-commerce website is the user interface that customers interact with when browsing and purchasing products.&lt;/li&gt;
&lt;li&gt;It provides a visually appealing and user-friendly design, creating a positive user experience.&lt;/li&gt;
&lt;li&gt;The architecture emphasizes how the frontend contributes to increasing customer engagement and conversion rates.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Medium-Level Abstraction: For project managers and design team leads:

&lt;ul&gt;
&lt;li&gt;The frontend architecture follows a component-based design approach, where different UI elements are encapsulated into reusable components.&lt;/li&gt;
&lt;li&gt;It uses popular frontend frameworks like React, Angular, or Vue.js, allowing efficient development and maintenance.&lt;/li&gt;
&lt;li&gt;The architecture includes details about responsive design principles, ensuring optimal performance on various devices.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Low-Level Abstraction: For frontend developers and technical team members:

&lt;ul&gt;
&lt;li&gt;The frontend employs a state management library (e.g., Redux) to manage the application's state and data flow.&lt;/li&gt;
&lt;li&gt;It uses RESTful APIs to communicate with the backend and fetch product data, user information, and other relevant data.&lt;/li&gt;
&lt;li&gt;The architecture discusses the implementation of client-side routing to enable smooth navigation between different pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Developer Toolkit: For developers with a focus on implementation details:

&lt;ul&gt;
&lt;li&gt;The frontend codebase is structured following best practices, such as organizing files by feature or module.&lt;/li&gt;
&lt;li&gt;It employs build tools like Webpack or Parcel to bundle and optimize the code for production deployment.&lt;/li&gt;
&lt;li&gt;The architecture highlights the use of testing frameworks (e.g., Jest or Cypress) to ensure code quality and robustness.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  So, what do you think, does every software project need software Architect?
&lt;/h3&gt;

&lt;p&gt;The short answer is "&lt;strong&gt;yes&lt;/strong&gt;", Why? because every software team should look at a number of factors in order to assess how much software architecture thinking, a degree of which manifests itself as up-front design, is necessary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have experience working on various frontend projects. However, we didn't have proper technical design or architectural meetings to plan the projects. Instead, we simply used a familiar framework that the team already knew, so we could save time on learning new things and quickly set up the file structure. Unfortunately, this approach led to some challenges. We faced difficulties in communicating with each other about new components introduced by team members. Additionally, we lacked clear guidelines for documentation and a structured process for code reviewing. These important aspects were overlooked, causing some issues along the way.&lt;br&gt;
Also, I believe you noticed that, in backend development, where planning and scalability are key, software architects are highly valued. They are invited onto a project long before development begins and they have discussions with clients about architectural needs (functional, non-functional requirements, etc.)&lt;br&gt;
Where is the frontend time? We were being asked to do all our work piece by piece, as an afterthought.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are two approaches to handling up-front design meetings.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Too many up-front design meetings with the team trying to answer all of the questions and solve the problems before writing a single line of code.&lt;/li&gt;
&lt;li&gt;The Opposite, is too few up-front design meetings.

&lt;ul&gt;
&lt;li&gt;From my point of view, we can go with this approach, but for every big problem, we have to set up a meeting with the team members to solve it in a proper way and all team members agree on one solution, also a proper communication way should be setup from day one, so by the time, we can build a solid solution, may it, not the best solution, but at least there is consistency, clear file structure, and not a spaghetti code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/David_A._Thomas_(software_developer)" rel="noopener noreferrer"&gt;Dave Thomas&lt;/a&gt; once said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Big design up-front is dump, but doing no design-up-front is even dumber.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>architecture</category>
      <category>tutorial</category>
      <category>essentials</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Frontend Architecture: The Architecture (Part. 1)</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Thu, 17 Aug 2023 07:10:05 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-1-4m6g</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-the-architecture-part-1-4m6g</guid>
      <description>&lt;h1&gt;
  
  
  1. What is "Frontend Architecture"?
&lt;/h1&gt;

&lt;p&gt;What is the first definition that will be popped into your mind when you hear "&lt;strong&gt;Frontend Architecture&lt;/strong&gt;"?&lt;br&gt;
I know that the definition may be a little bit vague, but let's try to think about some definitions we can conclude from our experiences and the books.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skeleton and File Structure&lt;/li&gt;
&lt;li&gt;The Big Picture&lt;/li&gt;
&lt;li&gt;Communications.&lt;/li&gt;
&lt;li&gt;Building Blocks&lt;/li&gt;
&lt;li&gt;A plan &lt;/li&gt;
&lt;li&gt;A blueprint&lt;/li&gt;
&lt;li&gt;Strategy and Vision&lt;/li&gt;
&lt;li&gt;Frameworks, Tools and Technical Direction.&lt;/li&gt;
&lt;li&gt;Blocks that are expensive to change later&lt;/li&gt;
&lt;li&gt;Technical Leadership&lt;/li&gt;
&lt;li&gt;Foundations&lt;/li&gt;
&lt;li&gt;Awareness of Constraints and Restrictions&lt;/li&gt;
&lt;li&gt;Business&lt;/li&gt;
&lt;li&gt;Standard and Guidelines&lt;/li&gt;
&lt;li&gt;Processes (e.g. Code Review, Git Flow, CICD)&lt;/li&gt;
&lt;li&gt;Path to achieve the Goal.&lt;/li&gt;
&lt;li&gt;Elegant (e.g. clean code, components design)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what do you think? Is there another definition you think about but not listed here?&lt;/p&gt;

&lt;p&gt;It is hard to find once and for good definition for the "Frontend Architecture" but in general we can say there are two common themes for the "Frontend Architecture". &lt;strong&gt;Frontend Architecture as a noun&lt;/strong&gt; and &lt;strong&gt;Frontend Architecture as a verb&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Architecture as a &lt;em&gt;noun&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;We can summarize as being about structure and the skeleton. It's about the decomposition of a product into a collection of smaller building blockers and the interactions/relationships between these building blocks.&lt;br&gt;
e.g. Building the main blocks like cross-cutting blocks that will communicate with other blocks like pages, containers and components. Cross-cutting blocks here like logging and exception handling blocks, http block, main managers or helpers like storage manager, etc. The file structure or the skeleton you will build by following some well-known patterns, like feature-first, component-first, type-first, MVC pattern, atomic pattern, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Architecture as a &lt;em&gt;verb&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;As a verb, the process of creating the architecture, is about translating the &lt;strong&gt;architectural drivers&lt;/strong&gt; (&lt;em&gt;functional requirements, non-functional requirements, constraints and principles&lt;/em&gt;) into a technical solution, technical roadmap, communicating the vision to a number of stakeholders both inside and outside the software development team and introducing the technical leadership.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Generally, the Frontend Architecture is a collection of tools and processes that aims to improve the quality of frontend code while creating a more efficient and sustainable workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Frontend (Application) Architecture
&lt;/h2&gt;

&lt;p&gt;In General, the Application Architecture is what we as software developers are probably the most familiar with.&lt;br&gt;
We have today different kinds of applications, like, Mobile apps, Backend apps, Frontend apps, and some other types of Apps. we can define an application as a single solid unit developed in a single technology or language.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes, we may have an "application" developed with different languages and technologies, for example, a micro-frontend application or a micro-service application. But in the end, we can say that each is a single unit.&lt;br&gt;
Application Architecture is about looking inside the app to understand how it is designed and built. This includes how this application has been broken down into small building blocks, and understanding the patterns, frameworks, and libraries in use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the end, the application architecture cares about what is happening deep inside this single-unit (a.k.a. application) and how it is built. &lt;/p&gt;

</description>
      <category>architecture</category>
      <category>tutorial</category>
      <category>essentials</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Frontend Architecture: Introduction</title>
      <dc:creator>Hamed Farag</dc:creator>
      <pubDate>Thu, 17 Aug 2023 07:08:41 +0000</pubDate>
      <link>https://dev.to/hamed_farag/frontend-architecture-introduction-1ii3</link>
      <guid>https://dev.to/hamed_farag/frontend-architecture-introduction-1ii3</guid>
      <description>&lt;h2&gt;
  
  
  An Introduction
&lt;/h2&gt;

&lt;p&gt;Over the last few years, the frontend evolved very fast, and many topics, frameworks, libraries, and techniques were introduced.&lt;/p&gt;

&lt;p&gt;I remember when the frontend developer/engineer used to be called a "UI Developer", and receive a design screen from the designer as a PSD (Photoshop Document File), and with his skills, he should extract the assets by slicing the needed icons, background or whatever he wants and then use these extracted images into the HTML and adjust them using the CSS, and of course, writes some JavaScript code (jQuery Code, to be more accurate) to add some interactivity to some elements like an open popup or confirmation dialogs and so on. And also write some CSS to add some padding, margin, and a lot of floats to match the design.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I can remember if someone writes some styles using any CSS Preprocessor like LESS or SASS, he will be categorized as a Geek Developer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But Now, do you think it is easy to create a simple frontend project without using any framework or library? The answer is *&lt;em&gt;YES *&lt;/em&gt;, of course, you can create a new one using the basics (HTML, CSS, and JavaScript), but &lt;u&gt;do you dare to do that&lt;/u&gt;?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgajt3lzi9f49eiek73e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffgajt3lzi9f49eiek73e.jpg" alt="New year, new frameworks?" width="474" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can you count, do you? okay, we have tons of libraries and frameworks, and each one of them resolves a problem in the real world or a problem in another library or framework. Also, a lot of techniques you should choose one of them, a simple example.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose one of the following to write your styles in your next project, (CSS, LESS, SASS, CSS-IN-JSS, or utility-first CSS).&lt;/li&gt;
&lt;li&gt;mmmmh&lt;/li&gt;
&lt;li&gt;Okay, whatever your choice, your choice is based on what?&lt;/li&gt;
&lt;li&gt;🤔🤔&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, in the series, we will talk about a lightweight guideline for Frontend Architecture and the aspects you should think about and consider while building your next project.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>architecture</category>
      <category>tutorial</category>
      <category>essentials</category>
    </item>
  </channel>
</rss>
