>_ Black Engine

Variables de entorno en Vite y React: .env y .env.local

Por Black Engine · 6 de noviembre de 2026

En Vite, las variables de entorno se definen en un archivo .env en la raíz del proyecto y solo las que empiezan con VITE_ llegan a tu código de React, donde se leen con import.meta.env.VITE_NOMBRE. El archivo .env.local funciona igual pero es para tus valores locales y git lo ignora. Si una variable sale undefined, casi siempre falta el prefijo, falta reiniciar el servidor o falta definirla en el hosting.

Si no sabes qué es un archivo .env, empieza por qué es el archivo .env.

Cómo usar .env en Vite

1. Crea el archivo en la raíz

Al lado de package.json, no dentro de src/:

# .env
VITE_SUPABASE_URL=https://abcdefgh.supabase.co
VITE_SUPABASE_ANON_KEY=eyJhbGciOi...
VITE_NOMBRE_APP="Mi Tienda"

2. Léela en tu código

// src/lib/supabase.ts
import { createClient } from "@supabase/supabase-js";

const url = import.meta.env.VITE_SUPABASE_URL;
const key = import.meta.env.VITE_SUPABASE_ANON_KEY;

if (!url || !key) {
  throw new Error("Faltan VITE_SUPABASE_URL o VITE_SUPABASE_ANON_KEY");
}

export const supabase = createClient(url, key);

El if te avisa claramente si falta una variable, en lugar de una pantalla en blanco.

3. Reinicia el servidor

Vite lee el .env al arrancar. Después de crear o cambiar una variable:

# Ctrl + C para detener, y luego:
npm run dev

Reglas clave (según la documentación de Vite)

La guía oficial de variables y modos de Vite establece:

  • Solo las variables con prefijo VITE_ se exponen al código. Una variable DB_PASSWORD no llega al navegador, lo cual es bueno.
  • Todas son texto (string). VITE_LIMITE=10 llega como "10"; conviértela con Number().
  • Se escriben dentro del JavaScript al hacer build. Por eso Vite advierte que no deben contener información sensible como llaves de API secretas.
  • Vite incluye variables propias: import.meta.env.MODE, import.meta.env.DEV y import.meta.env.PROD.

.env.local y los demás archivos

Vite carga estos archivos, en este orden de prioridad (el de abajo gana):

Archivo Cuándo se carga ¿Lo ignora git? (por convención)
.env Siempre Depende de tu .gitignore
.env.local Siempre Sí
.env.[modo] (ej. .env.production) Solo en ese modo Depende de tu .gitignore
.env.[modo].local Solo en ese modo Sí

Por defecto, npm run dev corre en modo development y npm run build en modo production. Así puedes tener:

# .env.development
VITE_API_URL=http://localhost:3000

# .env.production
VITE_API_URL=https://api.tunegocio.mx

Uso recomendado:

  • .env.example → nombres sin valores, sí se sube al repo.
  • .env.local → tus valores reales, no se sube.

.env en React según la herramienta

Herramienta Prefijo Cómo se lee
Vite (Lovable, Bolt, la mayoría hoy) VITE_ import.meta.env.VITE_X
Create React App REACT_APP_ process.env.REACT_APP_X
Next.js (navegador) NEXT_PUBLIC_ process.env.NEXT_PUBLIC_X
Next.js (solo servidor) Sin prefijo process.env.X

Si tu proyecto viene de un tutorial de Create React App y lo pasaste a Vite, cambia process.env.REACT_APP_ por import.meta.env.VITE_: process.env no existe en el navegador con Vite.

Variables de entorno al publicar (Vercel, Netlify)

El hosting no tiene tu .env. Hay que agregarlas en su panel:

  • Vercel: proyecto → Settings → Environment Variables.
  • Netlify: sitio → configuración del sitio → Environment variables.

