In 2025, the use of chrome without extension is equivalent to using a smartphone without apps. This is possible, but you have lost a lot.
And even though how important extension is, it is very easy to make – it is just Javscript with HTML, CSS, and browser API.
In this tutorial, we are going to learn about Chrome extensions, which are going to learn about Chrome extensions by building a generator extension of the latest and highly secure architecture for Chrome Extension, Mini Fest V3 (MV3). You can proceed to see what we will make Here.
The table of content
What are the key components of Chrome extension?
Chrome extensions are incredibly powerful tools that can add custom functionality to your browser experience so how you use the web.
Before we write a code, let’s understand some important ingredients:
Each extension starts with A Manufacture File This JSON File Chrome tells everything to know about Extension: Names, versions, Permissions and Files
User interface Made with HTML, CSS, and JavaScript. This is mainly a mini web page that lives inside your browser
Finally, there is Service worker Which runs in the background and brings data from external APIS. In the Charter V3, the service workers have replaced the background pages
How to make a consultation generator chrome extension
Take a look at what we’re going to make:

This design is by Front and Servant.
Terms:
To follow this tutorial, you need:
When you form an extended plan, the only condition is that they have to keep manifest.json File in the extension route directory.
Test your Chrome Extension
Before starting construction, you would like to see your progress after each file to catch any problem quickly. How to load your extension in the CH Chrome of Testing is:
Barley
chrome://extensionsChrome extensions to open the page.In the upper right corner of the Extension Page, Toggle Manufacturer On
Click on Load Packed Buttons that appear.
In the file dialog, go to Extended root folder And click Select a folder.
Your extension should appear. If its icon does not immediately appear in your browser toolbar, click on Riddle Icon in your toolbar and pin it.

Now let’s start by explaining your extension identity manifest.json File
The benefits of the V3s appearing
manifest.json There is a chrome extension heart. JSON (JavaScript Objects indicators), it provides chrome to everything that you need to know about expansion.
Think of it as a passport with a visa and chrome as the immigration officers confirm identification and access.

The Charter V3 (MV3) brings reliable in better performance, security, and expansion. MV3 uses services workers who only activate the time of need, improve battery life and prevent extension from slowing down their browser.
Let’s break every important field:
manifest_versionThe most important line. Give it 3 to tell Chrome that you are using Mini Fest V3.nameFor, for, for,.versionFor, for, for,.descriptionExplain the basic identity of your extension.actionA mini -fest v3 field that controls what happens when someone clicks on your extensiondefault_iconIn the toolbardefault_popupPoint your HTML file, so clicking on the icon opens the page into a small popup window.permissionsChrome tells to what extent you need to access. We are using host permission So our expansion can bring advice from this API. Without it, the extension will be stopped from these requests. This may be more cautious, but it is a safety move that protects consumers.backgroundPoint your service worker script.service_workerField tells Chrome thatservice-worker.jsShould walk in the background.
Step 1: Create a Mini Fest 3 File
What is here, according to the description of the different parts of the file mentioned above, manifest.json File will look like:
{
"name": "Advice Generator",
"description": "Get a fresh piece of advice whenever you need it!",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "index.html",
"default_icon": "/icons/icon-dice.png"
},
"permissions": (
"activeTab"
),
"host_permissions": (
""
),
"background": {
"service_worker": "service-worker.js"
}
}
You can see activeTab In other examples of extension. Although we do not need it strictly, we are able to know about it. This gives temporary access to whatever tab is underway, but only when they click on the Extension icon.
The picture below will be the result of running our mini -fest code above.

Step 2: Create HTML and CSS Pages
Now that our extension identification and permission is defined, let’s proceed to build the user interface starting with one index.html Page
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advice Generatortitle>
<link rel="stylesheet" href="style.css">
<link href=" rel="stylesheet">
head>
<body>
<main class="advice-card">
<h1 class="advice-id">ADVICE #<span id="advice-id-number">span>h1>
<p class="advice-quote" id="advice-quote">
“It is easy to sit up and take notice, what's difficult is getting up and taking action.”
p>
<div class="divider">
<img src="icons/pattern-divider.png" alt="Divider pattern">
div>
<button class="dice-button" id="generate-advice-btn">
<img src="icons/icon-dice.png" alt="Dice icon">
button>
main>
<script src="index.js">script>
body>
html>
Now, let’s make the design live with one style.css File in your Root Directory. We will set the physical overall style, keep the card position, and style all the elements inside it.
:root {
--clr-light-cyan: hsl(193, 38%, 86%);
--clr-neon-green: hsl(150, 100%, 66%);
--clr-grayish-blue: hsl(217, 19%, 35%);
--clr-dark-grayish-blue: hsl(217, 19%, 25%);
--clr-dark-blue: hsl(218, 23%, 16%);
--ff-manrope: 'Manrope', sans-serif;
--fw-regular: 400;
--fw-bold: 700;
}
body {
margin: 0;
padding: 0;
font-family: var(--ff-manrope);
background-color: var(--clr-dark-blue);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
min-width: 30rem;
box-sizing: border-box;
}
.advice-card {
background-color: var(--clr-dark-grayish-blue);
border-radius: 0.5rem;
padding: 1.5rem 1.5rem;
width: 60%;
text-align: center;
position: relative;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);
margin-bottom: 70px;
}
.advice-id {
color: var(--clr-neon-green);
font-size: 0.8em;
letter-spacing: 4px;
text-transform: uppercase;
margin-bottom: 20px;
}
.advice-quote {
color: var(--clr-light-cyan);
font-size: 1.75em;
font-weight: var(--fw-bold);
line-height: 1.4;
margin-bottom: 1.2rem;
padding: 0 15px;
}
.divider {
margin-bottom: 35px;
}
.divider img {
max-width: 90%;
height: auto;
}
.dice-button {
background-color: var(--clr-neon-green);
border: none;
border-radius: 50%;
width: 2rem;
height: 2rem;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: absolute;
bottom: -1rem;
left: 50%;
padding: 1rem;
transform: translateX(-50%);
transition: box-shadow 0.3s ease-in-out;
}
.dice-button:hover {
box-shadow: 0 0 40px var(--clr-neon-green);
}
.dice-button img {
width: 2rem;
height: 2rem;
}
The picture below will be the result of running our HTML and CSS code above the initial mini -fest.

