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

> Learn to configure content script injection and URL matches in the Chrome Extension Boilerplate. Take control of your extension's behavior with precise matching.

- Repository: [JongHak Seo/chrome-extension-boilerplate-react-vite](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Configure content script injection and matches by editing [`chrome-extension/manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts) for direct control, or define reusable patterns in [`packages/module-manager/lib/const.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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:

```typescript
// 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.json) to the output directory.

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

```typescript
// 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts) directly. Add an entry to the `content_scripts` array specifying the `matches` patterns and corresponding JavaScript files.

```typescript
// 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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/module-manager/lib/const.ts) under `MODULE_CONFIG`.

```typescript
// 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:

```bash
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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/make-manifest-plugin.ts) automatically injects [`refresh.js`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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

- **Primary configuration** happens in [`chrome-extension/manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/manifest.ts), where you define `content_scripts` arrays with `matches` patterns and JavaScript entry points.
- **Modular management** uses [`packages/module-manager/lib/const.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/module-manager/lib/const.ts) to define reusable `MODULE_CONFIG` entries that merge into the manifest when you run `pnpm run add <feature>`.
- **Build automation** is handled by [`chrome-extension/utils/plugins/make-manifest-plugin.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/chrome-extension/utils/plugins/make-manifest-plugin.ts), which writes the final [`manifest.json`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.json) and injects development hot-reload scripts.
- **URL pattern syntax** follows standard Chrome extension match patterns: `https://*.example.com/*`, `<all_urls>`, or specific paths.

## Frequently Asked Questions

### What URL pattern syntax does the matches array support?

The `matches` array in [`manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/make-manifest-plugin.ts) merges this configuration into the base manifest from [`manifest.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.ts), generating the final [`manifest.json`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.ts) actually cover the URL you are testing. Development mode injects [`refresh.js`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/refresh.js) via [`make-manifest-plugin.ts`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/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`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.ts), as the changes only take effect after the Vite plugin regenerates [`manifest.json`](https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/manifest.json).