<?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: Achmad Junaedi</title>
    <description>The latest articles on DEV Community by Achmad Junaedi (@juna_go15).</description>
    <link>https://dev.to/juna_go15</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4096507%2F720b974c-02b1-46bb-aeb3-d49b3f130679.jpg</url>
      <title>DEV Community: Achmad Junaedi</title>
      <link>https://dev.to/juna_go15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/juna_go15"/>
    <language>en</language>
    <item>
      <title>Ditched React for our school marketplace app 👇 Bundle: &lt;50KB. Load time on a $80 Android: 320ms. Story + architecture breakdown here #DEVCommunity #webdev</title>
      <dc:creator>Achmad Junaedi</dc:creator>
      <pubDate>Wed, 09 Sep 2026 08:44:07 +0000</pubDate>
      <link>https://dev.to/juna_go15/ditched-react-for-our-school-marketplace-app-bundle-50kb-load-time-on-a-80-android-320ms-1dnl</link>
      <guid>https://dev.to/juna_go15/ditched-react-for-our-school-marketplace-app-bundle-50kb-load-time-on-a-80-android-320ms-1dnl</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl" class="crayons-story__hidden-navigation-link"&gt;Building a High-Speed School Marketplace: Why We Ditched Frameworks for Vanilla JS &amp;amp; PWA&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="/juna_go15" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4096507%2F720b974c-02b1-46bb-aeb3-d49b3f130679.jpg" alt="juna_go15 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/juna_go15" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Achmad Junaedi
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Achmad Junaedi
                
                
              
              &lt;div id="story-author-preview-content-4612886" 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="/juna_go15" 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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4096507%2F720b974c-02b1-46bb-aeb3-d49b3f130679.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Achmad Junaedi&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/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 9&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/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl" id="article-link-4612886"&gt;
          Building a High-Speed School Marketplace: Why We Ditched Frameworks for Vanilla JS &amp;amp; PWA
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/javascript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;javascript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/pwa"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;pwa&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&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/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;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;
            4 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a High-Speed School Marketplace: Why We Ditched Frameworks for Vanilla JS &amp; PWA</title>
      <dc:creator>Achmad Junaedi</dc:creator>
      <pubDate>Wed, 09 Sep 2026 08:08:41 +0000</pubDate>
      <link>https://dev.to/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl</link>
      <guid>https://dev.to/juna_go15/building-a-high-speed-school-marketplace-why-we-ditched-frameworks-for-vanilla-js-pwa-27dl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5tqkckzl916fyvzqo9h6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5tqkckzl916fyvzqo9h6.webp" alt=" " width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the modern web ecosystem, starting any web project without reaching for React, Next.js, Vue, or Svelte has almost become taboo. Yet, when our team at &lt;strong&gt;&lt;a href="https://setvy.id" rel="noopener noreferrer"&gt;Setvy&lt;/a&gt;&lt;/strong&gt; sat down to architect Aksara-Mart—a digital marketplace serving thousands of students and teachers across our vocational high school—we made an intentional, contrarian decision:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Decision:&lt;/strong&gt; We threw out all third-party frontend frameworks and built the entire user interface in pure Vanilla JavaScript, modern modular CSS, and Progressive Web App (PWA) standards.&lt;/p&gt;

&lt;p&gt;Why? Because when your primary user base consists of students using second-hand, $80 entry-level Android phones connected to crowded school Wi-Fi, developer convenience cannot come at the expense of end-user performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Reality of School Hardware and Campus Networks
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code, we profiled our target environment in real classroom conditions:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Hardware Constraints&lt;/strong&gt;: Approximately 65% of students carry entry-level devices with 2GB to 3GB of RAM, powered by aging Quad-core MediaTek chips or Snapdragon 400-series processors.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Network Bottlenecks&lt;/strong&gt;: During recess spikes, hundreds of students connect to the campus Wi-Fi simultaneously, dropping effective bandwidth to congested 2G/3G speeds.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;The 15-Minute Recess Rush&lt;/strong&gt;: Students have exactly 15 minutes between bells to browse the canteen menu, order food, and pick it up. A 4-second loading screen means they literally don't get lunch.&lt;/p&gt;

&lt;p&gt;A barebones Next.js or React e-commerce template typically ships 250 KB to 500 KB of minified JavaScript. On a modern M3 MacBook or iPhone 16, parsing 300 KB of JS takes 15 milliseconds. On a budget Android phone, it takes &lt;strong&gt;1,200 to 2,500 milliseconds&lt;/strong&gt;. This latency manifests as Hydration Lag (Total Blocking Time): the page looks rendered, but tapping the 'Order' button does nothing because the main JavaScript thread is frozen during hydration.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Architecture: Under 50 KB and 60 FPS
&lt;/h2&gt;

&lt;p&gt;By returning to web fundamentals, we achieved blistering performance:&lt;br&gt;
• &lt;strong&gt;Total Initial Payload&lt;/strong&gt;: &amp;lt; 48 KB (gzipped JS + CSS bundle).&lt;br&gt;
• &lt;strong&gt;First Contentful Paint (FCP)&lt;/strong&gt;: ~320 ms on real school 4G.&lt;br&gt;
• &lt;strong&gt;Time to Interactive (TTI)&lt;/strong&gt;: Instantaneous, zero hydration lag.&lt;/p&gt;

&lt;p&gt;The project structure remains clean, modular, and maintainable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aksaramart/
├── public/
│   ├── index.html       # Semantic HTML5 shell &amp;amp; modal templates
│   ├── skripmart.js     # Modular Vanilla JS logic (~35 KB)
│   ├── stylemart.css    # Clean CSS Variables design system
│   ├── sw.js            # PWA Service Worker for offline asset caching
│   └── manifest.json    # Progressive Web App configuration

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Clean Patterns for Vanilla JS State &amp;amp; DOM
&lt;/h2&gt;

&lt;p&gt;Building with Vanilla JS doesn't mean writing spaghetti code. We used modern ES6+ patterns, isolated state stores, and memory-efficient Event Delegation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pattern A: Modular State Store Without Third-Party Libraries&lt;/strong&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="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt;   &lt;span class="nc"&gt;JAVASCRIPT &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SKRIPMART&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// A lightweight, reactive-free state store (skripmart.js)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aksara_cart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;activeCategory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveCart&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&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="s1"&gt;aksara_cart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;renderCartBadge&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addToCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;productId&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;existing&lt;/span&gt;&lt;span class="p"&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;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;qty&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;qty&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;appState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;qty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;saveCart&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;renderCartUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern B: Memory-Efficient Event Delegation&lt;/strong&gt;&lt;br&gt;
Instead of binding individual click listeners to hundreds of menu cards (which bloats browser memory on low-end phones), we attach a single event listener to the parent container:&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="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt;   &lt;span class="nc"&gt;JAVASCRIPT &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SKRIPMART&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Only 1 single event listener for the entire product catalog grid&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="s1"&gt;catalogGrid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-action="add-to-cart"]&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;btn&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;addToCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Smooth native CSS micro-animation without any external animation library&lt;/span&gt;
    &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scale-bounce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scale-bounce&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Making It a True App: Progressive Web App (PWA) Standards
&lt;/h2&gt;

&lt;p&gt;Most students won't download a canteen app from Google Play or Apple App Store due to limited phone storage. With PWA standards, the app installs instantly to their home screen directly from the browser in 1 tap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Custom 'Install App' Topbar Trigger&lt;/strong&gt;&lt;br&gt;
We intercept the native beforeinstallprompt event to present a prominent, branded install button in the top navigation:&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="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt;   &lt;span class="nc"&gt;JAVASCRIPT &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PWA&lt;/span&gt; &lt;span class="nx"&gt;INSTALL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deferredPrompt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;installBtn&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="s1"&gt;installAppBtn&lt;/span&gt;&lt;span class="dl"&gt;'&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="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;beforeinstallprompt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Prevent default clunky mini-infobar&lt;/span&gt;
    &lt;span class="nx"&gt;deferredPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&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;installBtn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;installBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inline-flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Reveal our button&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;installBtn&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;deferredPrompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;deferredPrompt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;outcome&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;deferredPrompt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userChoice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User install outcome: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;deferredPrompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;installBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;b. Cache-First Service Worker (sw.js)&lt;/strong&gt;&lt;br&gt;
To ensure the catalog opens instantly even when students walk through hallways with dead Wi-Fi zones, the Service Worker caches all core app shell assets:&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="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt; &lt;span class="err"&gt;●&lt;/span&gt;   &lt;span class="nx"&gt;JAVASCRIPT&lt;/span&gt; &lt;span class="nx"&gt;SERVICE&lt;/span&gt; &lt;span class="nc"&gt;WORKER &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;SW&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CACHE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aksaramart-v1.4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;STATIC_ASSETS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/index.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/skripmart.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/stylemart.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/manifest.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/icons/icon-192.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;install&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CACHE_NAME&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;STATIC_ASSETS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skipWaiting&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Forward Supabase database REST &amp;amp; RPC calls directly to network&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="s1"&gt;/rest/v1/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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="s1"&gt;/rpc/&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="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Serve static assets directly from local cache&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respondWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;caches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. The Performance Verdict: Real-World Lighthouse Audit
&lt;/h2&gt;

&lt;p&gt;We executed Lighthouse audits on an emulated low-end Moto G4 device throttled to slow 3G network conditions:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffwgqyag34qpk6tqoa9p4.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffwgqyag34qpk6tqoa9p4.png" alt=" " width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Conclusion
&lt;/h2&gt;

&lt;p&gt;Ditching frameworks for Vanilla JS proved to be a resounding success for our students and teachers. The app launches immediately, remains completely immune to hydration freezes, and preserves scarce phone battery and memory.&lt;/p&gt;

&lt;p&gt;However, a fast frontend is completely meaningless if the underlying database is vulnerable. How do we secure transaction data from curious IT students who open Inspect Element to try altering menu prices from $1.50 to $0.01?&lt;/p&gt;

&lt;p&gt;In the next article, we dive deep into our Zero-Trust security architecture using Supabase Row Level Security (RLS) and multi-role governance.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>pwa</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Stopped Using Gemini 3.1 Pro for Agentic Coding — Why I Moved to Gemini 3.7 Flash High Mode</title>
      <dc:creator>Achmad Junaedi</dc:creator>
      <pubDate>Tue, 01 Sep 2026 11:32:50 +0000</pubDate>
      <link>https://dev.to/juna_go15/i-stopped-using-gemini-31-pro-for-agentic-coding-why-i-moved-to-gemini-37-flash-high-mode-43hf</link>
      <guid>https://dev.to/juna_go15/i-stopped-using-gemini-31-pro-for-agentic-coding-why-i-moved-to-gemini-37-flash-high-mode-43hf</guid>
      <description>&lt;p&gt;I landed my first Point of Sale (POS) SaaS client project and built it inside &lt;strong&gt;Google Antigravity&lt;/strong&gt;, trusting &lt;strong&gt;Gemini 3.1 Pro&lt;/strong&gt; for all agentic coding. Bad move. Midway through, severe bugs hit—fixing sales inputs completely broke my dashboard analytics.&lt;/p&gt;

&lt;p&gt;Frustrated, I switched to the GPT stack (Codex, GPT-5.5, GPT-5.6 Sol). But that brought a new headache: token quotas drained in minutes and API bills went through the roof.&lt;/p&gt;

&lt;p&gt;The breakthrough? Community stats on Agent Arena showed Flash models beating 3.1 Pro in agentic tasks. Desperate, I tested &lt;strong&gt;Gemini 3.6 Flash&lt;/strong&gt; and it was surprisingly solid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Beginning: Falling for 3.1 Pro Hype&lt;/strong&gt;&lt;br&gt;
When Google dropped Gemini 3.1 Pro in February 2026, tech Twitter hyped its ARC-AGI-2 benchmark scores as the ultimate problem solver.&lt;br&gt;
Early on, 3.1 Pro handled high-level whiteboard concepts fine:&lt;br&gt;
• &lt;strong&gt;System Architecture&lt;/strong&gt;: Mapping schemas and ERDs.&lt;br&gt;
• &lt;strong&gt;Business Logic&lt;/strong&gt;: Outlining business logic flows.&lt;br&gt;
• &lt;strong&gt;Edge Cases&lt;/strong&gt;: Spotting potential edge cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Client Pressure &amp;amp; Regression Hell&lt;/strong&gt;&lt;br&gt;
I secured a major deal with a client who paid 50% upfront. Expectations were high, and that's where things went downhill.&lt;br&gt;
A retail POS requires tight database relations: transactions, inventory sync, multi-outlet stock, and live dashboard revenue summaries. When I instructed Gemini 3.1 Pro in Antigravity to build the sales input module:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fatal Regressions:&lt;/strong&gt; The sales input worked, but the dashboard suddenly went crazy. The model rewrote existing SQL aggregation queries without respecting cross-module dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lost Query Logic&lt;/strong&gt;: It repeatedly forgot critical database filter conditions (like tenant IDs or soft-delete flags), causing messy data anomalies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deadline Panic&lt;/strong&gt;: The client wanted deliverables per contract, and I was sweating because the code kept breaking.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3. Fleeing to GPT &amp;amp; The Token Trap&lt;/strong&gt;&lt;br&gt;
Panicking about deadlines, I switched to the OpenAI ecosystem:&lt;br&gt;
• &lt;strong&gt;Codex / GPT-5.5 (Medium)&lt;/strong&gt;: Daily coding assistant.&lt;br&gt;
• &lt;strong&gt;GPT-5.5 (High Reasoning)&lt;/strong&gt;: Complex SQL logic.&lt;br&gt;
• &lt;strong&gt;GPT-5.6 Sol&lt;/strong&gt;: Heavy artillery for deep debugging.&lt;br&gt;
While reasoning was solid, a new problem popped up: tokens burned out insanely fast.&lt;/p&gt;