With the completion of HTML and CSS, the visual aspect of our expansion is complete. Next, let’s write the JavaScript and give life that handles new advice and update the display.
Step 3: Add a service worker
At the Mini Fest V3, the basic background logic for expansion survives in its service worker. Unlike the Permanent Background pages of the Charter V2, V3 Service Workers only walk when needed, as in response to a message index.js Or browser event.
Ours service-worker.js It will be the character:
Listen to the request from
index.js(When the user clicks on the dice).Bring a new piece of advice from the Slip Slip API.
Send this advice back
index.jsShow
Create a file that has a name service-worker.js In your extension route directory.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "fetchAdvice") {
fetchAdvice().then(adviceData => {
sendResponse({ advice: adviceData });
}).catch(error => {
console.error("Error fetching advice:", error);
sendResponse({ error: "Failed to fetch advice" });
});
return true;
}
});
async function fetchAdvice() {
try {
const response = await fetch("https://api.adviceslip.com/advice");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.slip;
} catch (error) {
console.error("Could not fetch advice:", error);
throw error;
}
}
Message handling in service workers
Since service workers do not have direct access to your domo index.html Page (and vice versa), they communicate using the message passing. As you can see in the above code, the user clicks in the dice index.htmlAnd index.js Will send a message service-worker.js Seeking new advice. After that the service worker will bring advice and send him back to another message.
chrome.runtime.onMessage.addListener Incoming messages and hears sendResponse Answers
Our service worker is now ready to bring advice. The next step is to make us index.js Talk with it.
Step 4: Add the functionality of the app
First, we will make our index.js The file is responsible for all the logic facing the user. This will handle the user conversation (clicking on the dice), send a message to us service-worker.js To get a new advice, and then update index.html With recovery advice.
Ours index.js Will perform the following steps:
Refer to the HTML elements where we will show the identification, excerpt and dice of the advice.
When the dice clicked, set the event listeners for this.
Send a message
service-worker.jsApplying new advice.Return the advice
service-worker.jsAnd update the content on itindex.htmlPage
const adviceIdElement = document.getElementById('advice-id-number');
const adviceQuoteElement = document.getElementById('advice-quote');
const generateAdviceBtn = document.getElementById('generate-advice-btn');
function requestNewAdvice() {
chrome.runtime.sendMessage({ action: "fetchAdvice" }, (response) => {
if (chrome.runtime.lastError) {
console.error("Error sending message:", chrome.runtime.lastError);
adviceQuoteElement.textContent = "Error: Could not get advice.";
adviceIdElement.textContent = "---";
return;
}
if (response && response.advice) {
adviceIdElement.textContent = response.advice.id;
adviceQuoteElement.textContent = `“${response.advice.advice}”`;
} else if (response && response.error) {
console.error("Service Worker error:", response.error);
adviceQuoteElement.textContent = `Error: ${response.error}`;
adviceIdElement.textContent = "---";
}
});
}
if (generateAdviceBtn) {
generateAdviceBtn.addEventListener('click', requestNewAdvice);
} else {
console.error("Generate advice button not found!");
}
document.addEventListener('DOMContentLoaded', requestNewAdvice);
With index.js In place, our advice generator is now ready as you can see in GIF below:

The next important step is to know how to debug your extension, what should be wrong.
How to debug your Chrome extension
Chrome provides the best debugging tools to help solve the defects. Always follow these necessary steps:
Reload your extension after changing changes (especially
manifest.jsonOrservice-worker.js) By clicking the refresh iconchrome://extensions.Check your check
manifest.jsonFor types – lost coma or brackets will break everything.Confirm your API URL and make sure you have the correct permission
manifest.json.
Debugging the main HTML and JS pages
It is likely where you will face your initial JavaScript or HTML/CSS problems.
Open the extension and right -click anywhere in the popup to inspect.
Check the Console Tab for JavaScript errors from your
index.jsFileUse the elements tabs to inspect your HTML and adapt to CSS style in real time.

DEBG to Service Worker – Important for MV 3
The service worker runs in the background and has its own separate derivatives.
Barley
chrome://extensions.Click on Service worker Link under your extension or mistakes button.
Check console and network tabs respectively for service workers and API errors.

Conclusion
Congratulations, you just created a chrome extension using the Mini Fest V3. You have created a user interface, implemented background processing with the service worker, and established communication between different parts of your expansion. These skills are building blocks for any chrome extension, no matter how easy or complicated.
Here are some helpful resources: