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

envelor

v0.1.0

Published

Smart deploy recommender for Node.js and TypeScript apps.

Readme

Envelor v0

Deploy inteligente. Custo mínimo deployavel.

Uma CLI que infere o perfil da sua app Node.js/TypeScript, compara targets de deploy, e coloca no ar no mais barato que realmente pode ser deployado no v0 — sem manifest, sem config, sem decisão manual.

Quickstart

npx envelor deploy ./meu-app

Comandos

| Comando | Descrição | |---------|-----------| | envelor deploy <path> | Infere, compara e deploya | | envelor deploy <path> --dry-run | Planeja sem deployar | | envelor deploy <path> --target hetzner | Força target específico | | envelor compare <path> | Mostra tabela comparativa de custo | | envelor show <path> | Mostra manifest, target selecionado e trilha de decisão | | envelor migrate <path> | Verifica se há target mais barato disponível | | envelor doctor <path> | Verifica prontidão do projeto para o fluxo de deploy |

compare aceita --telemetry para registrar um evento local. show e migrate registram telemetria apenas quando o manifest do projeto já está com opt-in ativo.

Por padrão, compare e deploy preferem o target mais barato com deploy real disponível. Targets apenas de dry-run continuam visíveis na tabela e no JSON, mas não viram seleção automática quando existe uma opção deployável suportada.

compare também aceita --mode deploy e --mode planning:

  • deploy: recomenda o target suportado mais barato com deploy real
  • planning: recomenda o target suportado mais barato, mesmo que seja dry-run-only em v0

migrate aceita os mesmos modos:

  • deploy: só recomenda trocas que preservam um caminho real de deploy
  • planning: aponta a menor alternativa suportada no manifest, mesmo que ela seja dry-run-only em v0

--json funciona em todos os comandos para saída estruturada e uso em automações.

Erros também seguem um contrato único:

  • saída humana: Error [CODE]: mensagem, seguida de Hint: quando houver ação recomendada
  • saída JSON: { "error": { "code", "message", "hint?", "details?" } }

Saídas de sucesso em --json também seguem um contrato enxuto por comando.

Flags do deploy

| Flag | Descrição | |------|-----------| | --dry-run | Planeja e grava manifest sem deployar de fato | | --target <name> | Força target: fly.io, hetzner, railway, render, vercel | | --yes | Aceita defaults, reutiliza valores locais de .env | | --telemetry | Opt-in para telemetria anônima no manifest | | --region <name> | Override de região (ex: mia, iad) | | --database-url <url> | DATABASE_URL explícita para o deploy | | --env KEY=VALUE | Variáveis de ambiente explícitas (pode repetir) | | --hetzner-host <ip> | Host/IP do VPS Hetzner | | --hetzner-user <user> | Usuário SSH (default: root) | | --hetzner-port <port> | Porta SSH (default: 22) | | --ssh-key-path <path> | Caminho da chave SSH privada |

Frameworks suportados

  • Next.js — detecção via package.json + file conventions (/app, /pages)
  • Fastify — detecção via package.json + route scan AST
  • Express — detecção via package.json + route scan AST
  • Hono — detecção via package.json + route scan AST

Bancos suportados

  • Postgres — via drivers (pg, postgres, Prisma, Drizzle, Knex) + connection strings
  • SQLite — via better-sqlite3, sql.js, Prisma/Drizzle com SQLite
  • Nenhum — apps stateless

Targets de deploy

| Target | Status | Custo base | |--------|--------|------------| | Fly.io | Deploy completo | ~$1.94–$6.39/mês | | Hetzner | Deploy completo (VPS + Docker) | ~€3.79–€6.49/mês | | Railway | Dry-run / comparação | ~$5–$15/mês | | Render | Dry-run / comparação | ~$7/mês | | Vercel | Dry-run / comparação | $0–$20/mês |

Doctor

Para um diagnóstico simples antes de tentar deploy:

npx envelor doctor ./meu-app

Para checar um target específico:

npx envelor doctor ./meu-app --target fly.io

O comando destaca:

  • blockers práticos como DATABASE_URL ausente
  • se o target suporta deploy real ou só dry-run em v0
  • binários locais exigidos para o target escolhido
  • próximos passos claros, sem precisar ler o código

Para automação:

npx envelor --json doctor ./meu-app --target railway

Contrato de erro

Exemplo humano:

Error [INVALID_ENV_ASSIGNMENT]: Invalid env assignment: JWT_SECRET.
Hint: Use --env KEY=VALUE and repeat the flag for multiple values.

Exemplo JSON:

{
  "error": {
    "code": "MANIFEST_NOT_FOUND",
    "message": "Manifest not found for this project.",
    "hint": "Run envelor deploy <path> --dry-run first to generate .envelor/manifest.json."
  }
}

Códigos atuais:

  • CLI_USAGE_ERROR
  • INVALID_ENV_ASSIGNMENT
  • MANIFEST_NOT_FOUND
  • CLI_RUNTIME_ERROR

Contrato de sucesso (--json)

Os payloads de sucesso foram reduzidos ao necessário para automação e integração shell.

Princípios:

  • cada comando retorna um resumo útil, não a estrutura interna inteira
  • custos preservam moeda original e custo normalizado em USD quando relevante
  • selectedTarget diferencia recomendação deployável de opções apenas comparáveis em dry-run
  • a forma textual pode evoluir sem quebrar consumidores de JSON

Exemplo de compare:

{
  "command": "compare",
  "selectionMode": "deploy",
  "selectionReason": "fly.io was selected because deploy mode prefers the cheapest supported target with real deploy capability; vercel is cheaper overall but only supports dry-run in v0.",
  "app": {
    "name": "my-app",
    "framework": "express",
    "database": "postgres",
    "workload": "micro-api",
    "routeCount": 4
  },
  "selectedTarget": {
    "name": "fly.io",
    "currency": "USD",
    "costEstimate": 3.19,
    "normalizedCostUsd": 3.19,
    "supportsRealDeploy": true,
    "supportsDryRun": true
  },
  "cheapestOverallTarget": {
    "name": "vercel",
    "currency": "USD",
    "costEstimate": 0,
    "normalizedCostUsd": 0,
    "supportsRealDeploy": false,
    "supportsDryRun": true
  },
  "targets": []
}

Exemplo de doctor:

{
  "command": "doctor",
  "app": {
    "name": "my-app",
    "framework": "express",
    "database": "postgres",
    "workload": "micro-api",
    "routeCount": 4,
    "ambiguous": false,
    "llmResolved": false
  },
  "target": {
    "requested": "railway",
    "selected": "railway",
    "supportsRealDeploy": false,
    "supportsDryRun": true
  },
  "summary": {
    "pass": 0,
    "warn": 2,
    "fail": 0,
    "info": 1
  },
  "checks": [],
  "nextSteps": []
}

Exemplo de migrate:

{
  "command": "migrate",
  "mode": "planning",
  "app": {
    "name": "my-app",
    "framework": "express",
    "database": "none",
    "workload": "micro-api",
    "routeCount": 1
  },
  "currentTarget": "fly.io",
  "recommendation": {
    "mode": "planning",
    "currentTarget": "fly.io",
    "currentCost": 2.03,
    "currentCurrency": "USD",
    "currentSupportsRealDeploy": true,
    "recommendedTarget": "vercel",
    "recommendedCost": 0,
    "recommendedCurrency": "USD",
    "recommendedSupportsRealDeploy": false,
    "savingsPercent": 100,
    "monthlySavingsUsd": 2.03,
    "reason": "Switching from fly.io to vercel saves about USD 2.03/month (~100%) in planning mode, which also considers dry-run-only providers."
  }
}

Exemplo de show:

{
  "command": "show",
  "projectPath": "./my-app",
  "app": {
    "name": "my-app",
    "framework": "express",
    "database": "none",
    "workload": "micro-api",
    "routeCount": 1
  },
  "selectionMode": "deploy",
  "selectionReason": "fly.io was selected because deploy mode prefers the cheapest supported target with real deploy capability; vercel is cheaper overall but only supports dry-run in v0.",
  "selectedTarget": {
    "name": "fly.io",
    "currency": "USD",
    "costEstimate": 2.03,
    "normalizedCostUsd": 2.03,
    "supportsRealDeploy": true,
    "supportsDryRun": true
  }
}

Roadmap e distribuição

O plano de distribuição do produto e o roadmap operacional estão em ROADMAP.md.

Resolução de ambiguidade via LLM

Quando a inferência não encontra rotas suficientes para classificar a app com segurança, o Envelor usa uma chamada LLM para resolver a ambiguidade e alimentar a classificação final.

Configure uma das variáveis:

  • ANTHROPIC_API_KEY ou ENVELOR_ANTHROPIC_KEY — usa Claude Haiku
  • OPENAI_API_KEY ou ENVELOR_OPENAI_KEY — usa GPT-4o-mini

Ordem de tentativa: Anthropic, depois OpenAI, e por fim fallback local para api-standard. Timeout por provedor: 5 segundos.

Política de custo e câmbio

  • Pricing continua estático em v0, sem chamadas a APIs de providers.
  • Rankings e recomendações cross-currency usam custo mensal normalizado para USD.
  • A taxa embutida atual é 1 EUR = 1.09 USD.
  • Para benchmarking interno, é possível sobrescrever a taxa com ENVELOR_FX_EUR_USD.

Desenvolvimento

npm install          # Instalar dependências
npm test             # Rodar testes (vitest)

## Validação real

Validação manual executada em repositórios públicos reais durante o fechamento do v0:

- `heroku/node-js-getting-started` (Express)
- `honojs/examples/basic` (Hono)
- `vercel/next-learn/dashboard/final-example` (Next.js + Postgres)

Fluxos verificados:

- `compare --json` passou a selecionar `fly.io` como default quando ele é o target deployável mais barato, mesmo que existam opções dry-run-only mais baratas
- `compare --json --mode planning` continua expondo a visão de menor custo absoluto quando o objetivo é benchmarking ou planejamento
- `doctor --json --target fly.io` continuou reportando blockers reais como `DATABASE_URL` ausente e falta de `flyctl`
- `deploy --dry-run --target fly.io` continuou gerando manifest e plano válidos nos três projetos
npm run test:watch   # Testes em watch mode
npm run typecheck    # Verificação de tipos
npm run check        # Typecheck + testes
npm run build        # Compilar TypeScript → dist/
npm run dev          # Rodar CLI em modo dev (tsx)

Arquitetura

Código → infer → classify → envelope → compare → deploy → report
                                 ↓
                          manifest interno
                       (.envelor/manifest.json)

Estrutura de arquivos

src/
  cli.ts            ← Ponto de entrada, comandos
  infer.ts          ← Análise de código (AST + LLM)
  classify.ts       ← Classificação de workload
  envelope.ts       ← Cálculo de envelope operacional
  compare.ts        ← Comparação cross-provider
  deploy.ts         ← Orquestração de deploy
  report.ts         ← Formatação CLI
  manifest.ts       ← Persistência de manifest
  llm.ts            ← Resolução de ambiguidade via LLM
  telemetry.ts      ← Eventos locais de deploy/compare/show/migrate
  migrate.ts        ← Recomendação de migração
  portable.ts       ← Avaliação de portabilidade VPS
  currency.ts       ← Normalização cambial para ranking e recomendações
  doctor.ts         ← Diagnóstico rápido de prontidão
  types.ts          ← Tipos TypeScript
adapters/
  fly.ts            ← Adapter Fly.io
  hetzner.ts        ← Adapter Hetzner VPS
  railway.ts        ← Adapter Railway (dry-run v0)
  render.ts         ← Adapter Render (dry-run v0)
  vercel.ts         ← Adapter Vercel (dry-run v0)
  types.ts          ← Interface DeployAdapter
data/
  pricing.ts        ← Tabelas de preço
  workloads.ts      ← Defaults de envelope por classe
  frameworks.ts     ← Registry de frameworks (extensível)
  providers.ts      ← Capacidades e custos por provider
tests/
  *.test.ts         ← 75 testes (17 arquivos)

Licença

MIT v0

Envelor is a CLI that infers the shape of a Node.js or TypeScript app, compares deployment targets, and deploys to the cheapest supported option.

What v0 does

  • Detects Express, Fastify, Hono, and Next.js apps
  • Detects Postgres, SQLite, or stateless workloads
  • Estimates a runtime envelope from the codebase
  • Compares Fly.io, Railway, Hetzner, Render, and Vercel
  • Deploys through real adapters for Fly.io and Hetzner
  • Persists an internal manifest to .envelor/manifest.json

Install

npm install
npm run build

Commands

Compare targets

node dist/src/cli.js compare ./examples/my-app

Dry-run deploy

node dist/src/cli.js deploy ./examples/my-app --dry-run

Fly deploy with guided config

node dist/src/cli.js deploy ./examples/my-app --target fly.io

Useful flags:

node dist/src/cli.js deploy ./examples/my-app \
  --target fly.io \
  --yes \
  --telemetry \
  --database-url postgresql://user:pass@host:5432/app \
  --env JWT_SECRET=super-secret \
  --env REDIS_URL=redis://cache.internal:6379

Behavior:

  • If .env or .env.local exists and --yes is passed, Envelor reuses those values.
  • If Postgres is detected, Envelor requires DATABASE_URL for a real deploy.
  • Fly secrets are sent with flyctl secrets set before flyctl deploy.

Hetzner deploy

node dist/src/cli.js deploy ./examples/my-app \
  --target hetzner \
  --hetzner-host 203.0.113.10 \
  --hetzner-user root \
  --ssh-key-path ~/.ssh/id_ed25519 \
  --yes

Behavior:

  • Assumes Docker is installed on the target VPS.
  • Generates a basic Dockerfile if the project does not provide one.
  • Uploads the project over SSH and SCP.
  • Starts a single container on port 80.

Manifest

Every deploy writes .envelor/manifest.json containing:

  • inferred framework and database
  • route summary
  • workload class
  • computed envelope
  • cross-provider comparison table
  • selected target
  • deployment metadata

Show the manifest:

node dist/src/cli.js show ./examples/my-app

Test

npm test

Current limits

  • Heuristic inference, not full semantic analysis
  • LLM ambiguity resolution is best-effort and intentionally bounded by short timeouts
  • Only Fly.io and Hetzner have deploy adapters in v0
  • Multi-service topologies, websockets, workers, and long-running jobs remain out of scope