Skip to content

Latest commit

ย 

History

2 Commits

Folders and files

Repository files navigation

TechStack Detector logo

๐Ÿ”Ž TechStack Detector

A Wappalyzer-style Chrome extension that identifies the technologies behind any website: CMS, frameworks, libraries, analytics, CDN, hosting, servers and more, with confidence scores, versions and evidence.

Manifest V3 React 19 Vite 8 Tests Version


๐Ÿ“‘ Table of contents

  1. โœจ Features
  2. ๐Ÿ“ธ Screenshots
  3. ๐Ÿš€ Quick start
  4. ๐Ÿงญ Using the extension
  5. ๐Ÿ—๏ธ Architecture
  6. ๐Ÿง  How detection works
  7. ๐Ÿ“Š Confidence, versions & evidence
  8. ๐Ÿ“š Rules & categories
  9. ๐Ÿ“ฆ Optional GPL Wappalyzer pack
  10. ๐ŸŽจ Icons & logos
  11. ๐Ÿ” Permissions & privacy
  12. ๐Ÿงช Testing
  13. ๐Ÿ› ๏ธ Scripts reference
  14. ๐Ÿ“ Project structure
  15. โž• Adding a technology
  16. ๐Ÿฉบ Troubleshooting
  17. ๐Ÿ—บ๏ธ Roadmap
  18. ๐Ÿ“„ License

โœจ Features

Feature Details
๐Ÿ” 7,500+ technologies About 260 hand-written, tested rules, plus an optional pack of about 7,260 from the open Wappalyzer database
๐ŸŽฏ Confidence scoring Every detection is Confirmed, Likely or Possible, based on how strong and how many its signals are
๐Ÿ”ข Version detection Reported only when a reliable fingerprint gives one (e.g. WordPress 7.1.3, React 18.3.1, PHP 8.2.34)
๐Ÿงพ Evidence Tap any technology to see exactly which signals matched and how much each contributed
๐Ÿ—‚๏ธ 33 categories CMS, page builders, frameworks, libraries, analytics, CDN, hosting, security and more, shown in a two-column layout
๐ŸŒ 11 signal sources HTML, DOM, JS globals, script and link URLs, CSS text, HTTP headers, cookies (including HttpOnly), XHR/fetch calls, visible text and meta tags
โฑ๏ธ Delayed-script aware Finds scripts that LiteSpeed, WP Rocket and similar plugins hide until the user interacts
๐Ÿ” Auto rescans After the first interaction, about 4 s after load, and on single-page-app route changes
๐Ÿท๏ธ Toolbar badge Shows the number of technologies found on the current tab
๐Ÿ–ผ๏ธ Real logos About 97% of technologies show a brand icon, bundled offline
๐ŸŒ— Light / dark / system themes Remembered between sessions
โœจ Animated UI Built with Motion; respects reduce motion
๐Ÿ“‹ Copy JSON Export the full scan, including evidence

๐Ÿ“ธ Screenshots

Light theme Dark theme
Popup, light theme Popup, dark theme
Evidence for a detection Resources tab
Expanded evidence Resources tab

๐Ÿš€ Quick start

โœ… Requirements

  • Node.js 22+ (developed on Node 24)
  • Google Chrome 116+, or another Chromium browser such as Edge or Brave
  • Microsoft Edge or Chromium: only needed for npm run pack:fetch (to shrink oversized icons) and for npm run test:e2e

๐Ÿ“ฅ Install and build

cd extension
npm install
npm run pack:fetch     # first time only: download Wappalyzer data and icons (~80 MB)
npm run build          # โ†’ dist/

๐Ÿ’ก pack:fetch is only needed once, and again whenever you want fresh Wappalyzer data. If you don't want the GPL pack at all, skip it and run npm run build:core instead.

๐Ÿงฉ Load into Chrome

  1. Open chrome://extensions.
  2. Turn on Developer mode (top right).
  3. Click Load unpacked and select the extension/dist folder.
  4. Pin the extension (puzzle icon โ†’ ๐Ÿ“Œ).

