How to Configure Content Script Injection and URL Matches in the Chrome Extension Boilerplate

Configure content script injection and matches by editing chrome-extension/manifest.ts for direct control, or define reusable patterns in packages/module-manager/lib/const.ts for modular feature management.

The jonghakseo/chrome-extension-boilerplate-react-vite repository uses a TypeScript-first approach to manifest generation, allowing developers to configure content script injection and URL matches through static configuration files that compile into the final manifest.json during the Vite build process.

Understanding the Manifest Architecture

The boilerplate generates the extension manifest through three coordinated systems: a static TypeScript definition, a modular configuration registry, and a Vite plugin that handles build-time assembly.

The Static Manifest Source

The primary source of truth resides in chrome-extension/manifest.ts. This file exports a manifest object that includes a pre-configured content_scripts array defining default injection behavior.

According to the source code, the default configuration matches all URLs and injects both logic and UI layers:

// chrome-extension/manifest.ts (lines 50-70)
content_scripts: [
  {
    matches: ['<all_urls>'],
    js: ['content/all.iife.js', 'content-ui/all.iife.js'],
    css: ['content.css'],
  },
],

Modular Configuration via MODULE_CONFIG

For feature-based development, the boilerplate provides packages/module-manager/lib/const.ts. This file exports a MODULE_CONFIG object that defines per-feature defaults, including content script specifications.

When you run pnpm run add <feature-name>, the module manager copies stub files into the appropriate src directories and merges the feature's content script configuration into the final manifest during the next build.

Build-Time Manifest Generation

The chrome-extension/utils/plugins/make-manifest-plugin.ts Vite plugin orchestrates the final assembly. It imports the base manifest, applies any modular overrides, and writes manifest.json to the output directory.

In development mode (IS_DEV), this plugin automatically appends a hot-reload script:

// chrome-extension/utils/plugins/make-manifest-plugin.ts (lines 41-47)
if (IS_DEV) {
  addRefreshContentScript(manifest);
}

Configuring Content Script Injection and Matches

You have two primary methods to define content script injection and URL matches: direct editing of the manifest file for immediate control, or modular configuration for reusable feature patterns.

Method 1: Direct Manifest.ts Editing

For custom scripts requiring specific URL patterns, edit chrome-extension/manifest.ts directly. Add an entry to the content_scripts array specifying the matches patterns and corresponding JavaScript files.

// chrome-extension/manifest.ts
content_scripts: [
  // Default boilerplate entries...
  {
    matches: [
      'https://blog.example.com/*',
      'https://*.mysite.org/articles/*',
    ],
    js: ['content/custom-inject.iife.js'],
    css: ['content.css'],
    run_at: 'document_idle', // Options: document_start, document_end, document_idle
  },
],

Place your compiled script in chrome-extension/public/content/ to ensure it gets copied to the extension root during build.

Method 2: Modular Feature Configuration

For features you plan to reuse across projects or share with teammates, define the configuration in packages/module-manager/lib/const.ts under MODULE_CONFIG.

// packages/module-manager/lib/const.ts
export const MODULE_CONFIG = {
  // Existing modules...
  'custom-inject': {
    content_scripts: [
      {
        matches: [
          'https://blog.example.com/*',
          'https://*.mysite.org/articles/*',
        ],
        js: ['content/custom-inject.iife.js'],
      },
    ],
  },
} as const;

Then activate the feature using the module manager:

pnpm run add custom-inject

This command copies stub files into src/ and ensures your content script configuration merges into the manifest during the next build cycle.

Development Hot-Reload Configuration

When running pnpm run dev, the make-manifest-plugin.ts automatically injects refresh.js into your content scripts. This enables instant reloading when you modify source files without requiring a full extension reload in chrome://extensions.

The plugin handles this automatically, but ensure your matches patterns in development cover your testing URLs, or the hot-reload script won't attach to the page.

Summary

Frequently Asked Questions

What URL pattern syntax does the matches array support?

The matches array in manifest.ts uses standard Chrome extension match patterns. You can specify exact URLs like https://example.com/path/*, use wildcards for subdomains with https://*.example.com/*, or target all URLs with <all_urls>. The scheme (http/https) must always be specified explicitly unless using <all_urls>.

Can I inject CSS alongside JavaScript content scripts?

Yes. Each entry in the content_scripts array supports a css property containing an array of CSS file paths relative to the extension root. For example: css: ['content.css', 'content/my-feature.css']. These styles inject before the DOM is complete, ensuring your UI appears immediately when the page loads.

How does the module manager update the manifest automatically?

When you run pnpm run add <feature-name>, the module manager reads the MODULE_CONFIG definition from packages/module-manager/lib/const.ts. It copies the feature's stub files into the appropriate source directories and marks the feature as active. During the next build, make-manifest-plugin.ts merges this configuration into the base manifest from manifest.ts, generating the final manifest.json with your content script entries included.

Why is my content script not loading in development mode?

First, verify that your matches patterns in manifest.ts actually cover the URL you are testing. Development mode injects refresh.js via make-manifest-plugin.ts, but if the URL doesn't match the pattern, neither script will attach. Second, ensure you have run pnpm run build or pnpm run dev after modifying manifest.ts, as the changes only take effect after the Vite plugin regenerates manifest.json.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →