<?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: Ken Kaneki gh</title>
    <description>The latest articles on DEV Community by Ken Kaneki gh (@kenkanekigh).</description>
    <link>https://dev.to/kenkanekigh</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%2F4102637%2F16635ee3-3e7d-4105-9e6f-5f296d5969ef.jpg</url>
      <title>DEV Community: Ken Kaneki gh</title>
      <link>https://dev.to/kenkanekigh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kenkanekigh"/>
    <language>en</language>
    <item>
      <title>Architecting Scalable Role-Based Access Control (RBAC) for Enterprise Dashboards</title>
      <dc:creator>Ken Kaneki gh</dc:creator>
      <pubDate>Sat, 05 Sep 2026 10:41:56 +0000</pubDate>
      <link>https://dev.to/kenkanekigh/architecting-scalable-role-based-access-control-rbac-for-enterprise-dashboards-595f</link>
      <guid>https://dev.to/kenkanekigh/architecting-scalable-role-based-access-control-rbac-for-enterprise-dashboards-595f</guid>
      <description>&lt;p&gt;When building standard consumer applications, handling user permissions is usually straightforward: you have a standard user, an admin, and maybe a moderator. But the moment you step into the enterprise world, authorization logic becomes one of the most complex architectural hurdles you will face.&lt;/p&gt;

&lt;p&gt;If you are tasked with building a dashboard for a large organization, a simple &lt;code&gt;isAdmin&lt;/code&gt; boolean in your database will no longer cut it. Let's dive into how to properly architect Role-Based Access Control (RBAC) for scale on the frontend.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Real-World Challenge
&lt;/h3&gt;

&lt;p&gt;Imagine you are developing a workforce management system. In massive internal portals—similar to the retail scheduling and payroll networks running over at &lt;a href="https://mysainsbury.com/" rel="noopener noreferrer"&gt;mysainsbury&lt;/a&gt;—the system has to dynamically render different UIs for cashiers, store managers, regional directors, and HR payroll staff. &lt;/p&gt;

&lt;p&gt;If you hardcode these roles directly into your UI components, your codebase will quickly become a nightmare of nested &lt;code&gt;if/else&lt;/code&gt; statements. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Decoupling Roles from Permissions
&lt;/h3&gt;

&lt;p&gt;The biggest mistake developers make is checking against &lt;strong&gt;Roles&lt;/strong&gt; instead of &lt;strong&gt;Permissions&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Bad Approach (Role-Based Check):&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;store_manager&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApproveShiftButton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens when a 'regional_director' also needs to approve shifts? You have to refactor every single component.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Good Approach (Permission-Based Check):&lt;/strong&gt;&lt;br&gt;
Instead, map roles to specific permissions at your application's entry point, and let the UI check for the permission.&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;// permissions.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ROLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;STAFF&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="s1"&gt;view_schedule&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;view_payslip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;MANAGER&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="s1"&gt;view_schedule&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;edit_schedule&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;approve_shifts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;HR&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="s1"&gt;view_payroll&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;edit_benefits&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hasPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;action&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;return&lt;/span&gt; &lt;span class="nx"&gt;ROLES&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userRole&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="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, your UI component becomes beautifully clean and scalable:&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="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;hasPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approve_shifts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApproveShiftButton&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Securing the Routes
&lt;/h3&gt;

&lt;p&gt;Frontend route protection is just for UX; the real security always happens on your backend API. However, failing to protect routes on the frontend leads to a clunky user experience. &lt;/p&gt;

&lt;p&gt;Instead of wrapping every single page component in a Higher Order Component (HOC), utilize a centralized layout wrapper:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProtectedRoute&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;requiredPermission&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuth&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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Redirect&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="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="nf"&gt;hasPermission&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requiredPermission&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UnauthorizedView&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Enterprise UI architecture is all about planning for scale. By decoupling your UI from hardcoded roles and relying entirely on a strict permissions matrix, you ensure that when the business logic inevitably changes, your frontend codebase won't need a massive rewrite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'd love to hear your thoughts!&lt;/strong&gt; &lt;br&gt;
How do you handle complex RBAC in your current projects? Do you prefer managing permissions on the client, or completely driving the UI state from the backend API? Leave your questions or approaches in the comments below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>architecture</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>3 Important Lessons I Learned Building My Chrome Extension (Manifest V3)</title>
      <dc:creator>Ken Kaneki gh</dc:creator>
      <pubDate>Mon, 31 Aug 2026 11:30:02 +0000</pubDate>
      <link>https://dev.to/kenkanekigh/3-important-lessons-i-learned-building-my-chrome-extension-manifest-v3-32ab</link>
      <guid>https://dev.to/kenkanekigh/3-important-lessons-i-learned-building-my-chrome-extension-manifest-v3-32ab</guid>
      <description>&lt;p&gt;Hey GUYSS!&lt;/p&gt;

&lt;p&gt;This is my first post here! I’ve been reading amazing tutorials on this platform for a while, and I finally decided to contribute by sharing a recent project of mine.&lt;/p&gt;

&lt;p&gt;Recently, I decided to dive into browser extension development and built my own Chrome Extension called &lt;strong&gt;LinkHunter Pro&lt;/strong&gt;. Basically, it helps web developers and SEO professionals easily find broken links, analyze page structures, and streamline their link-building research without leaving the browser.&lt;/p&gt;

&lt;p&gt;While building it, I had to learn the new Manifest V3 architecture. If you are planning to build your own extension soon, here are 3 quick lessons I learned along the way:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Service Workers are the new Background Pages
&lt;/h2&gt;

&lt;p&gt;If you are coming from Manifest V2, this is the biggest shift. You can no longer rely on persistent background scripts. Instead, you have to use Service Workers that wake up, do their job, and shut down. My tip: Make sure you don't store local state in your service worker variables! Always use chrome.storage to save data between events.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Keep the Popup UI Lightning Fast
&lt;/h2&gt;

&lt;p&gt;The popup HTML page closes the moment the user clicks anywhere outside of it. I learned that you should keep the popup UI extremely lightweight. I used vanilla JavaScript and minimal CSS to ensure the popup renders instantly. If it takes even a second to load, the user experience drops massively.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Ask for Permissions Carefully
&lt;/h2&gt;

&lt;p&gt;The Chrome Web Store review process is much stricter now. Initially, I asked for broad host permissions, but I quickly realized it's better to use activeTab permission wherever possible. It gives you temporary access to the tab the user is currently on without triggering scary security warnings during installation.&lt;/p&gt;

&lt;p&gt;Over to you! Have you ever built a browser extension? What was your biggest challenge when working with Manifest V3 or browser APIs? I'd love to hear your experiences in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chromeextension</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
  </channel>
</rss>