๐Ÿ”„ After every rebuild

  1. Click โ†ป on the TechStack Detector card in chrome://extensions. Chrome keeps running the old code until you do.
  2. Reload the website tab. Header-based detections (servers, CDNs, security policies) only work for pages loaded after the extension.
  3. Check the popup header: it shows "Detector ยท v1.5.4".

๐Ÿงญ Using the extension

๐Ÿ–ฑ๏ธ The popup

Area What it shows
Header Logo, version, theme toggle (โ˜€๏ธ / ๐ŸŒ™ / ๐Ÿ–ฅ๏ธ), rescan button
Site card Favicon, hostname, URL, chips for Secure or Not secure, language and scan time
Overview tab ๐Ÿงฉ Technologies, grouped by category in two columns, then ๐Ÿ“„ Page details (title, description, generator, language, charset, URL); click a detail to copy it
Resources tab Counts of scripts, external scripts, stylesheets, images, links and iFrames, plus an external-vs-inline script bar
JSON tab The full scan result with syntax highlighting
Footer ๐Ÿ”„ Rescan and ๐Ÿ“‹ Copy JSON

๐Ÿงพ Reading a technology row

[logo]  WordPress            โญ• 100
        7.1.3  Confirmed
  • Version chip: appears only when a fingerprint reliably exposed a version.
  • Level: ๐ŸŸข Confirmed, ๐Ÿ”ต Likely, ๐ŸŸ  Possible, or via X when the technology was implied by another (e.g. PHP via WordPress).
  • Ring: the confidence score (0โ€“100).
  • Click the row to expand its evidence: each signal type (META, HTML, SCRIPT, HEADER, JS, COOKIE, CSSโ€ฆ), the matched value and its weight (+100).

โš ๏ธ "Response headers weren't captured"

This banner appears when the tab was loaded before the extension started or was reloaded. Headers are only recorded while a page loads, so reload the tab to detect web servers, CDNs and the services listed in the site's Content-Security-Policy.


