# Development & Build

Source: https://inspectorlab.dev/development

> For the complete documentation index, see [llms.txt](https://inspectorlab.dev/llms.txt).

# Development & Build

Inspector Lab is a monorepo built with [Plasmo](https://www.plasmo.com/) and organized around the core extension in `apps/extension`. This page covers local development, the build process, and contribution guidelines.

## Requirements

<Field value="Node.js" type="version" required>20 or higher</Field>
<Field value="pnpm" type="package manager" required>9 or higher</Field>

## Quick Start

<Steps>
  <Step title="Clone the repository">
    ```bash
    git clone https://github.com/luangjokaj/inspector-lab.git
    cd inspector-lab
    ```
  </Step>
  <Step title="Install dependencies">
    ```bash
    pnpm install
    ```
  </Step>
  <Step title="Start the dev server">
    ```bash
    pnpm dev
    ```
    This runs Plasmo in watch mode across all packages and reloads the extension as you edit.
  </Step>
  <Step title="Load the extension locally">
    1. Open `chrome://extensions` in Chrome or a Chromium-based browser
    2. Enable **Developer mode** (toggle in the top right)
    3. Click **Load unpacked**
    4. Select `apps/extension/build/chrome-mv3-dev`
    
    The dev build will reload automatically as you make changes. Use this workflow to test changes before submitting to the Web Store.
  </Step>
</Steps>

## Project Structure

<Tree>
  <Tree.Folder name="apps" defaultOpen>
    <Tree.Folder name="extension" defaultOpen>
      <Tree.Folder name="src">
        <Tree.File name="popup/" />
        <Tree.File name="content/" />
        <Tree.File name="background/" />
        <Tree.File name="injected/" />
        <Tree.File name="manifest.config.ts" />
      </Tree.Folder>
      <Tree.Folder name="build">
        <Tree.Folder name="chrome-mv3-dev" />
        <Tree.Folder name="chrome-mv3-prod" />
      </Tree.Folder>
      <Tree.File name="package.json" />
    </Tree.Folder>
  </Tree.Folder>
  <Tree.Folder name="docs">
    <Tree.File name="ABOUT.md" />
    <Tree.File name="FEATURES.md" />
    <Tree.File name="INSTALL.md" />
    <Tree.File name="PRIVACY.md" />
  </Tree.Folder>
  <Tree.File name="package.json" />
  <Tree.File name="pnpm-workspace.yaml" />
</Tree>

## Available Commands

All commands run from the root of the monorepo:

| Command | Purpose |
|---------|---------|
| `pnpm dev` | Start development mode with watch and auto-reload across all packages |
| `pnpm build` | Build the extension for production in `apps/extension/build/chrome-mv3-prod` |
| `pnpm typecheck` | Run TypeScript type checking across all packages |
| `pnpm lint` | Lint code with ESLint |
| `pnpm format` | Format all code with Prettier |
| `pnpm format:check` | Check code formatting without writing changes |

## Building for Production

<Steps>
  <Step title="Run type checking">
    ```bash
    pnpm typecheck
    ```
    Ensures all TypeScript is valid before building.
  </Step>
  <Step title="Build the extension">
    ```bash
    pnpm build
    ```
    Outputs to `apps/extension/build/chrome-mv3-prod`.
  </Step>
  <Step title="Verify code quality">
    ```bash
    pnpm lint
    pnpm format:check
    ```
    Ensures lint and formatting standards are met.
  </Step>
</Steps>

## Before Opening a Pull Request

All of the following checks must pass:

```bash
pnpm typecheck
pnpm lint
pnpm build
pnpm format:check
```

- **Keep changes focused** — each PR should address a single concern or feature
- **Match the existing code style** — Prettier and ESLint are enforced
- **Write descriptive commit messages** — help reviewers and future maintainers understand your intent
- **For larger changes**, open an issue first to discuss the approach

## Extension Architecture

The extension is built with:

- **Plasmo** — Manifest V3 bundler and framework for Chrome extensions
- **React 19** — UI library for the inspector interface
- **Cherry UI** + **styled-components** — component library and CSS-in-JS styling in Shadow DOM
- **TypeScript** — for type safety across the codebase

Key modules live in `apps/extension/src`:

- **`popup/`** — Extension popup UI (entry point from the browser toolbar)
- **`content/`** — Content scripts injected into web pages
- **`background/`** — Service worker (background script) for extension lifecycle and messaging
- **`injected/`** — UI panels (Elements, Console, Network, etc.) rendered in an isolated Shadow DOM
- **`manifest.config.ts`** — Plasmo manifest configuration

For a deeper technical overview, see the [Architecture Overview](/architecture) page.

## Development Tips

### Hot Reload

The dev server watches for changes in source files and automatically reloads the extension. If you modify manifest permissions or background scripts, you may need to manually reload the extension from `chrome://extensions`.

### Console and Debugging

- Open the extension popup, then right-click and select **Inspect popup** to debug the popup UI
- For content scripts, open DevTools on any page where Inspector Lab is running and check the **Console** tab
- Service worker logs appear in the extension details under **Service worker** on `chrome://extensions`

### Testing on iPad

To test on iPad with [Orion by Kagi](https://orionbrowser.com/):

Install from the Chrome Web Store directly on the iPad, or create a local build and follow the step-by-step guide in [Installation & Setup](/installation) for Orion-specific sideloading.

## Dependencies

### Core Dependencies

<Field value="react" type="^19.2.8">UI framework for the inspector interface</Field>
<Field value="react-dom" type="^19.2.8">React DOM rendering and portal support</Field>
<Field value="plasmo" type="^0.90.5">Manifest V3 extension bundler and development server</Field>
<Field value="cherry-styled-components" type="^0.2.15">Cherry UI component library</Field>
<Field value="styled-components" type="^6.5.0">CSS-in-JS styling solution</Field>

### Dev Dependencies

<Field value="typescript" type="^7.0.2">Type checking and compilation</Field>
<Field value="@types/chrome" type="^0.2.5">Chrome API type definitions</Field>
<Field value="prettier" type="^3.9.6">Code formatter</Field>
<Field value="eslint" type="latest">Code linter</Field>

Updating dependencies should be done carefully — test the build and extension behavior after version bumps.

## Extension Permissions

The extension requests permissions as defined in `apps/extension/package.json`:

| Permission | Purpose |
|------------|---------|
| `activeTab` | Temporary access to the current tab when the popup opens (no standing permission) |
| `cookies` | Read and write cookies in the Storage panel |
| `scripting` | Inject content scripts into web pages |
| `storage` | Persist extension state (theme, open tabs) |
| `webRequest` | Capture network traffic in the Network panel |

Optional host permissions (`http://*/*, https://*/*`) allow full-page inspection; on restricted sites and `chrome://` pages, the inspector falls back gracefully.

<Callout type="note">
The extension launches with a user gesture (clicking the popup icon) and temporary `activeTab` access — it does not request standing permission to every site. This is a privacy-first design constraint.
</Callout>

## Sideloading for Testing

Before releasing to the Web Store, test your changes by sideloading the dev build locally:

1. Run `pnpm dev` from the repository root
2. Open `chrome://extensions` and enable **Developer mode**
3. Click **Load unpacked** and select `apps/extension/build/chrome-mv3-dev`
4. Edit any source file; the extension will rebuild and reload automatically
5. Test the updated extension on any web page by clicking the Inspector Lab icon

This workflow lets you verify all changes work correctly before submitting to the store. When ready to release, run `pnpm build` to create the production-optimized build in `apps/extension/build/chrome-mv3-prod`.

## Troubleshooting

| Issue | Solution |
|-------|----------|
| Changes don't appear after editing | Ensure `pnpm dev` is running. If you modified the manifest, manually reload the extension from `chrome://extensions` |
| TypeScript errors on build | Run `pnpm typecheck` to see all type errors, then fix them before building |
| Extension doesn't load unpacked | Check that you're pointing to the correct build folder (`chrome-mv3-dev` or `chrome-mv3-prod`), and that it contains a `manifest.json` |
| Inspector panel doesn't appear | Open the extension popup on any web page. If it still doesn't work, check the background service worker logs on `chrome://extensions` |
| Lint or format errors block the build | Run `pnpm lint --fix` and `pnpm format` to auto-correct most issues, then run the checks again |

## Contributing

We welcome issues and pull requests. Please:

- Open an issue for larger changes before investing time in implementation
- Keep commits focused and well-described
- Run the full test suite (`pnpm typecheck`, `pnpm lint`, `pnpm build`, `pnpm format:check`) before submitting
- Match the existing code style (enforced by Prettier and ESLint)

For more details, see the [Contributing section in the main README](https://github.com/luangjokaj/inspector-lab#contributing).

## License

Inspector Lab is released under the [MIT License](https://github.com/luangjokaj/inspector-lab/blob/main/LICENSE). © [Luan Gjokaj](https://github.com/luangjokaj)

---

<Columns cols={2}>
  <Card title="Architecture Overview" icon="layers" href="/architecture">Learn how Inspector Lab is structured at a high level.</Card>
  <Card title="Message Protocol" icon="message-square" href="/messaging">Understand how the extension communicates internally.</Card>
</Columns>
