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

tauri-nuxt-dev

v0.0.1

Published

A development runner for Tauri and Nuxt with automatic port resolution.

Readme

tauri-nuxt-dev

CI npm version npm downloads license

One command to run Tauri + Nuxt in development, with automatic free-port resolution.

Replaces the usual copy-pasted scripts/dev.ts: pick a free port, start Nuxt there, point Tauri at the same URL.

pnpm add -D tauri-nuxt-dev @tauri-apps/cli
# package.json → "dev": "tauri-nuxt-dev"
pnpm dev

Contents

Why this exists

Tauri’s dev flow needs both sides to agree on a URL:

  1. Nuxt binds a free port.
  2. Tauri loads that exact devUrl.
  3. beforeDevCommand starts Nuxt on the same port.

If 3000 is busy, a naive script either crashes or leaves Tauri pointing at the wrong port. This library resolves a free port once, then builds a Tauri --config override so both stay in sync.

preferred port (config / NUXT_PORT / --port / 3000)
        │
        ▼
  get-port-please  ──►  free port
        │
        ├─► beforeDevCommand  (package-manager aware `nuxt:dev`)
        └─► build.devUrl      (http://localhost:<port>)
                │
                ▼
           tauri dev --config <json>

Your on-disk src-tauri/tauri.conf.json is never modified.

Features

  • Auto free port via get-port-please
  • c12 project configtauri-nuxt-dev.config.ts or package.json#tauri-nuxt-dev
  • Package-manager aware — pnpm / npm / yarn / bun nuxt:dev scripts
  • Local Tauri CLI first — resolves @tauri-apps/cli, falls back to PATH
  • CLI + librarytauri-nuxt-dev bin, or tauriNuxtDev() in a script
  • Safe spawn — no shell: true; shell-quoted beforeDevCommand only

Install

# pnpm
pnpm add -D tauri-nuxt-dev @tauri-apps/cli

# npm
npm i -D tauri-nuxt-dev @tauri-apps/cli

# yarn
yarn add -D tauri-nuxt-dev @tauri-apps/cli

# bun
bun add -d tauri-nuxt-dev @tauri-apps/cli

Requirements

| | | | -------- | ------------------------------------------------------------------------------------------------------------ | | Node.js | ^20.19 / ^22.12 / >=24 (ESM only) | | Frontend | Nuxt app with a nuxt:dev or dev script (or a local nuxt binary) | | Tauri | @tauri-apps/cli locally (preferred), or tauri on PATH |

Quick start

1. Add the script

{
  "scripts": {
    "nuxt:dev": "nuxt dev",
    "dev": "tauri-nuxt-dev"
  }
}

2. Run

pnpm dev

If 3000 is free you get http://localhost:3000. If not:

Port 3000 is busy, using port 3001

3. Optional config

// tauri-nuxt-dev.config.ts
import { defineConfig } from 'tauri-nuxt-dev';

export default defineConfig({
  port: 3000,
  nuxt: 'vpr', // or omit to auto-detect `nuxt:dev`
});

Programmatic (same runner)

import { tauriNuxtDev } from 'tauri-nuxt-dev';

process.exitCode = await tauriNuxtDev({ port: 3000 });

Configuration (c12)

Project settings load with c12 — same pattern as genbumppush.

Where config lives

| Source | Example | | -------------- | -------------------------------------------------------------- | | Config file | tauri-nuxt-dev.config.ts / .js / .mjs / .cjs / .json | | package.json | "tauri-nuxt-dev": { … } | | Explicit path | --config ./custom.config.ts |

Discovery is rooted at cwd (--cwd / options.cwd).

TypeScript configs: .ts config files load through native ESM when possible, then fall back to the optional peer jiti. Install it if your runtime cannot import the file directly:

pnpm add -D jiti

JSON and package.json#tauri-nuxt-dev configs need no extra dependency.

Resolution order (later wins)

  1. Built-in defaults (empty; ports still honor NUXT_PORT / PORT)
  2. "tauri-nuxt-dev" key in package.json
  3. C12 config file (or the configFile you pass)
  4. CLI flags / programmatic options (highest priority)

loadTauriNuxtDevConfig also loads .env via setupDotenv({ cwd }) without overwriting existing env vars. Secrets belong in the environment — not in config files.

TauriNuxtDevConfig fields

| Field | Type | Default | Description | | ----------- | -------------------- | ----------------------------- | ------------------------------------ | | port | number | NUXT_PORT / PORT / 3000 | Preferred port | | portRange | [from, to] | [port, port + 99] | Inclusive fallback scan | | host | string | unset / HOST | Port checks, Nuxt --host, devUrl | | nuxt | string \| string[] | auto | Nuxt starter binary or full argv | | tauriArgs | string[] | [] | Extra args for tauri dev |

Runtime-only options on tauriNuxtDev (cwd, configFile, env, logger, signal) are never read from a config file.

defineConfig

import { defineConfig } from 'tauri-nuxt-dev';

export default defineConfig({
  port: 3000,
  portRange: [3000, 3100],
  host: '0.0.0.0',
  nuxt: 'vpr',
  tauriArgs: ['--features', 'debug'],
});

Same object in package.json:

{
  "tauri-nuxt-dev": {
    "port": 3000,
    "nuxt": "vpr",
    "tauriArgs": ["--features", "debug"]
  }
}

The return type is the package’s own TauriNuxtDevConfig — not c12 internals — so consumer declaration emit stays portable under pnpm (see genbumppush#6).

loadTauriNuxtDevConfig

import { loadTauriNuxtDevConfig } from 'tauri-nuxt-dev';

const config = await loadTauriNuxtDevConfig(process.cwd());

const forced = await loadTauriNuxtDevConfig(process.cwd(), './custom.config.ts', {
  port: 4000,
});

CLI

tauri-nuxt-dev [options] [-- <tauri dev args>]

| Flag | Description | | ----------------- | ---------------------------------------------------- | | --config <file> | Explicit C12 config file | | --port <n> | Preferred port | | --host <host> | Port check + Nuxt --host + devUrl host | | --nuxt <bin> | Nuxt starter binary (default: package-manager aware) | | --cwd <dir> | Config discovery + spawn directory | | -h, --help | Help | | -v, --version | Version |

  • Unrecognized flags and everything after -- go to tauri dev.
  • CLI flags always win over the config file.
tauri-nuxt-dev
tauri-nuxt-dev --port 4000
tauri-nuxt-dev --config ./tauri-nuxt-dev.config.ts
tauri-nuxt-dev --host 0.0.0.0
tauri-nuxt-dev --nuxt vpr
tauri-nuxt-dev -- --features debug
tauri-nuxt-dev --port 4000 -- --target aarch64-apple-darwin

Recipes

Vite+ / vpr template

// tauri-nuxt-dev.config.ts
import { defineConfig } from 'tauri-nuxt-dev';

export default defineConfig({ nuxt: 'vpr' });

or

tauri-nuxt-dev --nuxt vpr
await tauriNuxtDev({ nuxt: ['vpr', 'nuxt:dev'] });

Device / mobile testing (bind all interfaces)

tauri-nuxt-dev --host 0.0.0.0

Nuxt gets --host 0.0.0.0. Tauri’s devUrl still uses localhost so the webview can connect (0.0.0.0 / :: are mapped automatically).

Force a port or range

import { defineConfig } from 'tauri-nuxt-dev';

export default defineConfig({
  port: 4000,
  portRange: [4000, 4100],
});

Programmatic runner with abort + custom logger

import { tauriNuxtDev } from 'tauri-nuxt-dev';

const code = await tauriNuxtDev({
  cwd: process.cwd(),
  configFile: './tauri-nuxt-dev.config.ts',
  port: 3000,
  host: '0.0.0.0',
  nuxt: 'vpr',
  tauriArgs: ['--features', 'debug'],
  env: { FOO: 'bar' },
  logger: {
    info: (m) => console.info(m),
    warn: (m) => console.warn(m),
    error: (m) => console.error(m),
  },
  signal: AbortSignal.timeout(60_000),
});

process.exitCode = code;

How it works

  1. Load c12 config (file / package.json + CLI/API overrides).
  2. Resolve a free port with get-port-please
    preferred → fallback range [port, port+99].
  3. Build the Nuxt command (package-manager aware — see below).
  4. Build a one-off Tauri config override:
    {
      "build": {
        "devUrl": "http://localhost:<port>",
        "beforeDevCommand": "<nuxt command> --port <port>"
      }
    }
  5. Spawn tauri dev --config <json> with shell: false.
  6. Forward signals (SIGINT / SIGTERM / AbortSignal) and resolve with the child exit code (0 on clean signal exit).
# equivalent shape of what the runner passes to Tauri
tauri dev --config '{"build":{"devUrl":"http://localhost:3001","beforeDevCommand":"pnpm run nuxt:dev -- --port 3001"}}'

Package-manager aware Nuxt command

With "nuxt:dev": "nuxt dev" in package.json:

| PM | beforeDevCommand | | ---- | ------------------------------------ | | pnpm | pnpm run nuxt:dev -- --port <port> | | npm | npm run nuxt:dev -- --port <port> | | yarn | yarn run nuxt:dev --port <port> | | bun | bun run nuxt:dev --port <port> |

Fallbacks when there is no nuxt:dev script:

  1. Local nuxt package → node <nuxt-bin> dev …
  2. nuxt dev on PATH

Package-manager detection order: packageManager field → lockfile (pnpm-lock.yaml, yarn.lock, bun.lockb/bun.lock, package-lock.json) → npm_config_user_agentnpm.

Programmatic API

import {
  // runner + config
  tauriNuxtDev,
  defineConfig,
  loadTauriNuxtDevConfig,
  toConfigOverrides,
  defaults,
  // ports
  resolveDevPort,
  parsePort,
  // Tauri config payload
  buildTauriDevConfig,
  serializeTauriDevConfig,
  toBrowserHost,
  // Nuxt command
  resolveNuxtDevCommandArgs,
  formatShellCommand,
  shellQuote,
  // resolution helpers
  detectPackageManager,
  resolveLocalNuxtBin,
  resolveTauriCli,
} from 'tauri-nuxt-dev';

tauriNuxtDev(options?): Promise<number>

End-to-end: load config → free port → spawn tauri dev → return exit code.

| Option | Type | Default | Notes | | ------------ | -------------------- | ----------------- | ---------------------------- | | port | number | env / 3000 | Overrides config file | | portRange | [from, to] | [port, port+99] | | | host | string | — | Port check + Nuxt + devUrl | | nuxt | string \| string[] | auto | Binary or full argv | | tauriArgs | string[] | [] | Forwarded to tauri dev | | cwd | string | process.cwd() | Runtime-only | | configFile | string | auto | Runtime-only | | env | NodeJS.ProcessEnv | process.env | Runtime-only | | logger | Logger | consola | Runtime-only | | signal | AbortSignal | — | Runtime-only |

interface Logger {
  info: (message: string) => void;
  warn: (message: string) => void;
  error: (message: string) => void;
}

Ports

import { resolveDevPort, parsePort } from 'tauri-nuxt-dev';

const port = await resolveDevPort(
  { port: 3000, portRange: [3000, 3100], host: '127.0.0.1' },
  process.env,
);

parsePort('3000'); // 3000
parsePort('0'); // undefined
parsePort('abc'); // undefined

| resolveDevPort option | Default | | ----------------------- | ----------------------------- | | port | NUXT_PORT / PORT / 3000 | | portRange | [port, port+99] | | host | HOST env | | name | 'tauri-nuxt-dev' |

parsePort accepts a string or number and returns undefined outside 1..65535.

Tauri config payload

import { buildTauriDevConfig, serializeTauriDevConfig, toBrowserHost } from 'tauri-nuxt-dev';

const config = buildTauriDevConfig({
  port: 3000,
  host: '0.0.0.0',
  beforeDevCommand: 'pnpm run nuxt:dev -- --port 3000 --host 0.0.0.0',
});
// { build: { devUrl: 'http://localhost:3000', beforeDevCommand: '…' } }

serializeTauriDevConfig(config); // JSON string for `--config`
toBrowserHost('::1'); // '[::1]'
toBrowserHost('0.0.0.0'); // 'localhost'

Nuxt command helpers

import { resolveNuxtDevCommandArgs, formatShellCommand, shellQuote } from 'tauri-nuxt-dev';

const args = resolveNuxtDevCommandArgs({
  cwd: process.cwd(),
  port: 4000,
  host: '0.0.0.0',
});
// ['pnpm', 'run', 'nuxt:dev', '--', '--port', '4000', '--host', '0.0.0.0']

formatShellCommand(args);
// 'pnpm run nuxt:dev -- --port 4000 --host 0.0.0.0'

shellQuote('hello world'); // "'hello world'" (POSIX)
shellQuote('hello world', 'win32'); // '"hello world"' (cmd.exe)

Resolution helpers

import { detectPackageManager, resolveLocalNuxtBin, resolveTauriCli } from 'tauri-nuxt-dev';

detectPackageManager('/path/to/app');
// { name: 'pnpm', packageJsonPath: '…/package.json', scripts: { … } }

resolveLocalNuxtBin();
// absolute path to nuxt bin, or undefined

resolveTauriCli();
// local: { command: process.execPath, prefixArgs: [entry], source: 'local' }
// path:  { command: 'tauri', prefixArgs: [], source: 'path' }

Local Tauri CLI is spawned as node <resolved-entry> … (no shell, cross-platform).

Environment variables

| Variable | Role | | ----------------------- | ------------------------------------ | | NUXT_PORT | Preferred port after config/--port | | PORT | Fallback preferred port | | HOST | Default host for port checks | | npm_config_user_agent | Last-resort package-manager hint |

Security

  • Child processes use shell: false.
  • Local Tauri CLI runs via node <resolved-entry>, not a shell string.
  • Ports are validated as safe integers in 1..65535.
  • devUrl hosts are validated; wildcard binds map to localhost and bare IPv6 is bracketed.
  • beforeDevCommand is a shell string only because Tauri requires one; argv tokens are shell-quoted for the platform (sh/POSIX single quotes on Unix, cmd.exe double quotes on Windows).
  • Unknown CLI args are argv passthrough to tauri dev, not shell interpolation.
  • .env is loaded without overwriting existing environment variables.

Report vulnerabilities via GitHub Security Advisories.

Migrating from scripts/dev.ts

Before — hand-rolled port scan + spawn in a template script.

After — config + one line:

// tauri-nuxt-dev.config.ts
import { defineConfig } from 'tauri-nuxt-dev';

export default defineConfig({ nuxt: 'vpr' });
{
  "scripts": {
    "dev": "tauri-nuxt-dev"
  }
}

Or keep a thin script:

// scripts/dev.ts
import { tauriNuxtDev } from 'tauri-nuxt-dev';

process.exitCode = await tauriNuxtDev({ nuxt: 'vpr' });

Related

Development

pnpm install
pnpm test
pnpm build
pnpm check

| Script | Description | | -------------------------- | ------------------------------------ | | pnpm build | tsdown build (+ publint) | | pnpm test | Vitest unit tests | | pnpm typecheck | TypeScript check | | pnpm lint / pnpm check | oxlint / format + lint gate | | pnpm release | Version bump + publish (genbumppush) |

Optional peer for TypeScript config files: jiti (see Configuration).

License

MIT © xcvzmoon