npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@metricinsights/pp-dev

v1.2.1

Published

Portal Page dev build tool

Downloads

1,363

Readme

pp-dev

The PP Dev Helper is a development framework and build tool for Metric Insights' Portal Pages, designed to make the lives of PP developers easier:

  • Build and test Portal Pages locally
  • Proxy API requests to a Metric Insights server
  • Hot module replacement for faster development
  • Image optimization and asset management
  • Template variable transformation
  • Code synchronization with Metric Insights instances

pp-dev is based on Vite.

📸 Feature tour — screenshots of the dev panel, Request Inspector, and Variables Editor.

Installation

npm install @metricinsights/pp-dev

Peer Dependencies

This package requires Next.js as a peer dependency for certain functionality:

npm install next@^15

Note: pp-dev requires Next.js version 15 or higher (but less than 17) to be installed in your project. This is a peer dependency, meaning it won't be automatically installed with pp-dev.

Package Structure

The pp-dev package provides multiple entry points for different use cases:

// Main package (includes everything)
import ppDev from '@metricinsights/pp-dev';

// Plugin only (for Vite integration)
import { vitePPDev } from '@metricinsights/pp-dev/plugin';

// Helpers only (defineConfig and utility functions)
import { defineConfig } from '@metricinsights/pp-dev/helpers';

// Client assets (for development UI)
import '@metricinsights/pp-dev/client/css/client.css';

Configuration

Configuration File

Create a configuration file named pp-dev.config with one of these extensions:

  • .ts (recommended)
  • .js or .cjs (for CommonJS)
  • .json

Alternatively, you can define configuration in your package.json using the pp-dev key.

Configuration Examples

TypeScript (recommended)

// pp-dev.config.ts
import { defineConfig } from '@metricinsights/pp-dev';

export default defineConfig({
  mi: {
    url: 'https://mi.company.com',
    token: process.env.MI_ACCESS_TOKEN,
    mode: 'standalone',
    apiVersion: 7,
  },
  app: {
    id: 123,
    type: 'template',
  },
});

JavaScript (CommonJS)

// pp-dev.config.js
const { defineConfig } = require('@metricinsights/pp-dev');

module.exports = defineConfig({
  mi: {
    url: 'https://mi.company.com',
    mode: 'standalone',
    apiVersion: 7,
  },
  app: {
    id: 123,
    type: 'template',
  },
});

JSON

{
  "mi": {
    "url": "https://mi.company.com",
    "mode": "standalone",
    "apiVersion": 7
  },
  "app": {
    "id": 123,
    "type": "template"
  }
}

package.json

{
  "name": "my-portal-page",
  "pp-dev": {
    "mi": {
      "url": "https://mi.company.com",
      "mode": "standalone"
    },
    "app": {
      "id": 123
    }
  }
}

Configuration Options

mi — Metric Insights connection

| Field | Type | Default | Description | |--------------|-----------------------------------|----------------|-----------------------------------------------------------| | url | string | — | URL of the Metric Insights instance | | token | string | MI_ACCESS_TOKEN env | Personal access token for authentication | | mode | 'standalone' \| 'embedding' | 'standalone' | Standalone hides the MI navigation; embedding keeps it | | include | 'top-bar' \| 'shared-components'| — | Bundle MI top-bar assets into the build (requires standalone) | | apiVersion | 6 \| 7 | 7 | MI API version to target |

app — Portal Page identity

| Field | Type | Default | Description | |--------|----------------------------|--------------------------|-------------------------------------------------------------| | id | number | — | Portal Page ID used to fetch template variables | | type | 'template' \| 'page' | 'template' | template syncs back to MI; page is standalone-only | | name | string | package.json#name | Template name on the MI instance (usually auto-resolved) |

proxy — Request proxying

| Field | Type | Default | Description | |---------------------|-----------|----------|------------------------------------------------------| | cache | boolean | true | Enable caching of proxied requests | | cacheTtl | number | 600000 | Cache TTL in milliseconds (10 minutes) | | tls.allowSelfSigned | boolean | false | Allow self-signed SSL certificates on the MI server |

build — Build output

| Field | Type | Default | Description | |---------------------|-------------------------------------------------------------|----------|--------------------------------------------------------------------------------------| | outDir | string | 'dist' | Output directory | | zip | boolean \| { fileName?: string; outDir?: string; inDir?: string } | true | Zip build output. Object form customizes filename and directories. | | versionFile | boolean \| { enabled?: boolean; fileNameTemplate?: string } | true | Write a VERSION file into the build | | imageOptimisations| boolean \| Record<string, unknown> | true | Image optimization. See vite-plugin-image-optimizer for object options |

inspector — Request Inspector

| Field | Type | Default | Description | |----------------|-----------|-------------|----------------------------------------------------------------| | enabled | boolean | true | Enable the request inspector | | maxMemory | number | 104857600 | Max total body memory (bytes) before oldest entries are evicted (default 100 MB) | | captureLimit | number | 10485760 | Max body size captured per request/response (bytes, default 10 MB). Larger bodies are stored truncated. |

sync — Template sync

| Field | Type | Default | Description | |--------------|----------|-------------|-----------------------------------------| | backupsDir | string | 'backups' | Directory for backups from the MI server |

devPanel — Dev panel appearance

| Field | Type | Default | Description | |------------|-----------------------------------------------------------------|------------------|-----------------------------------------------------------------------------| | position | 'top-left' \| 'top-right' \| 'bottom-left' \| 'bottom-right' | 'bottom-right' | Screen corner the dev panel is anchored to | | hidden | boolean | false | Fully hide the panel. Restore in the browser with ?pp-dev-panel=show | | autoHide | boolean | false | Panel slides behind the screen edge leaving a thin strip; hover reveals it |

These values are defaults: the panel itself has a settings popover (gear icon) with a corner picker, an auto-hide toggle and a hide button, and the panel can be dragged by its grip handle and snapped to any corner. Runtime choices are persisted in the browser's localStorage (pp-dev-info-position, pp-dev-info-auto-hide, pp-dev-info-hidden) and take precedence over the config until "Reset to config defaults" is clicked in the popover. The URL params ?pp-dev-panel=show / ?pp-dev-panel=hide set a persistent override too — handy for restoring a hidden panel or taking clean screenshots. Note that localStorage is origin-scoped, so overrides apply to every pp-dev app served on the same host and port. See the Dev Panel section for the full feature description.

Validation

pp-dev validates your config at startup and reports problems clearly:

| Condition | Behaviour | |---|---| | mi.include set + mi.mode !== 'standalone' | error | | mi.url missing + mi.mode === 'embedding' or app.type === 'template' | error | | mi.url missing + mi.mode === 'standalone' + app.type === 'page' | warning | | app.type === 'template' without app.id | error | | app.type === 'page' + mi.mode === 'standalone' without app.id | error | | app.name missing and no package.json#name | error | | devPanel.position not one of the four corners | error |

Environment Variables

| Variable | Description | |----------------------------------|-------------------------------------------------------------------------------------| | MI_ACCESS_TOKEN | Default value for mi.token when not set in config | | PP_DEV_DIST_ZIP | true/false — override build.zip for pp-dev build / pp-dev next-build | | PP_DEV_DIST_ZIP_DIR | Override the ZIP output directory (build.zip.outDir) | | PP_DEV_DIST_ZIP_FILENAME | Override the ZIP file name (build.zip.fileName) | | PP_DEV_VERSION_MANIFEST | true/false — override build.versionFile (VERSION/BUILD-MANIFEST generation) | | PP_DEV_VERSION_FILE_TEMPLATE | Override the VERSION file name template |

The PP_DEV_DIST_ZIP*/PP_DEV_VERSION_* variables are read by pp-dev build and pp-dev next-build; an equivalent CLI flag always takes precedence over its env var. See Build / Next.js Build.

Local development and network exposure: pp-dev is a development tool. It assumes a trusted machine. Personal access tokens and session helpers are still sensitive: they can authenticate to your Metric Insights backend as you.

  • Prefer binding the dev server to localhost when you do not need access from other devices. If you use --host (or equivalent) so the app listens on all interfaces or your LAN, other machines on the same network can reach the dev server and its dev-only routes. Treat that like exposing credentials: use only on networks you trust, or restrict access with your OS firewall.
  • Do not commit real tokens; keep them in .env (gitignored) or your secret store.

Migrating from 0.x

Run the built-in codemod to upgrade your config automatically:

npx @metricinsights/pp-dev migrate

Options:

| Option | Description | |---|---| | [config] | Path to config file (auto-detected if omitted) | | --dry-run | Preview the migrated output without writing | | --format ts\|js\|json | Override output format | | --output <file> | Write to a specific file instead of overwriting | | --no-backup | Skip creating a .bak backup of the original |

The command detects flat 0.x configs and legacy pp-watch.config.* files, converts them to the new grouped format, and writes a .bak backup before overwriting.

Field mapping (0.x → 1.0):

| 0.x | 1.0 | |---|---| | backendBaseURL | mi.url | | personalAccessToken | mi.token | | miHudLess: true | mi.mode: 'standalone' | | miHudLess: false | mi.mode: 'embedding' | | integrateMiTopBar: true | mi.mode: 'standalone', mi.include: 'top-bar' | | integrateMiTopBar: { addSharedComponentsScripts: true } | mi.include: 'shared-components' | | v7Features: true | mi.apiVersion: 7 | | v7Features: false | mi.apiVersion: 6 | | appId / portalPageId | app.id | | templateName | app.name (usually omit — auto-resolved from package.json#name) | | templateLess: true | app.type: 'page' | | templateLess: false | app.type: 'template' | | enableProxyCache | proxy.cache | | proxyCacheTTL | proxy.cacheTtl | | disableSSLValidation: true | proxy.tls.allowSelfSigned: true | | distZip | build.zip | | versionPlugin | build.versionFile | | imageOptimizer | build.imageOptimisations | | outDir | build.outDir | | syncBackupsDir | sync.backupsDir |

CLI Commands

Global Options

| Option | Description | | ------------------------ | -------------------------------------------------------------------------------- | | -c, --config <file> | Path to configuration file (default: pp-dev.config.js) | | --base <path> | Public base path (default: /) | | -l, --logLevel <level> | Log level: trace, debug, info, warn, error, silent (default: info) | | --clearScreen | Clear screen before logging | | --mode <mode> | Environment mode: development, production, test (default: development) |

Development Server

pp-dev [root] [options]
# Aliases: pp-dev dev, pp-dev serve

| Option | Default | Description | | --------------- | ----------- | --------------------------------- | | [root] | . | Root directory of the application | | --host <host> | localhost | Server hostname | | --port <port> | 3000 | Server port | | --open [path] | - | Open browser on server start | | --strictPort | - | Exit if port is already in use |

Development Shortcuts:

  • l - Proxy re-login (refresh authentication)
  • r - Restart dev server
  • u - Show server URLs
  • q - Quit dev server

Next.js Development

pp-dev next [options]
# Aliases: pp-dev next-server, pp-dev next-dev

| Option | Default | Description | | --------------- | ----------- | --------------------------------- | | [root] | . | Root directory of the application | | --port <port> | 3000 | Server port | | --host <host> | localhost | Server hostname |

Build

pp-dev build [options]

| Option | Default | Description | | ------------------------------- | --------- | ------------------------------------------------------ | | [root] | . | Root directory of the application | | --target <target> | modules | Transpile target | | --outDir <dir> | dist | Output directory | | --assetsDir <dir> | assets | Assets directory under outDir | | --changelog [file] | true | Create changelog file | | --distZip / --no-distZip | see below | Override build.zip — pack (or skip) the output ZIP | | --distZipDir <dir> | see below | Override the ZIP output directory (build.zip.outDir) | | --distZipFilename <file> | see below | Override the ZIP file name (build.zip.fileName) | | --versionManifest / --no-versionManifest | see below | Override build.versionFile — emit (or skip) VERSION/BUILD-MANIFEST | | --versionFileTemplate <tpl> | see below | Override the VERSION file name template |

The --distZip*/--versionManifest* flags (and their PP_DEV_* env var equivalents, see Environment Variables) let CI or ad-hoc builds override the build.zip and build.versionFile config without editing pp-dev.config. Precedence: CLI flag > env var > config file > built-in default. The same flags are available on pp-dev next-build (below).

Next.js Build

pp-dev next-build [options]

Plain next build only produces the Next.js static export — no VERSION file, BUILD-MANIFEST, or ZIP archive. pp-dev next-build runs next build and then applies the same post-build steps as pp-dev build, so Next.js and Vite templates produce build artifacts in the same format:

  1. Runs next build (requires output: 'export' in next.config)
  2. Writes VERSION-*.json + BUILD-MANIFEST.json into the export directory (build.versionFile)
  3. Zips the export directory into dist-zip/<name>.zip (build.zip)

If a project using withPPDev() still runs plain next build (e.g. directly, or via a build script nobody updated), withPPDev() prints a console warning during the production build phase suggesting pp-dev next-build instead. The warning is suppressed automatically when the build was started by pp-dev next-build itself.

Use it in place of next build in your package.json:

{
  "scripts": {
    "build": "pp-dev next-build --changelog"
  }
}

| Option | Default | Description | | ------------------------------- | --------- | ------------------------------------------------------ | | [root] | . | Root directory of the application | | --changelog [file] | true | Create changelog file | | --distZip / --no-distZip | see below | Override build.zip — pack (or skip) the output ZIP | | --distZipDir <dir> | see below | Override the ZIP output directory (build.zip.outDir) | | --distZipFilename <file> | see below | Override the ZIP file name (build.zip.fileName) | | --versionManifest / --no-versionManifest | see below | Override build.versionFile — emit (or skip) VERSION/BUILD-MANIFEST | | --versionFileTemplate <tpl> | see below | Override the VERSION file name template |

Migration

pp-dev migrate [config] [options]

| Option | Description | |---|---| | [config] | Config file to migrate (auto-detected if omitted) | | --dry-run | Preview output without writing | | --format ts\|js\|json | Output format | | --output <file> | Write to a specific path | | --no-backup | Skip .bak backup |

Changelog Generation

pp-dev changelog [oldAssetPath] [newAssetPath] [options]

| Option | Default | Description | | ------------------------ | ---------------- | -------------------------- | | [oldAssetPath] | - | Path to previous assets | | [newAssetPath] | - | Path to current assets | | --oldAssetsPath <path> | - | Path to previous assets | | --newAssetsPath <path> | - | Path to current assets | | --destination <path> | . | Changelog output directory | | --filename <name> | CHANGELOG.html | Changelog filename |

Icon Font Generation

pp-dev generate-icon-font [source] [destination] [options]

| Option | Default | Description | | ---------------------- | ----------- | ------------------------------- | | [source] | - | Source directory with SVG icons | | [destination] | - | Output directory | | --source <path> | - | Source directory with SVG icons | | --destination <path> | - | Output directory | | --fontName <name> | icon-font | Font name |

Next.js Integration

  1. Add a pp-dev.config.ts to your project root
  2. Update package.json scripts:
    {
      "scripts": {
        "dev": "pp-dev next",
        "build": "pp-dev next-build"
      }
    }
    pp-dev next-build replaces a plain next build so the Next.js template produces the same VERSION/BUILD-MANIFEST/ZIP artifacts as pp-dev build — see Next.js Build.
  3. Wrap your Next.js config:
// next.config.js
const { withPPDev } = require('@metricinsights/pp-dev');

module.exports = withPPDev({
  // your Next.js config
});

Vite Configuration

For custom build configuration, create a vite.config file. See Vite Configuration for details.

Dev Panel

pp-dev injects a floating dev panel into every served page. It shows the package name and version, the backend URL, the template mode and the App ID, and hosts the template Sync button. Since 1.0 the panel is fully repositionable and can be hidden.

Dev panel settings popover

Position

The panel can be anchored to any of the four screen corners (default: bottom-right). Three ways to move it:

  • Drag & snap — grab the grip handle (six dots on the panel's left side) and drag; on release the panel snaps to the nearest corner. Dragging works across iframes and is cancelled with Escape.
  • Settings popover — click the gear icon and pick a corner in the 2×2 grid.
  • Config default — set devPanel.position in pp-dev.config (see below).

The minimize arrow, the panel's shadow, rounded corner and slide direction all mirror automatically for left/top placements. Sync notification popups stack from the screen edge opposite the panel so they never cover it.

Auto-hide

Toggle Auto-hide in the settings popover (or set devPanel.autoHide: true). The panel slides behind the nearest screen edge leaving a 4px accent strip; hovering the strip for ~300 ms slides it out, and it hides again ~500 ms after the pointer leaves. Keyboard focus inside the panel keeps it revealed. While auto-hide is active the minimize arrow acts as a pin button that returns the panel to normal mode.

Theme

The settings popover has an Auto / Dark / Light switcher. "Auto" follows the OS/browser preference; the other two force an override. The choice is shared (via the same localStorage key) with the standalone Request Inspector and Variables Editor pages, which also each have their own copy of the switcher for when they're opened directly without the panel present.

Hiding and restoring

Hide panel in the settings popover (or devPanel.hidden: true) removes the panel from view entirely. To bring it back, open any page with ?pp-dev-panel=show in the URL — the override persists across reloads. The symmetric ?pp-dev-panel=hide hides it, which is handy for demos and clean screenshots.

State persistence

Runtime choices are saved in the browser's localStorage (pp-dev-info-position, pp-dev-info-auto-hide, pp-dev-info-hidden, pp-dev-info-theme) and take precedence over config values. Reset to config defaults in the settings popover clears all overrides. Storage is origin-scoped: overrides apply to every pp-dev app served on the same host and port, and a Metric Insights page that clears origin storage will reset them to config defaults.

Configuration

// pp-dev.config.ts
export default defineConfig({
  devPanel: {
    position: 'bottom-right', // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
    hidden: false,            // hide the panel entirely (restore with ?pp-dev-panel=show)
    autoHide: false,          // slide behind the screen edge, reveal on hover
  },
});

See the devPanel option reference for details.

Page variables

For pages with a template (app.type: 'template'), the settings popover has:

  • Reload variables — refetches the page's live variable values from MI right now (bypassing the usual request-level cache) and reloads the page, so [VarName] substitution reflects a just-saved value without restarting the dev server.
  • Open variables editor… — opens the standalone Variables Editor page.

Pages without a template (app.type: 'page') have no variables, so this group — and the button that opens the editor — is hidden.

Variables Editor

A standalone page at /@pp-dev/variables-editor, alongside the Request Inspector, with two tabs:

  • Schema — view/edit the template's __template_variables.json (add/remove variables, change type, default, additional_options, etc.), with a raw-JSON escape hatch.

Variables Editor — Schema tab

  • Values — edit the page's live variable values in place, with type-aware widgets (searchable select for static options, a per-item form for list, …). A JSON mode (View/edit raw JSON) shows/accepts the same values as plain JSON — list-type values as native arrays, not double-escaped strings — with Save to JSON file… / Import from JSON file… buttons, and flags values that don't match a declared option, changed since the last load, or aren't in the schema.

Variables Editor — Values tab

Both the active tab and Values' JSON mode are reflected in the URL (?tab=values&mode=json), so a specific view can be bookmarked or shared.

See the feature tour for more screenshots, including the advanced/raw-JSON views and the theme switcher.

See TEMPLATE_VARIABLES.md — also shipped inside the published package — for the __template_variables.json schema this feature reads.

Request Inspector

pp-dev includes a built-in request inspector that captures every proxied and locally-served HTTP request made during development. It is enabled by default.

Web UI

Open http://localhost:3000/@pp-dev/inspector (replace port as needed) in any browser tab while the dev server is running. The UI shows:

  • A scrollable list of captured requests with method, status, source badge, and timing
  • Full request and response headers, with a Copy button per section
  • Request and response bodies rendered as text for JSON/HTML/CSS/plain-text content types, with Copy and Save buttons
  • Binary bodies (images, fonts, archives) show metadata only and offer a Save button

Request Inspector — request list

Selecting a request opens the detail pane with headers and a syntax-highlighted body:

Request Inspector — request detail

  • A Clear button in the top-right removes all stored entries

Source badges

Each request in the list displays a colored letter badge to the left of the HTTP status:

| Badge | Color | Meaning | |-------|--------|----------------------------------------------| | P | Purple | Forwarded to the upstream Metric Insights server (proxy) | | C | Amber | Served from the local proxy cache | | L | Grey | Served locally (static file, dev route, etc.) |

Console banner

The dev panel script prints a one-line banner to the browser DevTools console when the page loads:

pp-dev  🔍 Request Inspector  →  http://localhost:3000/@pp-dev/inspector

The message persists in DevTools history so it is visible even when you open the console after the page has loaded.

REST API

The inspector also exposes a lightweight JSON API, useful for tooling and AI agents:

| Method | Path | Description | |----------|-------------------------|---------------------------------------------| | GET | /@api/requests | Paginated list of captured requests (metadata only, no bodies) | | GET | /@api/requests/:id | Full entry including captured request/response bodies (base64-encoded) | | GET | /@api/requests/stats | Store stats: entry count, memory usage, limits | | DELETE | /@api/requests | Clear all stored entries |

GET /@api/requests accepts ?limit= (default 50) and ?offset= query parameters for pagination.

Bodies in GET /@api/requests/:id are returned as base64 strings in requestBody / responseBody fields alongside requestContentType / responseContentType. A *Truncated: true flag indicates the body exceeded captureLimit and was cut off.

Configuration

// pp-dev.config.ts
export default defineConfig({
  inspector: {
    enabled: true,         // set to false to disable entirely
    maxMemory: 100 * 1024 * 1024,   // evict oldest entries above 100 MB
    captureLimit: 10 * 1024 * 1024, // capture at most 10 MB per body
  },
});

Troubleshooting

Common Issues

Next.js Peer Dependency Error

If you encounter an error like "Next.js is required but not available":

  1. Install Next.js in your project:

    npm install next@^15
  2. Verify the installation:

    npm list next
  3. Check your package.json:

    {
      "dependencies": {
        "next": "^15.0.0"
      }
    }

Version Compatibility

  • pp-dev requires Next.js version 15 or higher (but less than 17)
  • Node.js version 24 or higher is required
  • TypeScript version 5 or higher is recommended

Getting Help

  • Check the GitHub Issues for known problems
  • Review the CHANGELOG.md for recent changes
  • Ensure all peer dependencies are properly installed