Skip to main content

Documentation Index

Fetch the complete documentation index at: https://extension.js.org/llms.txt

Use this file to discover all available pages before exploring further.

You will build an Omnibox (address bar) shortcut. Type gh in the address bar, enter a query, and land on GitHub search results. Along the way you will wire a manifest.json and handle input in a background service worker. You will also practice the dev loop (createdevbuild) that every project follows.

What you will build

CapabilityWhat you get
Omnibox keyword flowTrigger extension behavior with gh from the browser URL bar
Background event handlingHandle user input through a service worker
Local dev loopRun, load, and validate extension behavior quickly
Progressive enhancementAdd live GitHub suggestions after baseline flow works

The plan

Make GitHub search as fast as a native browser shortcut. The extension reserves the keyword gh; after you type gh and a query, it opens GitHub search results.

Step 1 - create the extension

Use the Extension.js create command to scaffold a minimal extension named github-search.
npx extension@latest create github-search

Step 2 - create the manifest file

Every extension starts with a manifest file. It defines metadata, permissions, and runtime files. Based on the plan above, set the gh shortcut and add a service worker for user events.
{
  "manifest_version": 3,
  "name": "GitHub Search",
  "version": "1.0",
  "omnibox": {"keyword": "gh"},
  "background": {
    "service_worker": "service_worker.js"
  }
}
  • omnibox.keyword: When you type gh, the browser fires an event.
  • background.service_worker: Listens to the event you just triggered.

Step 3 - create the background service worker

In browser extensions, the background service worker (a script that runs independently of any visible page) handles browser events. For this example, add a script that listens to Omnibox input and routes the query to GitHub search. Create service_worker.js:
// When the user has accepted what is typed into the omnibox.
chrome.omnibox.onInputEntered.addListener((text) => {
  // Convert any special character (spaces, &, ?, etc)
  // into a valid character for the URL format.
  const encodedSearchText = encodeURIComponent(text)
  const url = `https://github.com/search?q=${encodedSearchText}&type=issues`

  chrome.tabs.create({url})
})
The script above opens a new tab with GitHub search results whenever you type something after “gh” in the address bar.

Step 4 - load your extension

Your package.json file now looks like this:
{
  "scripts": {
    "dev": "extension dev",
    "start": "extension start",
    "build": "extension build"
  },
  "devDependencies": {
    "extension": "latest"
  }
}
These scripts are the default Extension.js commands. Run the extension for the first time:
npm run dev
If your setup is correct, you see the following: You now have a working browser extension that searches on GitHub.

Step 5 - make it better

Improve the search experience by adding suggestions directly in the address bar with an Omnibox input listener. Update service_worker.js to fetch GitHub suggestions and display them while typing.
service_worker.js
// Create a debounce function to avoid excessive
// calls to the GitHub API while the user is still
// typing the search query.
function debounce(fn, delay) {
  let timeoutID
  return function (...args) {
    if (timeoutID) clearTimeout(timeoutID)
    timeoutID = setTimeout(() => fn(...args), delay)
  }
}

// When the user has changed what is typed into the omnibox.
chrome.omnibox.onInputChanged.addListener(
  debounce(async (text, suggest) => {
    const response = await fetch(
      `https://api.github.com/search/issues?q=${text}`
    )
    const data = await response.json()
    const suggestions = data.items.map((issue) => ({
      content: issue.html_url,
      description: issue.title
    }))

    suggest(suggestions)
  }, 250)
)

// When the user has accepted what is typed into the omnibox.
chrome.omnibox.onInputEntered.addListener((text) => {
  // Convert any special character (spaces, &, ?, etc)
  // into a valid character for the URL format.
  const encodedSearchText = encodeURIComponent(text)
  const url = `https://github.com/search?q=${encodedSearchText}&type=issues`

  chrome.tabs.create({url})
})
This code adds live GitHub suggestions directly in the address bar. You now have a working GitHub search extension. Iterate on it and adapt it to your own workflow.

Next steps