pnpm, Turborepo, Nx — todo cubierto

Env vars en un monorepo, sin el .env expandiéndose.

Cada paquete quiere sus propios secrets. Cada dev quiere un solo comando. Un .envshed.json en la raíz, cada workspace trae las claves que necesita, y los overrides por usuario siguen siendo locales.

Un monorepo es el momento en el que dotenv deja de escalar. El paquete A necesita una clave de Stripe. El paquete B necesita un URL de Postgres. El paquete C necesita las dos. La siguiente persona del equipo copia tres archivos de Slack, se salta uno, y la app crashea al arrancar con un undefined críptico. Envshed se construyó para que la estructura del monorepo que ya tienes siga intacta — y los secrets dejen de ser el eslabón débil.

Dónde los secrets en monorepo se descarrilan

Tres paquetes, tres .env, una sola persona manteniéndolos sincronizados

Una ingeniera se vuelve la dependencia ambulante. Se va de vacaciones y el setup del dev nuevo rompe de una forma que nadie puede reproducir.

Un paquete nuevo entra el martes, sus claves se pierden para el viernes

Nadie recuerda qué env vars pertenecen al paquete que agregaste el sprint pasado. El .env.example se desvía un valor por vez.

Turbo cachea una task con una env var faltante

El caché trata la clave faltante como build válido. El bug sobrevive una semana porque el run de CI que debió fallar se sirvió del caché.

Un config que entiende la forma de tu workspace

Envshed trata a tu monorepo como una estructura de primera clase. Un solo archivo de config en la raíz declara el entorno de cada paquete. envshed pull recorre el config, trae solo las claves que cada workspace declaró y las escribe donde ese workspace las espera. pnpm workspaces, Turborepo, Nx, Lerna — si tu herramienta lee process.env, Envshed entrega los valores.

Declara una vez, trae por workspace

Un archivo de config. Cada paquete trae lo que necesita.

// .envshed.json en la raíz del repo
{
  "org": "acme",
  "project": "platform",
  "defaultEnv": "development",
  "workspaces": {
    "apps/api": ["DATABASE_URL", "REDIS_URL"],
    "apps/web": ["NEXT_PUBLIC_API_URL"],
    "packages/auth": ["JWT_SECRET"]
  }
}

Qué reemplaza esto

Pull con alcance por workspace

envshed pull --workspace apps/api solo escribe las claves que la app API declaró. Los paquetes de frontend nunca ven el Stripe secret.

Clave faltante detectada antes del arranque

Envshed falla en voz alta cuando un workspace declara una clave que no está en el vault. El undefined en runtime se vuelve un error en lint.

Amistoso con Turborepo

Los valores se escriben a archivos .env en disco. Las claves env y globalEnv de Turbo las leen igual. El hashing del caché no cambia.

Lo que obtienes

  • envshed init detecta workspaces y sugiere un config
  • Alcance de claves por workspace — sin filtrar STRIPE_SECRET_KEY al bundle del frontend
  • Overrides por usuario junto a los valores compartidos — tu DATABASE_URL local sigue siendo local
  • Funciona con pnpm workspaces, Turborepo, Nx y Lerna
  • Registro de auditoría a nivel de workspace — sabe quién trajo qué, dónde

Preguntas específicas de monorepo

¿Necesito una cuenta por paquete?

No. Una organización, un proyecto, un entorno. El config declara qué lee cada workspace. Los paquetes son solo agrupaciones de claves dentro del mismo vault.

¿Respeta el hashing de caché de Turborepo?

Sí. Los secrets se escriben a archivos .env en disco. Las claves env y globalEnv de Turbo los leen desde ahí. El comportamiento del caché es el mismo que tenías antes de Envshed.

¿Paquetes distintos pueden usar entornos distintos al mismo tiempo?

Sí. Corre envshed pull --workspace apps/api --env staging y envshed pull --workspace apps/web --env development en paralelo.

¿Y si mi monorepo tiene 80 paquetes?

El config sigue siendo declarativo y diffable. Puedes generarlo desde los package.json en la CI si quieres mantenerlo automatizado.

Deja de diffear archivos .env entre paquetes

Un comando en la raíz. Cada workspace trae exactamente lo que necesita.

Empezar gratis

Parte de Envshed.