Puntos clave:

  1. Mismo nombre exacto, con VITE_.
  2. Vuelve a hacer deploy después de agregarlas: como se escriben en el build, un deploy anterior no las tiene.
  3. Define para qué entorno aplica cada una (producción, vista previa).

Si el deploy falla, ve a npm run build exited with 1.

Autocompletado en TypeScript

Si tu proyecto usa TypeScript, el editor no sabe qué variables existen y no te avisa si escribes mal un nombre. La documentación de Vite recomienda declararlas en src/vite-env.d.ts:

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_SUPABASE_URL: string;
  readonly VITE_SUPABASE_ANON_KEY: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Así, un error como VITE_SUPABSE_URL aparece subrayado antes de que llegue a producción.

Leer variables en vite.config

El archivo vite.config.ts corre en Node, no en el navegador, y ahí import.meta.env todavía no tiene tus valores. Si necesitas una variable para configurar Vite (por ejemplo, el puerto o un proxy hacia tu API), usa loadEnv:

import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd());
  return {
    server: { proxy: { "/api": env.VITE_API_URL } },
  };
});

En apps hechas con Lovable o Bolt

Estas herramientas no siempre usan .env. En muchos proyectos de Lovable conectados a Supabase, la URL y la llave pública vienen escritas directamente en un archivo como src/integrations/supabase/client.ts. Eso no es un problema de seguridad por sí mismo (la llave anon es pública por diseño y la protección real depende de tus políticas RLS), pero sí significa que cambiar de proyecto de Supabase no es tan simple como editar un .env. Si exportas el proyecto para publicarlo en otro lado, busca dónde están esos valores antes de cambiarlos. Ver exportar un proyecto de Lovable.

Cómo comprobar qué quedó en el build

Si en producción algo apunta al lugar equivocado, revisa el resultado del build:

npm run build
grep -r "supabase.co" dist/assets/ | head

Verás qué URL quedó escrita dentro del JavaScript. Si ves un valor viejo, el hosting está usando otra variable o un build anterior.

Por qué sale undefined: checklist

  1. ¿El nombre empieza con VITE_?
  2. ¿El archivo está en la raíz (no en src/)?
  3. ¿Reiniciaste npm run dev?
  4. ¿El nombre en el código es idéntico (mayúsculas incluidas)?
  5. ¿Usas import.meta.env y no process.env?
  6. En producción: ¿la agregaste en el hosting y volviste a hacer deploy?

Lo que nunca debe ir con prefijo VITE_

  • service_role de Supabase.
  • Llave secreta de Stripe (sk_live_...).
  • API keys de OpenAI, Gemini o Anthropic.
  • Contraseñas de correo o SMTP.

Estas van en el servidor (una Edge Function de Supabase o una función de Vercel). Si ya están en tu frontend, considéralas expuestas: ver qué hacer si tu API key está expuesta y service role key expuesta.

Si tu app hecha con IA tiene llaves mezcladas entre frontend y servidor, o funciona en local pero no publicada, en Black Engine lo revisamos contigo por WhatsApp.

Preguntas frecuentes

¿Por qué mi variable de entorno sale undefined en Vite?

Lo más común: no tiene el prefijo VITE_, no reiniciaste el servidor de desarrollo después de crearla, o en el hosting no está definida al momento del build.

¿Cuál es la diferencia entre .env y .env.local?

Ambos se cargan siempre, pero .env.local está pensado para tus valores personales o secretos locales y git lo ignora; los valores de .env.local tienen prioridad.

¿Cómo se usan variables de entorno en Create React App?

En Create React App el prefijo es REACT_APP_ y se leen con process.env.REACT_APP_NOMBRE. En Vite el prefijo es VITE_ y se leen con import.meta.env.VITE_NOMBRE.

¿Las variables VITE_ son secretas?

No. Se copian dentro del JavaScript que descarga el navegador, así que cualquiera puede verlas. Nunca pongas llaves secretas con ese prefijo.

Pide ayuda por WhatsApp