&lt;p&gt;Running heavy models like GPT-5.6 Sol and 5.5 High across autonomous agentic loops burned quotas in no time. I needed a workhorse that didn't drain my wallet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Community Outrage: It Wasn't Just Me&lt;/strong&gt;&lt;br&gt;
My frustration wasn't unique. On the &lt;a href="https://discuss.ai.google.dev/t/unacceptable-antigravity-quotas-for-gemini-3-1-pro-workflow-completely-blocked/124971" rel="noopener noreferrer"&gt;Google AI Developers Forum&lt;/a&gt; , a thread titled "Unacceptable Antigravity Quotas for Gemini 3.1 Pro – Workflow Completely Blocked!" had racked up roughly 60 upvotes and 19 replies within days.&lt;/p&gt;

&lt;p&gt;One developer, Hauke_Walden, summed up the core complaint: "...it is totally unacceptable that the quota usage is so intransparent, and even worse, the totally random 'refresh' policy... It's like a car that sometimes works, sometimes it doesn't. That's ok for a hobbyist and his vintage car, but not for a cab driver."&lt;/p&gt;

&lt;p&gt;Another, madnz-08, described a specific bug: "Yesterday my quota dropped from 60% to 0% without any prompt, and the worst part was seeing the reset time set to 50+ hours."&lt;/p&gt;

&lt;p&gt;A third, MrTos, put it bluntly: "It is unacceptable to be stuck at 10 prompts on Gemini 3.1."&lt;/p&gt;

&lt;p&gt;The pattern in the thread was consistent: vanishing quotas, lockout timers reported as high as 133–167 hours, and reports of paying developers getting locked out mid-project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. The Pivot: Testing Gemini 3.6 Flash&lt;/strong&gt;&lt;br&gt;
Hunting for a leaner alternative, I saw rankings on Agent Arena praising Flash models for agentic tool use.&lt;br&gt;
Curious, I tested Gemini 3.6 Flash in Antigravity:&lt;br&gt;
• &lt;strong&gt;Blazing Speed&lt;/strong&gt;: Instant feedback loops without lag.&lt;br&gt;
• &lt;strong&gt;Quota Sanity&lt;/strong&gt;: No panic about hitting rate limits mid-session.&lt;br&gt;
• &lt;strong&gt;Sane Diffs&lt;/strong&gt;: It stayed in its lane without aggressively trashing outside files.&lt;br&gt;
It proved lightweight models were getting unwarranted hate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. August: Brother's WhatsApp Tip &amp;amp; The Jump to 3.7 Flash&lt;/strong&gt;&lt;br&gt;
In August, my younger brother sent me a WhatsApp message: "Bro, Google just dropped Gemini 3.7 Flash."&lt;br&gt;
As reported by &lt;a href="https://venturebeat.com/technology/googles-gemini-3-7-flash-targets-coding-and-agents-with-a-50-introductory-price-cut" rel="noopener noreferrer"&gt;VentureBeat&lt;/a&gt;, Google  built 3.7 Flash specifically for coding and agentic loops, with a 50% introductory discount ($0.75 / 1M input, $3.75 / 1M output).&lt;br&gt;
Having seen good results with 3.6 Flash, I wanted to see if Google really pulled off deep reasoning on a Flash model without killing speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. The Proof: Gemini 3.7 Flash (High Mode) in Antigravity&lt;/strong&gt;&lt;br&gt;
I opened Antigravity, picked Gemini 3.7 Flash, and enabled Thinking Mode: High. The leap in quality was immediate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blazing Fast &amp;amp; Token-Efficient&lt;/strong&gt; Inference stayed snappy even with extended thinking on. In fast agent loops, code fixes felt instant without distracting pauses, while token burn remained low.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex Database Queries Handled Smoothly&lt;/strong&gt; Any fear that Flash would choke on multi-table queries disappeared. It surgically edited the sales module without touching outside files, kept dashboard queries in sync, and maintained schema rules without destructive side effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaner Code &amp;amp; Only Minor Tweaks&lt;/strong&gt; There were a few minor formatting adjustments, but the code structure was clean. Those small tweaks took one quick prompt to fix—not fatal structural bugs. I delivered the client project right on time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
This client project taught me a valuable lesson: in daily agentic coding, diff discipline, fast inference, and token efficiency matter way more than benchmark scores on paper.&lt;br&gt;
From Agent Arena tests with 3.6 Flash to the leap in Gemini 3.7 Flash, it proved Flash models with thinking mode aren't just "cheap alternatives"—they are solid workhorses that handle heavy code cleanly and safely.&lt;br&gt;
If you're building a SaaS and stuck between regression bugs or sky-high token bills, give Gemini 3.7 Flash a run in Google Antigravity.&lt;/p&gt;

&lt;p&gt;Written by Achmad Junaedi — Founder of &lt;a href="https://setvy.id/" rel="noopener noreferrer"&gt;setvy.id&lt;/a&gt; &amp;amp; Vocational Educator at SMKN 10 Surabaya, Indonesia.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>saas</category>
      <category>database</category>
    </item>
  </channel>
</rss>
