<?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: Ashik Varma</title>
    <description>The latest articles on DEV Community by Ashik Varma (@ashikvarma11).</description>
    <link>https://dev.to/ashikvarma11</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%2F402321%2F69ed890f-d87f-47e3-a422-fa1fda3ba54a.jpeg</url>
      <title>DEV Community: Ashik Varma</title>
      <link>https://dev.to/ashikvarma11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashikvarma11"/>
    <language>en</language>
    <item>
      <title>The Code Review Killer: Ditch Manual Checks with this n8n &amp; GPT Automation Guide</title>
      <dc:creator>Ashik Varma</dc:creator>
      <pubDate>Tue, 02 Dec 2025 03:07:05 +0000</pubDate>
      <link>https://dev.to/ashikvarma11/the-code-review-killer-ditch-manual-checks-with-this-n8n-gpt-automation-guide-5g1a</link>
      <guid>https://dev.to/ashikvarma11/the-code-review-killer-ditch-manual-checks-with-this-n8n-gpt-automation-guide-5g1a</guid>
      <description>&lt;p&gt;Have you ever wished you had a code review assistant of your own that could instantly give feedback on each new Pull Request (PR)?&lt;/p&gt;

&lt;p&gt;Manual code reviews are a necessary part of the development process, but they are expensive, slow, and inconsistent. As of writing this article, tools like GitHub Copilot's Code Review feature are premium, requiring subscriptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copilot Pro:&lt;/strong&gt; ($10 USD/month or $100/year)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copilot Pro+:&lt;/strong&gt; ($39 USD/month or $390/year)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Can we achieve this within a reduced budget? YES.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article is designed to help you build your own persistent, automated AI Code Review Assistant hosted for free (or near-free) using a powerful, controlled workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Role in the System&lt;/th&gt;
&lt;th&gt;Why We Use It&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;n8n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Workflow Creation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;An AI workflow automation tool that connects GitHub to OpenAI, manages the logic, and formats the output.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;NHost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Managed Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides a free-tier, managed &lt;strong&gt;PostgreSQL&lt;/strong&gt; database where n8n stores all workflow data and credentials.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Hosting n8n&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hosts our n8n web service, assigns a domain URL, and connects to the NHost database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenAI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Review Code&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Provides the LLM intelligence to critique the code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Why PostgreSQL (NHost) over SQLite?
&lt;/h3&gt;

&lt;p&gt;n8n uses SQLite by default, which is great for local development but does not support highly concurrent transactions and struggles with scalability. We need a solution that can scale and adapt based on the number of Pull Requests being raised to the repository. NHost provides a free tier that fits well for a personal project while offering PostgreSQL's stability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database Setup and Hosting
&lt;/h2&gt;

&lt;p&gt;I have followed the exact steps mentioned in this article → &lt;a href="https://dev.to/singhamandeep007/the-ultimate-guide-to-self-hosting-n8n-for-free-using-render-and-nhost-2d69"&gt;The Ultimate Guide to Self-Hosting n8n for Free using Render and Nhost - DEV Community&lt;/a&gt; to set up the underlying infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Create an account in NHost, start a project, and set up a Database. This will generate environment variables as mentioned in the post.&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%2Fte6k0tkob8r3vjdduenu.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%2Fte6k0tkob8r3vjdduenu.png" alt="NHost Setup" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Sign up for an account on Render, create a new Web Service, and choose &lt;strong&gt;n8nio/n8n:latest&lt;/strong&gt; as the Docker image. Add the environment variables generated in NHost to the Render project.&lt;/p&gt;

&lt;p&gt;This will host your n8n application on the cloud and generate a domain name.&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%2Fa2e8pj0sjqo2jwg7npfx.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%2Fa2e8pj0sjqo2jwg7npfx.png" alt="Render Setup" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;To ensure GitHub can reach your bot, you must correct the webhook URL inside n8n. Set the following environment variables in your &lt;strong&gt;Render Web Service settings&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;WEBHOOK_URL&lt;/code&gt;: &lt;code&gt;https://[your-render-domain].onrender.com/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;N8N_HOST&lt;/code&gt;: &lt;code&gt;[your-render-domain].onrender.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;N8N_PROTOCOL&lt;/code&gt;: &lt;code&gt;https&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Credentials Required
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GitHub Access Token:&lt;/strong&gt; Generate a Personal Access Token from your GitHub settings and ensure it has the &lt;strong&gt;repo&lt;/strong&gt; scope checked (required for reading and commenting).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI API Key:&lt;/strong&gt; You'll need an active key. If you are a new user, you might have received free trial credits, but many users now need to pay the minimum of $5 to activate the key and avoid the &lt;strong&gt;insufficient_quota&lt;/strong&gt; error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost Control:&lt;/strong&gt; I have used &lt;strong&gt;gpt-5-nano&lt;/strong&gt; for this project as it consumes the fewest tokens. You can use any capable model you wish, but remember that the &lt;strong&gt;Mini&lt;/strong&gt; models offer the best balance of power and cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Workflow
&lt;/h2&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%2Fy2cgj9eexkvmrji4anak.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%2Fy2cgj9eexkvmrji4anak.png" alt="Workflow Diagram" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In N8n, you’ll find a list of actions in the right pane that you can drag and drop to the canvas. The actions needed for our workflow are &lt;strong&gt;Github Trigger&lt;/strong&gt;, &lt;strong&gt;HttpRequest&lt;/strong&gt;, &lt;strong&gt;Code in JS&lt;/strong&gt;, &lt;strong&gt;OpenAI&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Github Trigger
&lt;/h3&gt;

&lt;p&gt;In Github, generate an Access Token from the settings and provide all access.&lt;/p&gt;

&lt;p&gt;In the right pane inside n8n, search “&lt;strong&gt;Github&lt;/strong&gt;”, and drag and drop “&lt;strong&gt;on a pull request&lt;/strong&gt;” trigger. This will add the same to your canvas as the first step. Click on the item to open the settings.&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%2F2oswhuqwd28qnrvcmime.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%2F2oswhuqwd28qnrvcmime.png" alt="Github Trigger" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once saved, the GitHub Trigger node will display a unique &lt;strong&gt;Webhook URL&lt;/strong&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%2F4kn2m4u3ntewq22o52jw.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%2F4kn2m4u3ntewq22o52jw.png" alt="Webhook URL" width="635" height="892"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching the Code Diff
&lt;/h3&gt;

&lt;p&gt;The goal is to fetch the raw code changes from the PR event data. The previous node provides an object containing the PR details. You must construct the GitHub API URL to get the file changes. For simplicity, you can often grab the &lt;strong&gt;{{ $json.body.pull_request.url }}/files&lt;/strong&gt; to get the list of files in the PR. This HTTP request needs to use the &lt;strong&gt;GitHub Access Token credential&lt;/strong&gt; for authorization.&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%2Fjg2bre0m3htc58hdrp1s.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%2Fjg2bre0m3htc58hdrp1s.png" alt="Fetching Code Diff" width="582" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining the AI Persona
&lt;/h3&gt;

&lt;p&gt;The next step is to define the prompt for OpenAI to start reviewing your PR. Inject &lt;strong&gt;reviewPrompt&lt;/strong&gt; to define the AI's role, ensuring high-quality, structured feedback. Paste a detailed prompt into this node. The persona &lt;strong&gt;"Senior Software Engineer"&lt;/strong&gt; is vital for quality and technical feedback. This node structures the prompt and the code diff into the format expected by the OpenAI Chat Model. Add your own customizations inside the &lt;strong&gt;instructions&lt;/strong&gt; variable.&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%2F7ok4wlfodgmy7x4khc63.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%2F7ok4wlfodgmy7x4khc63.png" alt="Defining AI Persona" width="800" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating the Review
&lt;/h3&gt;

&lt;p&gt;This is the step where you integrate OpenAI into the workflow. Select the cheapest capable model, such as gpt-5-nano. In the node settings, map the variables from the previous Function node. Add the API key that was generated previously.&lt;/p&gt;

&lt;p&gt;Drag and drop &lt;strong&gt;{{$json.reviewPrompt}}&lt;/strong&gt; to the &lt;strong&gt;Prompt&lt;/strong&gt; field.&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%2Fdm7yt2oru59xl8flml1n.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%2Fdm7yt2oru59xl8flml1n.png" alt="Generating Review" width="800" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Formatting the Output
&lt;/h3&gt;

&lt;p&gt;This is the node labeled "Translate to Github version" in the diagram. The goal is to take the raw Markdown text generated by OpenAI and wrap it in the exact JSON payload required by the GitHub Comments API.&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%2F90l05j6k5rftj2ixbfqj.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%2F90l05j6k5rftj2ixbfqj.png" alt="Formatting Output" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Posting the Comment
&lt;/h3&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%2Fo8v5aqvoyjwvsw7id3i3.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%2Fo8v5aqvoyjwvsw7id3i3.png" alt="Posting Comment" width="800" height="581"&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%2Ft0na9zt3u5j8vzrb9142.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%2Ft0na9zt3u5j8vzrb9142.png" alt="Posting Comment" width="480" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final step of the workflow: Node labeled "Post comments on Github". The goal is to send the formatted review back to the Pull Request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; &lt;strong&gt;POST&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Endpoint:&lt;/strong&gt; Construct the URL using data from the trigger node: &lt;strong&gt;{{ $('Github Trigger').item.json.body.pull_request.url }}/reviews&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Body:&lt;/strong&gt; Use the JSON output from the previous step - &lt;strong&gt;{{ $json.comments }}&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Select the &lt;strong&gt;GitHub Access Token credential&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;

&lt;p&gt;The agent posted the review comment to the Pull Request based on the instructions provided. Additionally, you can provide a structure or template, the agent can follow while creating the comment.&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%2F4r1e2xq2mm6g4zu2qn4p.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%2F4r1e2xq2mm6g4zu2qn4p.png" alt="Output" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;This is a fairly basic prompt that could be improved by adding more instructions to the &lt;strong&gt;Code Review Prompt&lt;/strong&gt; node.&lt;/p&gt;

&lt;p&gt;To ensure your solution stays robust and economical, implement conditional skipping logic in an &lt;strong&gt;IF Node&lt;/strong&gt; to skip the expensive OpenAI call for trivial or work-in-progress PRs, and add schema validation to your final &lt;strong&gt;Function Node&lt;/strong&gt; to ensure the AI's JSON output is always clean and accepted by the GitHub API.&lt;/p&gt;

&lt;p&gt;You are now in full command of your automation. Happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Build a Design Picker Extension with Vanilla Javascript</title>
      <dc:creator>Ashik Varma</dc:creator>
      <pubDate>Fri, 30 Jul 2021 02:55:36 +0000</pubDate>
      <link>https://dev.to/ashikvarma11/build-a-chrome-extension-with-vanilla-javascript-3jnf</link>
      <guid>https://dev.to/ashikvarma11/build-a-chrome-extension-with-vanilla-javascript-3jnf</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Sometimes you like the fonts and color palettes used in websites that you visit and wish to check out what they are. Most people use different extensions for this purpose. &lt;/p&gt;

&lt;p&gt;Fetching a CSS property from wherever you click is so easy, that if you could build an extension, fetching the most relevant properties you want in one go improves your productivity. &lt;/p&gt;

&lt;p&gt;I'm going to walk you through the steps I've used to build a simple extension using pure JavaScript and CSS.&lt;/p&gt;

&lt;p&gt;If you'd like to explore it first, Check out -&amp;gt;   &lt;a href="https://github.com/ashikvarma11/design-picker"&gt;Github Link&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Files
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Manifest file
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "manifest_version": 2,
  "name": "Picker Extension",
  "version": "1.0.0",
  "content_scripts": [
    {
      "matches": ["&amp;lt;all_urls&amp;gt;"],
      "html": ["popup/popup.html"],
      "js": ["content.js"]
    }
  ],
  "permissions": ["tabs"],
  "icons": { "16": "icon.png", "48": "icon.png", "128": "icon.png" },

  "browser_action": {
    "default_popup": "popup/popup.html",
    "default_title": "Picker"
  }
}

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

&lt;/div&gt;



