Saltar al contenido principal

Configuración del entorno

Closegram tiene tres lugares separados que necesitan configuración de entorno, cada uno con su propio archivo:

AppArchivoPlantilla
apps/backend.env (también .env.dev para Docker, .env.test para el stack de pruebas).env.example
apps/frontend-nextjs.env.local.env.local.example
apps/iosNo es un archivo .env real — las variables se configuran directamente en el scheme de Xcode (ver iOS más abajo)apps/ios/app/.env.example (solo de referencia)

Esta página es una referencia completa de cada variable en las tres. Para instrucciones paso a paso sobre cómo obtener los valores reales de claves/secretos (Firebase, Google, Apple, Stripe, AWS, Twilio, etc.), consulta Obtención de claves API. Para cómo difieren estas variables entre local/development/production y qué valores van en el dashboard de Railway por entorno, consulta Entornos de despliegue.

Inicio rápido

# Backend
cd apps/backend
cp .env.example .env
# completa los valores — consulta las tablas de abajo y la guía de claves API

# Frontend
cd apps/frontend-nextjs
cp .env.local.example .env.local

Genera un secreto aleatorio seguro para cualquier valor *_SECRET con:

node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"

Infraestructura local vía Docker (recomendado)

No necesitas cuentas reales de base de datos, Redis o LiveKit para desarrollar localmente — apps/backend/docker-compose.yml levanta los tres con credenciales de desarrollo integradas:

cd apps/backend
npm run docker:up # postgres + redis + redis-livekit + livekit, usando .env.dev
npm run migrate # ejecuta las migraciones contra el Postgres dockerizado
npm run seed # opcional — datos de siembra
ServicioContenedorPuerto por defectoCredenciales por defecto
PostgreSQLclosegram-postgres5432usuario postgres / contraseña closegram_postgres_pass / bd closegram_dev
Redisclosegram-redis6382 (host) → 6379 (contenedor)contraseña closegram_redis_pass
Redis (instancia dedicada de LiveKit)closegram-redis-livekit6381contraseña livekit_redis_pass
Servidor LiveKitclosegram-livekit7880 (HTTP), 7881 (TCP), 7882 (UDP)clave API devkey / secreto dev1234567890abcdef1234567890abcdef (fijo en docker-compose.yml, solo desarrollo)
Redis Commander (GUI, opcional)closegram-redis-commandervía --profile guiadmin / admin

Como la clave de desarrollo de LiveKit está integrada en el archivo compose, puedes dejar LIVEKIT_URL, LIVEKIT_API_KEY y LIVEKIT_API_SECRET en tu .env apuntando a ws://localhost:7880 / devkey / dev1234567890abcdef1234567890abcdef para el desarrollo local — no se necesita cuenta de LiveKit Cloud hasta que despliegues. Otros scripts útiles: npm run docker:down, npm run docker:reset (borra los volúmenes), npm run docker:up:test (Postgres/Redis de prueba separado en puertos distintos), npm run redis:cli / redis:cli:livekit.

Qué es realmente necesario

No todas las variables de abajo necesitan un valor real para ejecutar la app localmente. En resumen:

  • Necesario para arrancar del todo: Base de datos (DB_*), secretos JWT (JWT_*). Sin ellos el backend no arranca o la autenticación no funciona.
  • Necesario para funcionalidades específicas, de lo contrario esa funcionalidad se degrada silenciosamente: Firebase (verificación de inicio de sesión con Google + push), inicio de sesión con Apple (APPLE_*), Stripe (pagos — DISABLE_STRIPE=true para omitirlo), AWS S3 (subida de archivos — DISABLE_S3=true usa respuestas simuladas), SMS/Twilio (OTP por teléfono — DISABLE_SMS=true para omitirlo), LiveKit (llamadas/en vivo — ver la sección de Docker más arriba, DISABLE_LIVEKIT=true para omitirlo).
  • Opcional / solo observabilidad: Redis se puede omitir con DISABLE_REDIS=true (aunque varias funcionalidades en tiempo real dependen de él — ver Infraestructura), Sentry/Datadog/New Relic/LogRocket/logger personalizado, analítica de BigQuery (recae en Postgres vía ANALYTICS_DB_TYPE=postgres), PayPal, MessageBird.
  • Vestigial — definido en .env.example pero no leído por ningún código del backend (confirmado buscando en el código fuente, seguro dejarlo en blanco o eliminarlo): DEEPAI_API_KEY, AWS_PINPOINT_PROJECT_ID, GMAIL_USER_NAME / GMAIL_USER_PASSWORD / GMAIL_SERVICE_HOST / GMAIL_SERVICE_PORT (no existe una ruta de envío por Gmail/nodemailer — EMAIL_PROVIDER solo tiene una implementación aws-ses a pesar de ser nominalmente conectable).

Backend — apps/backend/.env

Aplicación

