<?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: Ch Usama</title>
    <description>The latest articles on DEV Community by Ch Usama (@ch-usama).</description>
    <link>https://dev.to/ch-usama</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%2F887351%2Fcb87ca8d-d799-432b-9078-f10006734f5a.jpg</url>
      <title>DEV Community: Ch Usama</title>
      <link>https://dev.to/ch-usama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ch-usama"/>
    <language>en</language>
    <item>
      <title>How I Built a Modern Chrome Extension with React, Plasmo, and rrweb</title>
      <dc:creator>Ch Usama</dc:creator>
      <pubDate>Tue, 23 Sep 2025 15:22:06 +0000</pubDate>
      <link>https://dev.to/ch-usama/how-i-built-a-modern-chrome-extension-with-react-plasmo-and-rrweb-4bh8</link>
      <guid>https://dev.to/ch-usama/how-i-built-a-modern-chrome-extension-with-react-plasmo-and-rrweb-4bh8</guid>
      <description>&lt;p&gt;Browser session recording is a game-changer for QA, product teams, and user research. I recently built a Chrome extension that lets users record their “Golden Path” flows, manage projects, and upload recordings to the cloud—all with a modern React UI. In this post, I’ll walk you through the architecture, key challenges, and lessons learned, so you can build your own powerful browser extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Why Build a Session Recorder Extension?
&lt;/h2&gt;

&lt;p&gt;Manual bug reports and user feedback often miss crucial context. By capturing browser sessions, you can replay exactly what happened—making debugging, QA, and product feedback much more effective. My goal was to create an extension that’s easy to use, secure, and developer-friendly.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏗️ Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/src
   /components
     /popup
     /recorder
     /auth
   /contents
   popup.tsx
/lib
   /hooks
   /providers
   /services
   /types
/constants
   api.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scaffolding with Plasmo
&lt;/h2&gt;

&lt;p&gt;Plasmo makes it painless to set up a Chrome extension with React and TypeScript. It handles manifest generation, content script injection, and hot reloading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pnpm create plasmo
pnpm install
pnpm dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Technical Deep-Dive&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Architecture &amp;amp; Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React 18, TypeScript, Tailwind CSS, Plasmo (for Chrome extension scaffolding)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State &amp;amp; Data&lt;/strong&gt;: React Context, @tanstack/react-query for async state, zod for schema validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recording&lt;/strong&gt;: rrweb for capturing DOM events, rrweb-player for playback&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth&lt;/strong&gt;: Auth0 via Chrome’s identity API, with token management and error handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API&lt;/strong&gt;: Custom API client with error schemas, project and upload services, and integration with a backend (Atlas)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UX&lt;/strong&gt;: Modular popup UI with project dropdown, recording controls, and a draggable in-page recorder bar&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Screen Recording&lt;/strong&gt;: Uses rrweb to capture and serialize user interactions, storing events in Chrome’s local storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt;: Auth0 flow is triggered via Chrome’s identity API, with robust error handling and token management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Management&lt;/strong&gt;: Fetches and manages projects from the backend, allowing users to select a context for their recordings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI/UX&lt;/strong&gt;: Clean, responsive popup and in-page controls, with feedback for loading, errors, and upload status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Notable Implementation Details
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Plasmo Integration&lt;/strong&gt;: Leverages Plasmo for MV3 manifest, content script injection, and streamlined extension development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Safety&lt;/strong&gt;: Heavy use of TypeScript and zod for runtime and compile-time safety.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: Custom error classes and retry logic for API and auth failures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Hooks and providers abstract logic for recording, uploading, and project management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Developer Experience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linting &amp;amp; Formatting&lt;/strong&gt;: ESLint, Prettier, and Husky for pre-push checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scripts&lt;/strong&gt;: pnpm dev, pnpm build, and pnpm lint for a smooth workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plasmo&lt;/strong&gt;: Hot reloads and easy manifest management.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💡 Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OAuth in Extensions&lt;/strong&gt;: Chrome’s identity API is powerful but has quirks—test thoroughly!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Management&lt;/strong&gt;: React Context + react-query is a great combo for async data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: Invest in good error messages and retries, especially for auth and uploads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience&lt;/strong&gt;: A clean, simple UI makes a big difference for adoption.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📝 Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a modern Chrome extension is easier than ever with the right tools. Plasmo, React, and rrweb let you focus on features, not boilerplate. If you’re thinking about building your own extension, I hope this guide helps you get started!&lt;/p&gt;

</description>
      <category>plasmo</category>
      <category>webdev</category>
      <category>react</category>
      <category>chromeextension</category>
    </item>
    <item>
      <title>React Form Conditional Validation with Formik and Yup (Custom Hooks)</title>
      <dc:creator>Ch Usama</dc:creator>
      <pubDate>Tue, 05 Jul 2022 16:11:45 +0000</pubDate>
      <link>https://dev.to/ch-usama/react-form-conditional-validation-with-formik-and-yup-custom-hooks-14dj</link>
      <guid>https://dev.to/ch-usama/react-form-conditional-validation-with-formik-and-yup-custom-hooks-14dj</guid>
      <description>&lt;p&gt;&lt;strong&gt;In this article, you will fastly start using Formik and Yup(Conditional) with custom hooks in your React project.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Formik is using for building forms in React. Formik is providing lots of feature (less code, easy maintable, custom hooks, easy integrate and more)that making life easier while creating forms.  You can easily build schema for validation with Yup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Formik
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npm i formik&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Yup
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;npm i yup&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction of Formik
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Getting values in and out of form state&lt;/li&gt;
&lt;li&gt;Validation and error messages&lt;/li&gt;
&lt;li&gt;Handling form submission
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simple form with formik&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFormik&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;formik&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;SignupForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;values&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="nf"&gt;alert&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;values&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Email Address&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;formik&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Problem statement
&lt;/h2&gt;

&lt;p&gt;The problem is that formik form has two inputs. One is select and other is text input select has two option 'yes' or 'no'. If user select the 'Yes' then user must write about the dish on the other hand if user select the 'no' there is no validation.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;I had a formik form where I needed to enter the passphrase if it was required and make it optional if it wasn't required. While validating the field using 'Yup' I needed a way to conditionally change the validation logic for the field. For this, I need to use the &lt;strong&gt;when()&lt;/strong&gt; function from Yup which allows us to change the validation logic applied to a field based on some conditions. After this I pass the values with and make condition that if user select the Yes (User want to eat chicken)from the option then user must write about chicken dishes which one user want otherwise no condition. Write about the dish depend on the user selection. &lt;/p&gt;
&lt;h2&gt;
  
  
  Formik useFormik custom hook
&lt;/h2&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;formik&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFormik&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;initialValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dropdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ChickenDish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Yup Schema
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;validationSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dropdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;ChickenDish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dropdown&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="na"&gt;is&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dropdown&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;dropdown&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Yes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;then&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Yup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;* Required&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;h2&gt;
  
  
  Example
&lt;/h2&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://yqn631.csb.app" rel="noopener noreferrer"&gt;
      yqn631.csb.app
    &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>react</category>
      <category>formik</category>
      <category>yup</category>
      <category>materialui</category>
    </item>
  </channel>
</rss>