&lt;p&gt;A &lt;code&gt;manifest.json&lt;/code&gt; file is where the configuration for your project exists. The browser derives the name, paths to your scripts, icons, permissions, etc. through this file. Furthermore, we have a list of options to specify the nature of your extension, like, how it should be rendered when the user opens a new tab or which all websites should this extension be applied to, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Script
&lt;/h3&gt;

&lt;p&gt;A content script is a JavaScript file that has access to the DOM of the website that you visit. This means that you can get and set the properties of any element in the DOM tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pop up
&lt;/h3&gt;

&lt;p&gt;This is the window that pops up when you click on the extension icon. Pop-up doesn't have access to the content of the website that you visit. This is also referred to as "Extension" in the Chrome development docs. It has its DOM and is standalone. But, we can make the connection between your Content Script and Popup script through a series of "Message Passing".&lt;/p&gt;

&lt;h1&gt;
  
  
  Get your Design
&lt;/h1&gt;

&lt;p&gt;In the Content script -&amp;gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function listenToClick() {
  document.addEventListener("click", function (event) {
    payLoad = {
      ...payLoad,
      fontFamily: window
        .getComputedStyle(currElement, null)
        .getPropertyValue("font-family"),
      fontSize: window
        .getComputedStyle(currElement, null)
        .getPropertyValue("font-size"),
      color: window
        .getComputedStyle(currElement, null)
        .getPropertyValue("color"),
      backgroundColor: window
        .getComputedStyle(currElement, null)
        .getPropertyValue("background-color"),
    };
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two global variables - &lt;code&gt;payLoad&lt;/code&gt; and &lt;code&gt;currElement&lt;/code&gt; - are initialized outside this function. Whenever the user &lt;strong&gt;hover&lt;/strong&gt; over an element, the &lt;strong&gt;currElement&lt;/strong&gt; will be set. Further, clicking the element fetches the design using the code above.&lt;/p&gt;

&lt;h1&gt;
  
  
  Initiate a Handshake
&lt;/h1&gt;

&lt;p&gt;You need to ping the content script and get the design values you obtained in the content script as response.&lt;/p&gt;

&lt;p&gt;In the Popup script -&amp;gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function initiateHandshake() {
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.tabs.sendMessage(
      tabs[0].id,
      { message: "handshake" },applyValuesToView);
  });
}

function applyValuesToView(response) {
  let message = response;
  if (message != undefined) {
    if (message["color"]) font_col.innerHTML = message["color"];
    if (message["backgroundColor"]) bg_col.innerHTML = message["backgroundColor"];
    if (message["fontSize"]) font_size.innerHTML = message["fontSize"];
    if (message["fontFamily"]) font_fam.innerHTML = message["fontFamily"];
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever the user opens the popup, a &lt;strong&gt;handshake&lt;/strong&gt; message is sent to the content-script and in response, it will send the design data fetched when an element was clicked. &lt;/p&gt;

&lt;h1&gt;
  
  
  Send Response for Handshake
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function listenToPopUp() {
  chrome.runtime.onMessage.addListener(function (
    request,
    sender,
    sendResponse
  ) {
    if (request.message === "handshake") sendResponse(payLoad);
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Copy design value
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function copyDesign(event) {
  var tempInput = document.createElement("input");
  tempInput.value = event.target.innerText;
  document.body.appendChild(tempInput);
  tempInput.select();
  document.execCommand("copy");
  document.body.removeChild(tempInput);
  toggleSnackBar();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a hack for copying the text to the clipboard. An ** input** element is created to simulate click and copy through the JavaScript code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We use a similar approach whenever we want to download content from a link.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Publish the Extension
&lt;/h1&gt;

&lt;p&gt;Navigate to &lt;code&gt;chrome://extensions/&lt;/code&gt; and click on the &lt;code&gt;Load unpacked&lt;/code&gt; button.&lt;br&gt;
A prompt will appear to select your folder. Add the whole folder and it will install your extension &lt;strong&gt;locally&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This will run only on **your&lt;/em&gt;* browser.* &lt;/p&gt;

&lt;h1&gt;
  
  
  That's it.
&lt;/h1&gt;

&lt;p&gt;Feel free to fork the repo and customize your extension as you like.&lt;br&gt;
Thank you, for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>css</category>
      <category>html</category>
    </item>
  </channel>
</rss>
