Before you go, check out these stories!

0
Hackernoon logoBuilding a New Tab Chrome Extension with Zero Dependencies by@Dane

Building a New Tab Chrome Extension with Zero Dependencies

Author profile picture

@DaneDane Lyons

CPO at Hacker Noon

This story will walk you through the basic steps needed to get started building a new tab Chrome Extension powered by an API without any dependencies. Check out our Tech Stories Tab extension for reference.

Developing a new extension can be a little overwhelming. Google provides a ton of boilerplate examples, but digging through that mess can be a little like navigating through a labyrinth. A lot of examples are incomplete or lead you down the wrong path.

Here's what you need to get started building a new tab extension that fetches content from an API.

Step 1: Create a new folder for your extension

However you choose to make a new folder (

mkdir
) and where you put it (
~/
) is up to you.

Don't get too caught up in the name, it really doesn't matter. I called my folder

tech-stories-extension
, but it won't be visible once you start marketing your extension. You can always rename this later.

Step 2: Create a manifest.json file in your new folder

This is a necessary file for every Chrome Extension. Don't worry about every field you could add to your manifest at this stage. That's a future problem. For now, just start with something like this.

{
  "manifest_version": 2,
  "name": "Tech Stories Tab by Hacker Noon",
  "version": "1.0",
  "description": "The latest Hacker Noon tech stories.",
  "author": "Hacker Noon",
  "chrome_url_overrides" : {
    "newtab": "index.html"
  },
  "permissions": [
    "storage",
    "https://api.hackernoon.com/"
  ],
  "icons": {
    "16": "icon16.png",
    "128": "icon128.png"
  }
}

manifest_version
This is basically just a number to tell Google how to interpret your manifest.json file. Changing this will throw an error when you try and install your extension.

name/description/author
These fields will be used in the web store to describe your extension. You'll eventually want to be thoughtful in what you add here but for testing purposes, feel free to go with something random.

version
While testing, go with "0.1" or "1.0". Once you get published, you'll have to worry about incrementing by .1 for a minor upgrade and 1 for a major upgrade.

chrome_url_overrides
This is where you determine which html file will be used whenever a user opens a new tab. I've named mine

index.html
but feel free to stick it to the man and break convention.

permissions
Security is a pretty big deal when it comes to Chrome Extensions. By default, everything is pretty locked down. For example, you can't just go storing data to

localStorage
willy nilly like some random webpage. You've got to ask users permission to store things locally. You'll also want to add urls to any APIs you're fetching data from.

icons
At minimum, Google recommends having a 128x128 pixel icon and a 16x16 pixel icon.

Step 3: Create an index.html file

<html>
<head>
  <meta charset="utf-8">
  <title>Fancy Title</title>
  <meta name="description" content="Fancy description...">
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <div id="stories"></div>
  <script src="script.js"></script>
</body>
</html>

You'll probably want to change the fancy title and description to something a little more imaginative, but this will get you started. Take note of the

<div id="stories"></div>
element, we'll reference this in our javascript.

Step 4: Create a script.js file

const storiesDiv = document.querySelector('#stories');

const storyNode = (story) => {
  var template = document.createElement('template');
  template.innerHTML = story;
  return template.content.childNodes[0];
}

const addStories = (stories) => {
  for (let index in stories) {
    const story = stories[index];
    const html = `<div class="story">
      <a href="${story.url}">${story.title}</a>
    </div>`;
    storiesDiv.appendChild(storyNode(html));
  }
}

if (localStorage.lastFetch && localStorage.stories && (new Date() - localStorage.lastFetch) < (1000*60*60)) {
  addStories(JSON.parse(localStorage.stories));
} else {
  if (localStorage.stories) {
    addStories(JSON.parse(localStorage.stories));
  }

  fetch('https://api.hackernoon.com/featured-stories',{
      method: 'GET',
      mode: 'cors',
      credentials: 'include'
    })
    .then(response => response.json())
    .then(data => {
      if (!localStorage.stories) {
        addStories(data);
      }

      localStorage.setItem("stories", JSON.stringify(data));
      localStorage.setItem("lastFetch", new Date()-1);
    });
}

This is where the bulk of the work is happening in the chrome extension. You might be tempted to load Vue.js, React, or your favorite flavor of javascript, but if you just want to inject a few chunks for HTML into a static page, go with vanilla JS. Anything else is just not worth the trouble, in my opinion.

The above javascript is basically doing the following:

1) Check to see if you have cached stories (

localStorage.stories
) and you most recently fetched stories less than an hour ago.

2) If your check passes, grab stories from the cache.

3) If the check fails, fetch new stories from the API.

4) Add the stories to the

<div id="stories"></div>
element from
index.html
.

It's ok if you don't quite follow some of the logic here. The code is far from pristine. We can dive into the logic line-by-line in the comments below. I just don't want to get too deep into the weeds here so it's easier to understand what is going on at a high level.

Step 5: Create a style.css file

html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0}

#stories {}
.story {}

This sad CSS is going to look like garbage. It's really just a CSS reset and some boilerplate to get started. Check out CSS Tricks for tips on spicing things up a bit.

Step 6: Install your extension

1) Go to chrome://extensions/

2) Turn on "Developer mode" in the top right corner

3) Click "load unpacked" and select the folder containing your extension files.

4) Open and new tab and see your code in action!

Step 7: Iterate

Once you can see your code functioning in a new tab, start tweaking the HTML, JS, and CSS until you get things looking good enough to launch.

Step 8: Submit your extension for inclusion into the web store

You'll need to create a few promotional images, add a longer description and add security information in order to submit. Here is a walkthrough of the publishing process.

Conclusion

Without dependencies, you can build a new tab Chrome extension in less than 100 lines of code. Here is a github boilerplate repo in case you aren't the copy and pasting type.

This tutorial is a WIP, if you get stuck on any step, please leave a comment.

If you have any ideas for improvements to our extension, please leave a comment on our Product Hunt page.

Tags

Become a Hackolyte

Level up your reading game by joining Hacker Noon now!