portless: Stable .localhost HTTPS hostnames proxy for local development
Portless provides a local proxy that maps dev servers to stable .localhost HTTPS hostnames, streamlining local HTTPS and multi-package/multi-framework workflows; be mindful of local CA, privilege elevation, and license/compliance risks.
GitHub vercel-labs/portless Updated 2026-09-03 Branch main Stars 11.8K Forks 383
local development HTTPS proxy .localhost hostnames developer tool monorepo support

💡 Deep Analysis

5
What concrete pain points does portless solve for local development, and how effective is it?

Core Analysis

Project Positioning: portless replaces unstable numerical ports with stable, readable local hostnames (e.g. https://myapp.localhost), and centralizes port allocation, hostname mapping, and local TLS certificate management to remove manual hosts/mkcert work.

Technical Features

  • Hostname instead of ports: The proxy assigns stable <name>.<tld> hostnames and forwards traffic to backend ports (random or fixed, typically in the 4000-4999 range).
  • Port injection across frameworks: Uses PORT env or auto-injects --port/--host flags to drive most dev servers; provides special injection for frameworks that ignore PORT.
  • Default TLS with local CA: HTTPS (HTTP/2) is enabled by default; portless generates and trusts a local CA and binds to port 443 (auto-elevates if needed).

Usage Recommendations

  1. Get started: Install globally (npm install -g portless) and run portless myapp next dev to get https://myapp.localhost.
  2. Monorepos / worktrees: Place portless.json at repo root for central config; git worktree integration gives branch-prefixed hostnames for parallel work.
  3. Complex scripts: If a dev script is a compound or delegated command, explicitly set the port in the script so portless can route it reliably.

Caveats

  • The proxy binds system port 443 which may require elevation or conflict with existing services; check policies on managed machines and Windows behavior.
  • Runners that neither accept PORT nor have injectable flags require manual start command changes.
  • portless is not a public tunneling tool (e.g. ngrok) and does not expose services to the Internet.

Important Notice: Portless is effective at improving HTTPS parity and hostname stability for local development, but only when your environment permits binding 443 and trusting a local CA.

Summary: For multi-service, monorepo, or branch-parallel development workflows that need production-like HTTPS/subdomain behavior, portless offers clear productivity gains.

86.0%
How does portless's proxy architecture work, and why can it support many different development frameworks?

Core Analysis

Project Positioning: portless operates a local HTTPS proxy as a single control plane responsible for hostname mapping, port allocation, and certificate handling. This lets different dev servers be routed and secured consistently without changing their implementations.

Technical Features and Compatibility Strategy

  • Single proxy: The proxy binds port 443 by default, receives hostname traffic and forwards it to assigned backend ports. TLS and certificates are handled at the proxy.
  • Two-path port binding:
  • Environment variable path: Most servers respect the PORT environment variable; portless sets this env so servers listen on the proxy-assigned port.
  • CLI injection path: For runners that ignore PORT (e.g. Vite, Expo), portless auto-injects --port (and --host when needed) into recognized runner subcommands.
  • State and reuse: Runtime state is stored in ~/.portless; the proxy reuses recent config across restarts to avoid silent behavior changes.

Practical Recommendations

  1. Use standard dev commands: Keep dev scripts in forms portless recognizes (e.g. vite, next dev) so injection works automatically.
  2. Explicit ports for complex scripts: For compound commands, env prefixes, or delegated scripts, set PORT or --port explicitly in package.json to ensure correct routing.

Caveats

  • Injection depends on parsing command syntax; portless will avoid injection for compound commands, comments, or runner flag prefixes and will require manual config.
  • As a single proxy, its failure or permission issues (binding 443) affect all local routing.

Important Notice: Portless achieves broad compatibility by moving complexity to the proxy layer and using PORT env + CLI injection, but edge-case scripts still need manual handling.

Summary: The single-proxy + dual-path injection model is the key design enabling portless to support many frameworks; robust for common setups but requires explicit configuration in special cases.

85.0%
In monorepo and git worktree scenarios, how does portless ensure name isolation and usability?

Core Analysis

Project Positioning: For monorepos and parallel-branch workflows, portless offers centralized hostname policies and automatic branch-prefixed hostnames to ensure multi-package and multi-branch instances remain predictable and collision-free.

Technical Features

  • Repo-root config: Place portless.json at the repository root and use an apps map to assign explicit hostnames to packages (e.g. apps/web: { name: "myapp" }) for centralized management.
  • Auto-discovery and naming: Packages not explicitly configured are inferred from package.json and follow a <package>.<project>.localhost convention for hierarchical, readable hostnames.
  • git worktree awareness: When using worktrees, portless automatically prefixes hostnames with branch names, allowing parallel branch instances to coexist without manual port/hosts adjustments.

Usage Recommendations

  1. Centralize config: Keep portless.json at the repo root and use the apps map for key services to ensure team-wide consistency.
  2. Use worktree for parallel branches: Create worktrees for each branch that needs to run concurrently; portless will provide branch-prefixed hostnames. Alternatively, use --name to override when needed.
  3. Lock or align portless versions: Prefer a consistent portless install strategy across the team to avoid state-format or trust workflow drift.

Caveats

  • If contributors do not use git worktree and instead switch branches in-place, automatic branch isolation is unavailable; explicit --name or separate configs will be needed.
  • Default name inference relies on package.json and repo names; if you need custom subdomains, define them in portless.json.

Important Notice: To avoid naming conflicts, store portless.json at the repo root and standardize workflow (e.g. recommend git worktree) in your docs/CI.

Summary: Using repo-root config, package name inference, and worktree prefixes, portless delivers clear, manageable local hostname strategies for monorepos and parallel-branch development.

84.0%
What common developer experience issues arise when using portless, and how can they be avoided?

Core Analysis

Core Issue: Portless brings convenience but introduces friction in edge cases related to command injection, system permissions and certificate trust, and CI / team consistency.

Common Issues and Causes

  • Injection-unfriendly scripts: Compound commands (&&, |), delegated scripts, or env-prefixed commands prevent portless from injecting --port, breaking routing.
  • Permissions & platform differences: Binding port 443 may require sudo or conflict with existing services; on Windows or managed devices automatic elevation, /etc/hosts edits, and CA trust may be restricted.
  • CI / non-interactive environments: portless exits with a descriptive error in non-interactive mode (CI=1), causing early failures unless handled explicitly.
  • Version/state consistency: Per-project vs global installs can produce differing state formats and require re-running trust operations.

Practical Mitigations

  1. Explicit ports in scripts: For compound or delegated scripts, set PORT in package.json or run the actual startup command as a dedicated subscript so portless can route it.
  2. Certificates & permissions: On managed machines pre-install or pre-approve the CA, or use --no-tls where TLS is not required (note this changes test fidelity).
  3. CI strategy: Detect non-interactive runs (CI=1) and either skip portless or provide fixed ports and disable the proxy in CI pipelines.
  4. Versioning discipline: Prefer a consistent install approach (global or locked devDependency) and document trust steps in repo README.

Important Notice: Document portless usage and trust steps in the repository so contributors do not encounter unexpected permission/host/certificate prompts.

Summary: By codifying conventions (explicit ports, worktree usage, CI handling, and version policy) teams can avoid the majority of portless UX pitfalls.

83.0%
How can portless be used safely in CI, managed developer machines, or environments where /etc/hosts cannot be modified, and what are alternatives?

Core Analysis

Core Issue: Portless depends on system-level operations (binding port 443, writing /etc/hosts, trusting a local CA) that are commonly restricted in CI and managed machines. You must use explicit configurations or alternatives to ensure predictable pipelines.

Environment Strategies and Recommendations

  • CI (non-interactive):
  • portless exits with an error in non-interactive (CI=1) environments, so do not rely on its automatic proxy in CI. Instead, set fixed backend ports in CI (PORT=XXXX), pre-load test certificates if needed, or run in HTTP mode (--no-tls) to avoid interactive trust steps.
  • Managed developer machines:
  • Coordinate with security teams to pre-install and trust the local CA, or run development in a container/DevContainer where host mapping can be controlled. If CA trust is impossible, use --no-tls with the caveat that HTTPS-related behavior (cookies, same-site) will differ.
  • No /etc/hosts write permissions:
  • Prefer the .localhost TLD (usually no hosts edits required). If a custom TLD is required and you lack permission, you must either get elevated rights or avoid custom TLDs.

Alternatives Comparison

  • Fixed port + mkcert: Manual certificate lifecycle and hosts management; more work but feasible in locked-down environments.
  • Public tunnels (ngrok/localtunnel): Good for remote access but not a drop-in replacement for portless’s goal of local hostname stability and HTTPS parity.

Important Notice: Do not silently run portless in CI or managed environments—either disable it explicitly or provide a reproducible alternative in your pipeline.

Summary: For CI and restricted machines, use fixed ports and pre-provisioned certs or disable portless; if you must use it, coordinate CA trust and hosts permissions with your security team.

82.0%

✨ Highlights

  • Assigns readable https://myapp.localhost hostnames per project
  • Auto-injects ports and supports many frameworks (Next/Vite/Express etc.)
  • Generates and trusts a local CA on first run; may require elevation or manual trust
  • License and language/contributor metadata are unclear; repository visibility and compliance are uncertain

🔧 Engineering

  • Maps app traffic via a local proxy to stable hostnames and enables HTTPS/HTTP2 by default
  • Automatically injects ports or adds --port/--host flags into scripts to support different frameworks
  • Supports monorepos, discovering packages and generating <package>.<project>.localhost subdomains

⚠️ Risks

  • Local CA trust and binding to port 443 involve security and privilege risks; evaluate cautiously in enterprise settings
  • Project is pre-1.0; state directory/format may change between releases and cause breaking changes
  • Missing clear license and shows limited contributor/release records; perform compliance and maintenance assessment before adoption

👥 For who?

  • Frontend and full‑stack developers, especially teams needing local HTTPS or readable hostnames for debugging
  • Suitable for projects using Next.js, Express and for Turborepo/monorepo workflows