VariableEjemploPropósito
NODE_ENVdevelopmentSelecciona qué archivo .env.<NODE_ENV> se carga
APP_NAMEClosegramNombre visible usado en correos/logs
APP_VERSION / BACKEND_VERSION1.0.0Etiquetas de versión para logging/release de Sentry
BACKEND_PORT / PORT8000Puerto del servidor
API_URLhttp://localhost:8000URL pública propia del backend
FRONTEND_URLhttp://localhost:3000Se usa para construir enlaces en correos, CORS
TIMEZONEAmerica/Los_AngelesZona horaria por defecto del servidor
WEBAUTHN_RP_IDlocalhostPasskeys. Solo el dominio registrable — sin esquema/puerto/ruta (p. ej. closegram.com). Debe configurarse en producción, de lo contrario el registro de passkey falla con The RP ID "localhost" is invalid for this domain
WEBAUTHN_ORIGINFRONTEND_URLPasskeys. Origen(es) completo(s) permitidos para ejecutar la ceremonia, incl. https, sin barra final. Separa con comas para múltiples (p. ej. https://closegram.com,https://www.closegram.com)
WEBAUTHN_RP_NAMEAPP_NAMEPasskeys. Nombre mostrado en el prompt de passkey del sistema operativo

Base de datos

VariablePropósito
DB_HOST / DB_PORT / DB_NAME / DB_USER / DB_PASSWORD / DB_DIALECTPiezas estándar de conexión Sequelize/Postgres
DEV_DATABASE_URL / DATABASE_URLAlternativa de cadena de conexión completa (usada por algunas herramientas)

Redis

VariablePropósito
REDIS_HOST / REDIS_PORT / REDIS_PASSWORDConexión — potencia presencia, caché de chat, caché de OTP, BullMQ, suscripciones pub/sub
DISABLE_REDISConfigura true para ejecutar sin Redis (degrada las funcionalidades anteriores)
REDIS_COMMANDER_USER / REDIS_COMMANDER_PASSWORDInicio de sesión para la GUI opcional de Redis Commander

Traducción de chat (opcional)

Potencia el modo de traducción dentro del chat (message-translation.service.js). Independiente del proveedor: el primer proveedor configurado gana, en este orden — LibreTranslate → DeepL → Google Translate → OpenAI. Si ninguno está configurado, la funcionalidad se desactiva silenciosamente (el botón de traducir se oculta y el chat muestra el texto original), así que estas son totalmente opcionales. Las traducciones se almacenan en caché en Postgres (message_translation) por mensaje + idioma, así que cada proveedor se llama como máximo una vez por mensaje por idioma.

VariablePropósito
LIBRETRANSLATE_URLURL base de una instancia de LibreTranslate (p. ej. https://libretranslate.com o la tuya autoalojada). Opción más económica/autoalojable; habilita el proveedor cuando está configurada
LIBRETRANSLATE_API_KEYClave API opcional si tu instancia de LibreTranslate la requiere
DEEPL_API_KEYClave API de DeepL (plan gratuito: 500 mil caracteres/mes). Se usa si LibreTranslate no está configurado
DEEPL_API_URLURL base opcional de DeepL — por defecto https://api-free.deepl.com; usa https://api.deepl.com para el plan de pago
GOOGLE_TRANSLATE_API_KEYClave API de Google Cloud Translation v2. Se usa si las anteriores no están configuradas
OPENAI_API_KEYClave de OpenAI — respaldo de traducción basado en LLM si no hay un traductor dedicado configurado
OPENAI_TRANSLATE_MODELModelo para la traducción con OpenAI (por defecto gpt-4o-mini)
TRANSLATION_MONTHLY_CHAR_LIMITLímite estricto opcional de caracteres traducidos por mes calendario (rastreado en Redis). 0/sin configurar = sin límite. Al alcanzarlo, la traducción se detiene hasta el siguiente mes — una válvula de seguridad de gasto
TRANSLATION_MAX_CHARSLímite de caracteres por mensaje enviado a la API (por defecto 5000)
TRANSLATION_HTTP_TIMEOUT_MSTiempo de espera para una llamada HTTP al proveedor (por defecto 8000)

JWT

VariablePropósito
JWT_SECRETFirma los tokens de acceso de usuarios regulares
JWT_REFRESH_SECRETFirma los tokens de refresco
JWT_ADMIN_SECRETFirma los tokens de sesión del panel de administración
JWT_TOKEN_EXPIRYp. ej. 8h
JWT_TEMP_TOKEN_EXPIRYp. ej. 10m — tokens de corta duración (desafío 2FA, etc.)

Passkeys (WebAuthn)

Compartidas tanto por las passkeys de la app principal (services/passkey.service.js) como por las passkeys de administrador (services/admin-passkey.service.js) — no hay una variable separada solo para admin. Ambas usan por defecto localhost/FRONTEND_URL para desarrollo local, pero deben configurarse explícitamente en producción o el registro falla con The RP ID "localhost" is invalid for this domain (o, si solo WEBAUTHN_ORIGIN está mal configurado, con Unexpected registration response origin).

VariableEjemploPropósito
WEBAUTHN_RP_IDclosegram.comEl dominio registrable solamente — sin esquema, sin puerto, sin ruta. Debe ser el dominio del origen o un padre registrable de este (p. ej. closegram.com también es válido para admin.closegram.com — no se necesita un valor separado para el panel de administración). Por defecto es localhost.
WEBAUTHN_ORIGINhttps://closegram.com,https://admin.closegram.comEl/los origen(es) completo(s) autorizados para realizar la ceremonia, incluyendo el esquema. Separados por comas para varios — debe incluir tanto el origen de la app cliente como el del panel de administración (son subdominios distintos), o el registro de passkeys de administrador falla. Sin barra final. Por defecto es FRONTEND_URL.
WEBAUTHN_RP_NAMEClosegramNombre para mostrar en el diálogo de passkey del sistema operativo. Por defecto es APP_NAME.

Consulta el bloque WEBAUTHN_* en apps/backend/.env.example para un ejemplo real de producción, y Cuentas de administrador para el detalle específico del origen en admin.

AWS — S3, SES, SNS

VariablePropósito
AWS_REGIONp. ej. us-east-1
AWS_ACCESS_KEY / AWS_ACCESS_KEY_ID, AWS_SECRET_KEY / AWS_SECRET_ACCESS_KEYCredenciales de IAM (ambas variantes de nombre se leen en distintos lugares)
AWS_BUCKET_NAME / AWS_S3_URLBucket S3 para subidas
AWS_API_VERSION / AWS_PROFILE / AWS_TOKEN_KEYConfiguración diversa del SDK de AWS
STORAGE_PROVIDERActualmente solo aws-s3 está implementado
DISABLE_S3true usa respuestas simuladas de subida localmente
AWS_EMAIL / AWS_EMAIL_NAMEDirección/nombre "from" de SES
AWS_S3_EMAIL_TEMPLATES_PATHRuta en S3 para las plantillas de correo Pug
AWS_CONFIGURATION_NAMEConjunto de configuración de SES (seguimiento de rebotes/quejas)
AWS_SNS_SENDER_IDID de remitente SMS de SNS
AWS_PINPOINT_PROJECT_IDNo se referencia en ningún lugar del backend — vestigial

Correo

VariablePropósito
EMAIL_PROVIDERSolo aws-ses tiene una implementación a pesar de ser nominalmente conectable
DISABLE_EMAILOmite el envío de correos localmente
VERIFIED_EMAIL_TIME_WAIT / VERIFIED_EMAIL_LIMIT_TIMES / VERIFIED_EMAIL_TIME_TRANSFORMLimitación de frecuencia del código de verificación de correo
GMAIL_USER_NAME / GMAIL_USER_PASSWORD / GMAIL_SERVICE_HOST / GMAIL_SERVICE_PORTVestigial — no existe una ruta de envío por Gmail/nodemailer

SMS / OTP por teléfono

VariablePropósito
SMS_PROVIDERtwilio (por defecto), aws-sns o messagebird
SMS_ORIGINATOR_PHONEEtiqueta del remitente
DISABLE_SMSOmite el envío de SMS localmente
VERIFIED_SMS_TIME_WAIT / VERIFIED_SMS_LIMIT_TIMES / VERIFIED_SMS_TIME_TRANSFORMLimitación de frecuencia del OTP
TWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN / TWILIO_PHONE_NUMBER / TWILIO_VERIFY_SERVICE_SIDCredenciales de Twilio
MESSAGEBIRD_API_KEY / MESSAGEBIRD_ORIGINATORCredenciales de MessageBird (proveedor alternativo)
PHONE_LOGIN_PROVIDERInterruptor de cómo funciona "iniciar sesión / agregar cuenta con número de teléfono": firebase (por defecto — el cliente web usa Firebase Phone Auth, este servidor no envía SMS), twilio (mutations heredadas requestPhoneOtp/loginWithPhone, este servidor envía el OTP él mismo), o disabled (login por teléfono desactivado por completo, incluso vía Firebase). Reflejado en el frontend por NEXT_PUBLIC_PHONE_LOGIN_PROVIDER.

Stripe / PayPal

VariablePropósito
STRIPE_API_KEY_PROD_SECRETClave secreta de Stripe
STRIPE_WEBHOOK_SECRETVerifica las firmas de los webhooks entrantes de Stripe
PAYMENT_PROVIDERActualmente stripe
DISABLE_STRIPEOmite el procesamiento de pagos localmente
PAYPAL_CLIENT_ID / PAYPAL_CLIENT_SECRETCredenciales de la app de PayPal
PAYPAL_API_BASEPor defecto usa la URL de sandbox si no se configura

Compras dentro de la app (Apple / Google IAP)

Las monedas compradas dentro de las apps nativas iOS/Android se validan del lado del servidor contra cada tienda y luego se acreditan (ver Monedas). Es aparte del flujo web de Stripe/PayPal de arriba. Cómo obtener cada credencial: guía de API keys → Compras en app.

VariablePropósito
APPLE_IAP_ISSUER_IDIssuer ID de la API key de App Store Connect (para el App Store Server API)
APPLE_IAP_KEY_IDEl Key ID (kid) de la API key de App Store Connect
APPLE_IAP_PRIVATE_KEYContenido del .p8 (en línea; \n-escapado está bien)
APPLE_IAP_BUNDLE_IDBundle id de la app iOS (p. ej. com.closegram.app)
APPLE_IAP_ENVIRONMENTproduction o sandbox — opcional; el servicio prueba producción y cae a sandbox
GOOGLE_IAP_PACKAGE_NAMEapplicationId de Android (p. ej. com.closegram.app)
GOOGLE_IAP_SERVICE_ACCOUNT_KEYJSON de service account (como string) con acceso a Android Publisher

Webhooks de reembolso de tiendas — descuentan monedas cuando una tienda reembolsa/revoca una compra. Endpoints: POST /api/webhooks/apple/iap (App Store Server Notifications V2) y POST /api/webhooks/google/rtdn (Google RTDN vía Pub/Sub push). APPLE_IAP_ROOT_CERT es requerido para el webhook de reembolso de Apple — falla en cerrado y rechaza las notificaciones sin un root anclado. Las vars de Google son opcionales (su chequeo de token se salta si no se configuran):

VariablePropósito
APPLE_IAP_ROOT_CERTRequerido para el webhook de reembolso de Apple — PEM del Apple Root CA — G3. Sin él, el webhook rechaza toda notificación (fail-closed).
GOOGLE_RTDN_AUDIENCE(opcional) Audiencia esperada del token OIDC del push de Pub/Sub — normalmente la URL de tu webhook
GOOGLE_RTDN_SA_EMAIL(opcional) Email de la service account del push de Pub/Sub autorizada a llamar al webhook

Firebase (notificaciones push + verificación de auth de Google/teléfono)

VariablePropósito
FIREBASE_PROJECT_IDID del proyecto de Firebase
FIREBASE_PRIVATE_KEY_ID / FIREBASE_PRIVATE_KEY / FIREBASE_CLIENT_EMAIL / FIREBASE_CLIENT_IDCredenciales de cuenta de servicio (de la clave JSON descargada)
FIREBASE_AUTH_URI / FIREBASE_TOKEN_URI / FIREBASE_AUTH_PROVIDER_CERT_URL / FIREBASE_CLIENT_CERT_URL / FIREBASE_UNIVERSE_DOMAINCampos estándar del JSON de cuenta de servicio — copia tal cual
FIREBASE_DATABASE_URL / FIREBASE_STORAGE_BUCKETURLs del proyecto
FIREBASE_SERVICE_ACCOUNT_PATHAlternativa a las credenciales FIREBASE_* en línea — ruta a un archivo JSON de cuenta de servicio
DISABLE_PUSH_NOTIFICATIONSOmite el envío de push localmente

Inicio de sesión con Apple

VariablePropósito
APPLE_CLIENT_IDEl Bundle ID de la app iOS nativa (p. ej. com.yourapp.bundle) — el claim aud de los ID tokens que emite Sign in with Apple dentro de la app iOS. No es el Services ID de abajo, pese al nombre.
APPLE_WEB_CLIENT_IDEl Services ID separado para Sign in with Apple en la web (registrado en Apple Developer, ligado a un dominio verificado + Return URLs) — no es lo mismo que APPLE_CLIENT_ID/Bundle ID de arriba. Debe coincidir con NEXT_PUBLIC_APPLE_CLIENT_ID en frontend-nextjs. Déjalo sin configurar si no tienes montado el Sign in with Apple web.
APPLE_TEAM_IDTeam ID de Apple Developer
APPLE_KEY_IDID de la clave privada de Sign in with Apple
APPLE_REDIRECT_URIURL de redirección de OAuth (flujo web)
APPLE_PRIVATE_KEYEl contenido de la clave privada .p8 (en línea)
APPLE_PRIVATE_KEY_PATHAlternativa a APPLE_PRIVATE_KEY — ruta (relativa a apps/backend) al archivo .p8 (apple-auth.service.js)
APPLE_KEY_P8Nombre del archivo de la clave .p8 dentro de apps/backend/utils/ (estrategia OAuth heredada passport-apple)

Apple Push Notifications (APNs) — llamadas/VoIP en iOS

VariablePropósito
APNS_PRIVATE_KEY / APNS_KEY_ID / APNS_TEAM_IDClave de autenticación APNs (clave separada de Sign in with Apple)
APNS_BUNDLE_IDBundle ID de la app de iOS
APNS_PRODUCTIONfalse para APNs de sandbox, true para producción

Google Cloud / BigQuery (analítica)

VariablePropósito
GOOGLE_CLOUD_PROJECT_ID / GCP_PROJECT_IDProyecto de GCP
BIGQUERY_DATASET_ID / BIGQUERY_LOCATIONConfiguración del dataset
BIGQUERY_PRIVATE_KEY_ID / BIGQUERY_PRIVATE_KEY / BIGQUERY_CLIENT_EMAIL / BIGQUERY_CLIENT_IDCredenciales de cuenta de servicio
ANALYTICS_DB_TYPEpostgres (por defecto, no necesita GCP) o bigquery
ANALYTICS_DB_HOST / PORT / NAME / USER / PASSWORDSolo se usan cuando ANALYTICS_DB_TYPE=postgres y quieres una base de datos de analítica separada
ANALYTICS_ENABLEDInterruptor maestro de encendido/apagado

OAuth social

Hay dos mecanismos independientes de OAuth de Google en el código — ambos deben completarse si quieres que el inicio de sesión con Google funcione completamente fuera de la ruta de verificación de Firebase:

VariablePropósito
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRETEstrategia passport-google-token de Passport
CLIENT_ID / CLIENT_ID_SECRET / REDIRECT_URIsUn OAuth2Client de googleapis separado usado en otra parte del servicio de auth

Nota: el inicio de sesión con Facebook se eliminó por completo (tanto de la documentación orientada al producto de Autenticación como de la estrategia passport-facebook-token del backend) — ya no se ofrece como opción de login. FACEBOOK_APP_ID/FACEBOOK_APP_SECRET todavía existen, pero solo para crossposting (ver abajo).

Crossposting social (opcional) — para publicar contenido cruzado en X / TikTok / Facebook (services/crosspost.service.js):

VariablePropósito
X_CLIENT_ID / X_CLIENT_SECRETCredenciales de la app OAuth de X (Twitter)
TIKTOK_CLIENT_KEY / TIKTOK_CLIENT_SECRETCredenciales de la app OAuth de TikTok
FACEBOOK_APP_ID / FACEBOOK_APP_SECRETCredenciales de la app OAuth de Facebook Graph API (solo crossposting, no login)
TOKEN_ENCRYPTION_KEYCifra los tokens OAuth de terceros almacenados en reposo (utils/crypto.util.js). Si no está configurada, el almacenamiento de tokens es una operación sin efecto en texto plano — configúrala en producción cuando el crossposting esté habilitado. Generar: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Google Ad Manager (opcional) — reporte de ganancias por publicidad de creadores (services/gam-report.service.js):

VariablePropósito
GAM_NETWORK_CODETu código de red de Ad Manager
GAM_SERVICE_ACCOUNT_KEYRuta a (o JSON crudo de) la clave de cuenta de servicio
GAM_CREATOR_KEYNombre de la clave de segmentación personalizada que identifica al creador (por defecto creator)

Análisis de imágenes (NSFW / moderación de contenido)

VariablePropósito
IMAGE_ANALYSIS_PROVIDERgoogle-vision (el único proveedor implementado)
IMAGE_ANALYSIS_MIN_LABEL_CONFIDENCEUmbral de confianza 0–1
IMAGE_ANALYSIS_MAX_LABELS_PER_POSTLímite de etiquetas procesadas por subida
DISABLE_IMAGE_ANALYSISOmite el análisis localmente
DEEPAI_API_KEYVestigial — no se referencia en ningún lugar; el proveedor activo es Google Vision, que se autentica mediante las mismas credenciales de cuenta de servicio de Google Cloud de arriba

LiveKit (llamadas + transmisiones en vivo)

VariablePropósito
LIVEKIT_URL / LIVEKIT_WS_URLURL de WebSocket del servidor LiveKit
LIVEKIT_API_KEY / LIVEKIT_API_SECRETCredenciales del servidor
LIVEKIT_PORT / LIVEKIT_RTC_TCP / LIVEKIT_RTC_UDPSolo relevante si estás ejecutando el servidor LiveKit autoalojado con Docker
DISABLE_LIVEKITOmite llamadas/en vivo localmente

Localmente estas pueden apuntar al servidor LiveKit provisto por Docker (ver la sección de Docker más arriba) — no se necesita cuenta externa hasta producción.

Logging / observabilidad (todo opcional)

VariablePropósito
DATADOG_API_KEYHabilita el transporte de logs de Datadog
SENTRY_DSN / SENTRY_ENVIRONMENT / SENTRY_RELEASESeguimiento de errores
NEW_RELIC_LICENSE_KEY / NEW_RELIC_APP_NAME / NEW_RELIC_ENABLEDAPM — index.js hace require('newrelic') condicionalmente solo si la clave de licencia está configurada
NEW_RELIC_LOG_LEVELVerbosidad propia del log del agente de New Relic: error/warn/info/debug/trace (por defecto info)
LOGROCKET_APP_IDReproducción de sesiones
CUSTOM_LOGGER_URL / CUSTOM_LOGGER_API_KEYEnvía logs a un endpoint HTTP personalizado

Panel de administración, seguridad, límite de tasa, notificaciones

Estas generalmente tienen valores por defecto razonables y no necesitan cuentas externas — consulta .env.example para la lista completa: ADMIN_PANEL_URL, ADMIN_SESSION_TIMEOUT_MINUTES, ADMIN_REQUIRE_EMAIL_VERIFICATION, ADMIN_REQUIRE_2FA_SUPER_ADMIN, SESSION_EXPIRY_HOURS, MAX_FAILED_LOGIN_ATTEMPTS, ACCOUNT_LOCK_DURATION_MINUTES, el bloque PASSWORD_* de políticas, el bloque RATE_LIMIT_*, y NOTIFICATION_* / PUSH_NOTIFICATION_PROVIDER.

Frontend — apps/frontend-nextjs/.env.local

VariablePropósito
NEXT_PUBLIC_GRAPHQL_URLEndpoint GraphQL de cliente del backend — http://localhost:8000/web/graphql (el cliente usa la ruta dedicada /web/graphql; ya no hay /graphql legacy). Ajusta a tu BACKEND_PORT (por defecto 8000).
NEXT_PUBLIC_WS_URLWebSocket de suscripciones GraphQL — ws://localhost:8000/web/graphql
NEXT_PUBLIC_SITE_URLURL pública del sitio — se usa para metadatos SEO, enlaces canónicos, robots.txt, sitemap.xml. Debe ser el dominio real de producción en producción.
NEXT_PUBLIC_FIREBASE_API_KEY / _AUTH_DOMAIN / _PROJECT_ID / _STORAGE_BUCKET / _MESSAGING_SENDER_ID / _APP_IDConfiguración de la app web de Firebase (de la consola de Firebase, distinta de las credenciales de cuenta de servicio del backend)
NEXT_PUBLIC_FIREBASE_VAPID_KEYClave VAPID de Firebase Web Push — habilita las notificaciones push en la web. Opcional.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYClave pública de Stripe para los Elements del lado del cliente
NEXT_PUBLIC_PAYPAL_CLIENT_IDClient id público de la app de PayPal — para los botones de PayPal de "comprar monedas"
NEXT_PUBLIC_ADSENSE_CLIENTId de publicador de Google AdSense (p. ej. ca-pub-…). Activa el loader de verificación/Auto ads a nivel de todo el sitio en app/layout.tsx y el renderizado de AdSense en el espacio de anuncio del perfil — ver Anuncios y Reparto de Ingresos
NEXT_PUBLIC_GAM_NETWORK_CODECódigo de red de Google Ad Manager — habilita el espacio de anuncio del perfil basado en GPT (la ruta conforme de ingresos por creador, ver Anuncios y Reparto de Ingresos)
NEXT_PUBLIC_GA_MEASUREMENT_IDId de medición de GA4 (p. ej. G-XXXXXXXXXX), de Google Analytics → Admin → Data streams. Opcional — la etiqueta <GoogleAnalytics> en app/layout.tsx solo se renderiza cuando esto está configurado, así el tráfico de desarrollo nunca contamina la analítica de producción.
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYAutocompletado de Google Places para el campo de "ubicación" del composer de posts (necesita la Places API + Maps JavaScript API habilitadas en la clave). Opcional — sin ella el campo recae en entrada de texto manual + geolocalización.
NEXT_PUBLIC_GIPHY_API_KEYClave API de GIPHY — potencia el selector de GIFs
NEXT_PUBLIC_PHONE_LOGIN_PROVIDERRefleja el PHONE_LOGIN_PROVIDER del backend. Solo disabled tiene efecto aquí — oculta el botón "Continue with phone" en Login.tsx / AddAccountModal.tsx. Déjalo en blanco/sin configurar (o firebase) para mantenerlo visible.
NEXT_PUBLIC_APPLE_CLIENT_IDSign in with Apple en la web — un "Services ID" registrado en Apple Developer (ligado a un dominio verificado + Return URLs), no el Bundle ID de la app iOS nativa. Debe coincidir con APPLE_WEB_CLIENT_ID del backend. Déjalo en blanco para ocultar/desactivar el botón "Continue with Apple" (muestra un mensaje de "no disponible" en vez de fallar silenciosamente).
NEXT_PUBLIC_APPLE_REDIRECT_URIURL de retorno registrada para el Services ID de arriba. Requerida por el init() de Apple incluso en modo popup. Por defecto usa el origin actual si no se configura.

Todas las variables NEXT_PUBLIC_* se exponen al bundle del navegador — nunca pongas un secreto en una de estas.

iOS — apps/ios/app

iOS no carga un archivo .env automáticamente. apps/ios/app/.env.example es solo de referencia; los valores reales deben ingresarse directamente en el scheme de Xcode:

Xcode → Product → Scheme → Edit Scheme → Run → Arguments → Environment Variables

VariablePropósito
STRIPE_PUBLISHABLE_KEYLeída por Secrets.swift — recae en una clave de prueba fija en builds DEBUG, pero causa fatalError en Release si no está configurada
GIPHY_API_KEYMismo patrón — respaldo de desarrollo fijo en DEBUG, requerida en Release
API_HOSTOpcional — por defecto 127.0.0.1. Configúrala con la IP LAN de tu Mac (ipconfig getifaddr en0) al probar en un dispositivo físico. APIConfig.swift construye el endpoint como http://<API_HOST>:8000/web/graphql (la misma ruta /web/graphql que el cliente web).

Otras dos piezas de configuración de iOS que no son variables de entorno en absoluto:

  • app/GoogleService-Info.plist — ya está incluido en el repositorio, apuntando a la app iOS de Firebase del proyecto. Si estás levantando un proyecto de Firebase separado, descarga el tuyo propio desde la consola de Firebase y reemplaza este archivo (ver Obtención de claves API).
  • app/app.entitlements — declara la capacidad com.apple.developer.applesignin (necesaria para Sign in with Apple) y un grupo de apps (group.com.closegram, compartido con la extensión NotificationService para notificaciones push enriquecidas). Si haces un fork de esto bajo tu propio bundle ID, actualiza el identificador del grupo de apps aquí y en tu cuenta de Apple Developer.

Consulta la página técnica de iOS para el resto de la configuración (abrir el proyecto, resolver los paquetes de Swift, ejecutar pruebas).