๐Ÿ—๏ธ Architecture

                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Website tab โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                   โ”‚  content.js (isolated world)                โ”‚
                   โ”‚   โ€ข HTML, inline + decoded data: scripts    โ”‚
                   โ”‚   โ€ข script/link URLs, meta, cookies, CSS    โ”‚
                   โ”‚   โ€ข DOM probes, CSS variables, visible text โ”‚
                   โ”‚  probeMainWorld() (page's MAIN world)       โ”‚
                   โ”‚   โ€ข JS globals (window.React, Shopifyโ€ฆ)     โ”‚
                   โ”‚   โ€ข DOM expandos (__reactFiber$, __kโ€ฆ)      โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚ COLLECT_FINGERPRINT
 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   SCAN_TAB   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
 โ”‚  Popup   โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ โ”‚  Service worker (background.js)       โ”‚
 โ”‚ (React)  โ”‚ โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚   โ€ข webRequest: headers + requests    โ”‚
 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   result     โ”‚   โ€ข chrome.cookies: HttpOnly names    โ”‚
                           โ”‚   โ€ข detector.detect(fingerprint)      โ”‚
                           โ”‚   โ€ข tab cache + toolbar badge         โ”‚
                           โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿงฉ The pieces

Part File Role
โš™๏ธ Service worker src/background/serviceWorker.js The hub. Captures headers and network requests, runs scans, caches results per tab, updates the badge, routes messages.
๐Ÿ“„ Content script src/content/content.js Runs in each page. Collects the fingerprint on request and triggers automatic rescans.
๐Ÿง  Main-world probe src/detector/scanners/jsScanner.js Injected into the page's own JavaScript context. Reads globals and DOM properties the content script can't see.
โš›๏ธ Popup src/popup/, src/components/ React 19 UI with Motion animations.
๐Ÿ”ฌ Detector src/detector/ Pure JavaScript (no Chrome APIs), so it's fully unit-testable.

๐Ÿ’ฌ Messages

All messages are defined in src/shared/messages.js, and every response has the shape { ok: true, data } | { ok: false, error }.

Message From โ†’ To Purpose
PAGE_READY content โ†’ SW Page loaded or interacted with, or the route changed. Run an auto-scan.
COLLECT_FINGERPRINT SW โ†’ content Collect raw evidence for a scan
SCAN_TAB popup โ†’ SW Full scan of the active tab
GET_TAB_DATA popup โ†’ SW Cached result, for an instant render

๐Ÿ” When scans happen

  1. Page load (document_idle).
  2. About 4 s later: apps often render late (loading screens, client-side redirects, chat widgets).
  3. 2.5 s after the first scroll, click or keypress, to catch scripts that optimisers delay until interaction.
  4. On single-page-app navigation (Navigation API, debounced).
  5. Whenever the popup opens, or you press Rescan.

Concurrent scans of the same tab are merged into one.


๐Ÿง  How detection works

Detection works in four steps: collect evidence โ†’ match rules โ†’ score โ†’ resolve relationships.

1๏ธโƒฃ Collect evidence (the fingerprint)

Signal type Source Example
html Page HTML, plus inline scripts that WP Rocket stores as base64 /wp-content/plugins/
text Visible page text (innerText) Powered by โ€ฆ
scripts Contents of inline <script> tags _paq.push(
scriptSrc <script src>, delayed data-src scripts and network requests cdn.shopify.com
links <link href>, stylesheets and fonts fonts.googleapis.com
css Text of same-origin stylesheets, including CSS merged by optimisers font-family: "Font Awesome 5 Free"
meta <meta name/property> generator: WordPress 7.1.3
headers HTTP response headers (webRequest) server: cloudflare, x-powered-by: PHP/8.2
cookies Cookie names only, including HttpOnly laravel_session, _shopify_y
xhr fetch/XHR/beacon request URLs ip-api.com/json
js Page globals (main world) React.version, jQuery.fn.jquery
jsPrefix Globals with generated names webpackChunk_N_E, __sveltekit_x1y2
dom CSS selectors, attributes and element text [ng-version], astro-island
expando JS properties on DOM nodes __reactFiber$, __vue_app__
cssVars Computed CSS custom properties --tw-ring-offset-width (Tailwind)
url Page URL /wp-admin/

๐Ÿ›ก๏ธ Why three collection contexts? Content scripts run in an isolated world and can't see window.React or React's DOM markers. Only the main-world probe can. HTTP headers aren't visible to page scripts at all, so the service worker reads them via webRequest. HttpOnly cookies aren't in document.cookie, so their names come from chrome.cookies.

2๏ธโƒฃ Match rules

Each technology is a declarative rule, and the engine has no technology-specific code. A rule looks like this:

{
  name: "Shopify",
  category: "ecommerce",
  website: "https://www.shopify.com",
  color: "#95bf47",
  headers: { "x-shopid": true },                       // header exists
  scriptSrc: [/cdn\.shopify\.com/i],                    // URL pattern
  cookies: { _shopify_y: true },                        // cookie name
  js: { "Shopify.shop": { weight: 90 } },               // page global
  meta: { generator: { pattern: /^Shopify/, version: "\\1" } }
}

3๏ธโƒฃ Score

Each matching signal adds its weight, and the total is capped at 100. Strong, hard-to-fake signals weigh more than loose text matches:

Signal Default weight
meta, headers 100
expando 90
js, xhr, cssVars, jsPrefix 80
dom 70
scriptSrc, links, cookies, css 60
scripts 50
html, text, url 40

4๏ธโƒฃ Resolve relationships

Relationship Example Effect
implies Next.js โ†’ React; WordPress โ†’ PHP, MySQL Adds the implied technology, shown as via Next.js
excludes Lodash excludes Underscore.js Removes a look-alike
requires a3 Lazy Load requires WordPress Dropped unless the required technology is present
requiresCategory Afterpay requires an ecommerce platform Dropped unless something in that category is detected
versionOnly _.VERSION for Lodash Supplies a version but can never detect on its own

๐Ÿ“Š Confidence, versions & evidence

Level Score Meaning
๐ŸŸข Confirmed โ‰ฅ 80 One very strong signal, or several medium ones
๐Ÿ”ต Likely 50โ€“79 Good evidence, not conclusive
๐ŸŸ  Possible < 50 A single weak signal; treat as a hint

Versions come from regex capture groups (version: "\\1"), including ternary templates like \1?GA4:UA. When several signals report a version, the most specific wins (18.3.1 beats 18). A version is never guessed: no reliable pattern means no version.

Evidence records the signal type, the key (e.g. the header name), the matched value (truncated) and its weight. Cookie values are never shown or stored; only the fact that a cookie exists.


๐Ÿ“š Rules & categories

There are 258 hand-written rules in 33 categories, one file per area in src/detector/rules/:

File Covers
๐Ÿ“ cms.js WordPress, Drupal, Joomla, Ghost, Webflow, Wix, Squarespace, Framer, Duda, HubSpot CMS, TYPO3, Blogger, Contentful, Sanity, Strapi
๐Ÿงฑ wordpress.js Page builders (Elementor, Divi, WPBakery, Bricksโ€ฆ), themes (Astra, Kadence, Hello Elementorโ€ฆ), plugins (Yoast, Rank Math, WP Rocket, LiteSpeed Cache, Contact Form 7โ€ฆ)
๐Ÿ›’ ecommerce.js, ๐Ÿ’ณ payments.js Shopify, WooCommerce, Magento, BigCommerce, PrestaShop, Stripe, PayPal, Razorpay, Paddle, Klarnaโ€ฆ
โš›๏ธ frameworks.js React, Next.js, Vue, Nuxt, Angular, Svelte, SvelteKit, Astro, Gatsby, Remix, Ember, Preact, SolidJS, Qwik, Lit, Meteorโ€ฆ
๐Ÿ“ฆ libraries.js jQuery (+ UI, Migrate), Lodash, Underscore, GSAP, Swiper, Slick, Lottie, Chart.js, Three.js, D3, PDF.js, htmxโ€ฆ
๐ŸŽจ ui.js Tailwind, Bootstrap, Bulma, Foundation, MUI, Ant Design, Chakra, Mantine, Radix, DaisyUI, Lucide, Font Awesome, Google Fontsโ€ฆ
๐Ÿ“ˆ analytics.js Google Analytics, GTM, Hotjar, Mixpanel, PostHog, Meta Pixel, Clarity, Amplitude, Matomo, Segment, Pendo, Vercel Analyticsโ€ฆ
๐ŸŽฌ media.js, ๐Ÿงฐ widgets.js YouTube, Vimeo; live chat (Intercom, Crisp, Zoho SalesIQโ€ฆ), cookie banners, maps, ads, email marketing
๐Ÿ›ก๏ธ security.js Cloudflare Turnstile, hCaptcha, reCAPTCHA, Sentry, Datadog
๐ŸŒ cdn.js, โ˜๏ธ hosting.js, ๐Ÿ–ฅ๏ธ servers.js Cloudflare, CloudFront, Fastly, Akamai; Vercel, Netlify, AWS, GCP, Azure, Hostinger, Kinsta; Nginx, Apache, LiteSpeedโ€ฆ
๐Ÿง‘โ€๐Ÿ’ป languages.js Laravel, Django, Rails, Express, ASP.NET, PHP, Java, Node.jsโ€ฆ
โœจ misc.js Open Graph, RSS, HTTP/3, HSTS, PWA, Priority Hints, webpack, Vite, Turbopack, MySQLโ€ฆ

Every one of these rules has a test fixture that proves it fires. The test suite fails if a rule is added without one.


๐Ÿ“ฆ Optional GPL Wappalyzer pack

For Wappalyzer-level coverage, the default build includes about 7,260 more technologies converted from the community-maintained Wappalyzer database, enthec/webappanalyzer.

โš–๏ธ Licence: that data is GPL-3.0. A build that includes the pack must be distributed under GPL-3.0 terms, which means making the full source available. Use npm run build:core for a build with only our own rules and no GPL code: a 67 KB service worker instead of about 1.8 MB.

Step Command What happens
1 npm run pack:fetch Downloads fingerprints, categories, icons and the LICENSE into vendor/webappanalyzer/. Oversized icons are rendered to 64 px PNGs.
2 npm run build Converts the data into src/detector/packs/wappalyzer.generated.js, then builds

How the conversion works (scripts/lib/convertWappalyzer.mjs):

  • ๐Ÿ”„ Fields are mapped onto our signal types (text, scripts, dom attributes and text, properties โ†’ expando, and so on).
  • ๐Ÿงฎ Modifiers are honoured: \;version:\1 and \;confidence:N; confidence:0 becomes version-only.
  • ๐Ÿค Our own rule wins where both define a technology. Upstream signals our rule lacks are merged in as a supplement, in pack builds only.
  • ๐Ÿท๏ธ Name aliases, e.g. Google Font API โ†’ Google Fonts, so there are no duplicates.
  • ๐Ÿšซ Server-side-only fingerprints are skipped (DNS, robots.txt, certificates).
  • ๐Ÿฉน PACK_PATCHES fixes upstream fingerprints that misfired on real sites (e.g. Onsen UI matching consent.min.js, PyScript keyed on a Marketo cookie).
  • ๐Ÿ’พ The pack file is written atomically, so an interrupted import can't break the next build.

๐ŸŽจ Icons & logos

Icons are chosen in this order:

  1. ๐Ÿท๏ธ Simple Icons brand logo (CC0). Only the icons actually used are bundled, in src/components/techIcons.generated.js.
  2. โšก Symbols for web standards: HTTP/3 โšก, Open Graph ๐Ÿ”—, Priority Hints, HSTS ๐Ÿ”’, PWA ๐Ÿ“ฑ.
  3. ๐Ÿ–ผ๏ธ The upstream icon from the GPL pack, copied into dist/tech-icons/. Shown with <img>, so scripts inside an SVG can never run.
  4. ๐Ÿ”ค A coloured letter tile as the last resort, with a colour derived from the name.

The result is a real icon for about 97% of technologies. Near-black logos (Next.js, Vercel, X) switch to the text colour in dark mode.


๐Ÿ” Permissions & privacy

Permission Why it's needed
host_permissions (http/https) Scan any site automatically and run the main-world probe
scripting Inject the content script into tabs opened before install, and run the main-world probe
webRequest Read HTTP response headers and the page's own network requests
cookies Read the names of HttpOnly cookies (e.g. laravel_session)
storage Per-tab scan cache (session) and the last scan
activeTab Scan the current tab when you open the popup

๐Ÿ”’ Privacy:

  • All detection runs locally. Nothing is sent to any server, and there's no analytics or tracking.
  • Cookie values are never read into results, only their names.
  • Results live in chrome.storage.session: they're cleared when the browser closes, and per tab on navigation or close.
  • Requests made inside third-party iframes are ignored, so embedded widgets don't pollute a site's stack.

๐Ÿงช Testing

npm test            # 351 unit, coverage, regression and pack tests (~3 s)
npm run test:e2e    # real browser: 26 live websites in headless Edge (~5 min)
Suite File What it checks
๐Ÿง  Engine tests/detector.test.js Matching, scoring, implies, versions, false positives
๐Ÿงฉ Coverage tests/technologies.test.js Every rule fires on its fixture, extracts the right version, and never reports a version it can't support; plus false-positive look-alikes
๐Ÿ” Regression tests/regression.test.js Restricted URLs, message contract, the probe surviving Chrome's serialisation, every category having an icon
๐Ÿ“ฆ Pack tests/pack.test.js Converter rules, supplements, CSP-based detection, no duplicates, nothing detected on a plain page
๐ŸŒ End-to-end scripts/e2e.mjs Loads dist/ as a real extension, opens 26 live sites (Wappalyzer-compared), simulates a user interaction and checks the expected technologies
npm run test:e2e -- calgameswanted             # one site
E2E_DUMP=./dumps npm run test:e2e -- webvoltz  # save full scan JSON for debugging

โ„น๏ธ Google Chrome 137+ ignores --load-extension, so the e2e suite uses Edge or Chromium. Set BROWSER=<path> to choose one.


๐Ÿ› ๏ธ Scripts reference

Command Description
npm run build Import the pack (if fetched), generate icons, build into dist/
npm run build:core Build with our rules only (no GPL data or icons)
npm run dev Rebuild on every save (then click โ†ป in Chrome)
npm test Unit, coverage and regression tests
npm run test:e2e Real-browser test against live sites
npm run pack:fetch Download or refresh the Wappalyzer data and icons
npm run pack:import Re-convert the pack without a full build
npm run icons:tech Regenerate Simple Icons logos (verbose report)
npm run icons Regenerate the extension's own toolbar icons

๐Ÿ“ Project structure

extension/
โ”œโ”€โ”€ ๐Ÿ“„ public/
โ”‚   โ”œโ”€โ”€ manifest.json                 Manifest V3
โ”‚   โ””โ”€โ”€ icons/                        toolbar icons (generated)
โ”œโ”€โ”€ ๐Ÿ› ๏ธ scripts/
โ”‚   โ”œโ”€โ”€ build.mjs                     build pipeline (pages โ†’ content IIFE)
โ”‚   โ”œโ”€โ”€ e2e.mjs                       real-browser test
โ”‚   โ”œโ”€โ”€ fetch-wappalyzer.mjs          download pack data + icons
โ”‚   โ”œโ”€โ”€ import-wappalyzer.mjs         convert pack โ†’ generated rules
โ”‚   โ”œโ”€โ”€ lib/convertWappalyzer.mjs     the converter (pure, tested)
โ”‚   โ”œโ”€โ”€ optimize-icons.mjs            render oversized icons to 64 px PNG
โ”‚   โ”œโ”€โ”€ copy-tech-icons.mjs           copy used icons into the build
โ”‚   โ”œโ”€โ”€ generate-tech-icons.mjs       Simple Icons โ†’ techIcons.generated.js
โ”‚   โ””โ”€โ”€ generate-icons.mjs            the extension's own icon
โ”œโ”€โ”€ ๐Ÿงช tests/                         unit, coverage, regression, pack (+ fixtures/)
โ”œโ”€โ”€ ๐Ÿ“ฆ vendor/webappanalyzer/          upstream GPL data (after pack:fetch)
โ”œโ”€โ”€ ๐Ÿ–ผ๏ธ docs/screenshots/
โ””โ”€โ”€ ๐Ÿ’ป src/
    โ”œโ”€โ”€ background/serviceWorker.js   hub: scans, headers, requests, cookies, badge
    โ”œโ”€โ”€ content/                      content script + page facts
    โ”œโ”€โ”€ detector/
    โ”‚   โ”œโ”€โ”€ engine/                   detector, matcher, patterns, confidence, evidence, probe
    โ”‚   โ”œโ”€โ”€ scanners/                 html, script, css, dom, cookie + main-world jsScanner
    โ”‚   โ”œโ”€โ”€ rules/                    โ˜… one file per category โ€” all technologies live here
    โ”‚   โ”œโ”€โ”€ packs/                    optional generated GPL pack (+ active.js switch)
    โ”‚   โ”œโ”€โ”€ categories.js             33 categories (label + order)
    โ”‚   โ””โ”€โ”€ index.js                  rules + pack (with supplements) โ†’ detector
    โ”œโ”€โ”€ popup/                        App, hooks (scan, theme, clock), styles
    โ”œโ”€โ”€ components/                   SiteHero, TechList, TechRow, tabs, ui/
    โ”œโ”€โ”€ services/                     storage, tab cache, header & request stores, messaging
    โ”œโ”€โ”€ shared/messages.js            message contract
    โ””โ”€โ”€ utils/url.js

โž• Adding a technology

  1. Add a rule to the matching file in src/detector/rules/:

    {
      name: "Acme Chat",
      category: "chat",
      website: "https://acme.chat",
      color: "#ff5a1f",
      scriptSrc: [{ pattern: /widget\.acme\.chat/i, weight: 100 }],
      js: { "AcmeChat.version": { pattern: /^([\d.]+)/, version: "\\1", weight: 90 } }
    }
  2. Add a fixture to tests/fixtures/technologies.js:

    "Acme Chat": { fp: { js: { "AcmeChat.version": "2.4.1" } }, version: "2.4.1" },
  3. Add look-alikes to NEGATIVE in the same file, if the technology has any.

  4. Check it: run npm test, then npm run build, then reload the extension.

Rule reference:

Key Type Notes
html text scripts css scriptSrc links xhr url PatternSpec[] Matched against that source
meta headers { name: PatternSpec } Names are case-insensitive
cookies { name: PatternSpec } Exact, glob_* or /regex/; HttpOnly included
js { "dot.path": PatternSpec } Read in the page's main world
dom { selector: { attribute?, pattern?, version? } } attribute: "#text" = element text
expando jsPrefix cssVars string[] DOM properties, global-name prefixes, CSS variables
implies excludes requires string[] Technology names
requiresCategory string[] Category ids

A PatternSpec is a RegExp, a literal string, true (the key only has to exist), or { pattern, weight, version, versionOnly }.


๐Ÿฉบ Troubleshooting

Problem Fix
๐Ÿ”ข Header shows an old version Click โ†ป in chrome://extensions. If needed, remove the extension and Load unpacked dist/ again.
๐Ÿ“‰ Fewer technologies than expected Reload the tab, then scroll or click once and reopen the popup. Many sites load scripts only after interaction.
โš ๏ธ "Response headers weren't captured" Reload the tab. Headers are only recorded during page load.
๐Ÿงฑ Build says "GPL pack data missing" Run npm run pack:fetch, or use npm run build:core.
๐ŸŒ pack:fetch says "could not reach GitHub" Check your connection, VPN or proxy. Your existing vendor/ data is untouched, and npm run build still works.
๐Ÿšซ Popup says "This page can't be scanned" Chrome blocks extensions on chrome:// pages, the Web Store and file:// URLs.
๐Ÿงช e2e can't find a browser Install Edge or Chromium, or set BROWSER=<path>.

๐Ÿ—บ๏ธ Roadmap

Phase Scope Status
1๏ธโƒฃ Foundation MV3, React popup, content script, service worker, messaging, storage โœ…
2๏ธโƒฃ Detection engine Fingerprints, rules, confidence, evidence โœ…
3๏ธโƒฃ 100+ technologies 258 own rules + optional ~7,260-technology pack, logos, 26-site e2e โœ…
4๏ธโƒฃ MERN SaaS Express + MongoDB, JWT, dashboard, scan history โณ Next
5๏ธโƒฃ Advanced Bulk scanning, export, technology-change monitoring ๐Ÿ”œ
6๏ธโƒฃ Production Queues, rate limits, Chrome Web Store, subscriptions ๐Ÿ”œ

๐Ÿ“„ License

  • Our own code and rules: choose and add a licence (e.g. MIT) before publishing.
  • The optional Wappalyzer pack (vendor/webappanalyzer, src/detector/packs/wappalyzer.generated.js, upstream icons): GPL-3.0. See vendor/webappanalyzer/LICENSE. Builds made with npm run build:core contain none of it.
  • Simple Icons logos: CC0 1.0. Brand logos remain trademarks of their owners.

Made with โค๏ธ for learning Chrome extensions ยท ๐Ÿ”Ž TechStack Detector

Contributors

Languages