Adds end-to-end browser voice capture for the Memoro module, mirroring the existing dreams pattern: MediaRecorder → SvelteKit server proxy → mana-stt on the Windows GPU box via Cloudflare tunnel. Recording UI lives in /memoro page header (mic button + live timer + cancel + sticky-permission retry). Server proxy at /api/v1/memoro/transcribe forwards the blob with the server-held X-API-Key. memosStore.createFromVoice creates a placeholder memo with processingStatus='processing' and fires transcribeBlob in the background, which writes the transcript and flips status on completion (or 'failed' with error in metadata). Also corrects the mana-stt hostname across the repo: stt-api.mana.how (which never existed in DNS) → gpu-stt.mana.how (the actual Cloudflare tunnel route to the Windows GPU box). Adds an ENVIRONMENT_VARIABLES.md section explaining how to obtain MANA_STT_API_KEY and where the tunnel terminates. Adds tunnel health probes to the mac-mini health-check script so we catch tunnel-side breakage in addition to LAN-side. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8.1 KiB
Environment Variables Guide
This document explains the centralized environment variable system for the Mana monorepo.
Quick Start
# After cloning the repo, install dependencies (auto-generates .env files)
pnpm install
# Or manually generate .env files
pnpm setup:env
That's it! All app-specific .env files are generated from .env.development.
How It Works
.env.development # Central config (committed)
│
▼
scripts/generate-env.mjs # Transforms variables
│
▼
apps/**/apps/**/.env # Generated files (gitignored)
The generator reads .env.development and creates app-specific .env files with the correct prefixes for each platform:
| Platform | Prefix | Example |
|---|---|---|
| Expo (mobile) | EXPO_PUBLIC_ |
EXPO_PUBLIC_SUPABASE_URL |
| SvelteKit (web) | PUBLIC_ |
PUBLIC_SUPABASE_URL |
| Hono/Bun (server) | None | DATABASE_URL |
File Locations
Source File
.env.development- Single source of truth, committed to git
Generated Files (gitignored)
services/mana-auth/.envapps/chat/apps/server/.envapps/chat/apps/mobile/.envapps/chat/apps/web/.envapps/mana/apps/mobile/.envapps/mana/apps/web/.envapps/cards/apps/server/.envapps/cards/apps/web/.envapps/*/apps/server/.env(all apps with compute servers)apps/*/apps/web/.env(all web apps)apps/*/apps/mobile/.env(all mobile apps)
Variable Reference
Shared Variables
| Variable | Description | Used By |
|---|---|---|
MANA_AUTH_URL |
Auth service URL | All apps |
JWT_PRIVATE_KEY |
JWT signing key | mana-auth |
JWT_PUBLIC_KEY |
JWT verification key | All backends |
POSTGRES_USER |
Database user | Docker, backends |
POSTGRES_PASSWORD |
Database password | Docker, backends |
REDIS_HOST |
Redis host | mana-auth |
REDIS_PORT |
Redis port | mana-auth |
REDIS_PASSWORD |
Redis password | mana-auth |
Mana Auth Service
| Variable | Description | Default |
|---|---|---|
MANA_AUTH_PORT |
Service port | 3001 |
MANA_AUTH_DATABASE_URL |
PostgreSQL connection string | - |
JWT_ACCESS_TOKEN_EXPIRY |
Access token TTL | 15m |
JWT_REFRESH_TOKEN_EXPIRY |
Refresh token TTL | 7d |
JWT_ISSUER |
JWT issuer claim | mana |
JWT_AUDIENCE |
JWT audience claim | mana |
STRIPE_SECRET_KEY |
Stripe secret key | - |
STRIPE_PUBLISHABLE_KEY |
Stripe publishable key | - |
STRIPE_WEBHOOK_SECRET |
Stripe webhook secret | - |
CORS_ORIGINS |
Allowed CORS origins | - |
RATE_LIMIT_TTL |
Rate limit window (seconds) | 60 |
RATE_LIMIT_MAX |
Max requests per window | 100 |
Chat Project
| Variable | Description | Default |
|---|---|---|
CHAT_BACKEND_PORT |
Backend service port | 3002 |
CHAT_DATABASE_URL |
PostgreSQL connection string | - |
AZURE_OPENAI_ENDPOINT |
Azure OpenAI endpoint URL | - |
AZURE_OPENAI_API_KEY |
Azure OpenAI API key | - |
AZURE_OPENAI_API_VERSION |
API version | 2024-12-01-preview |
CHAT_SUPABASE_URL |
Supabase project URL | - |
CHAT_SUPABASE_ANON_KEY |
Supabase anonymous key | - |
Mana Project
| Variable | Description |
|---|---|
MANA_SUPABASE_URL |
Supabase project URL |
MANA_SUPABASE_ANON_KEY |
Supabase anonymous key |
Cards Project
| Variable | Description | Default |
|---|---|---|
CARDS_BACKEND_PORT |
Backend service port | 3004 |
CARDS_SUPABASE_URL |
Supabase project URL | - |
CARDS_SUPABASE_ANON_KEY |
Supabase anonymous key | - |
Speech-to-Text (mana-stt)
Used by the unified Mana web app's voice features (Memoro recording, Dreams voice capture, etc).
The browser never talks to mana-stt directly — requests go through the SvelteKit server-side proxy
(/api/v1/memoro/transcribe, /api/v1/dreams/transcribe) which attaches the API key from
MANA_STT_API_KEY. Keep that key out of the browser bundle.
| Variable | Description | Default |
|---|---|---|
STT_URL |
Public mana-stt URL — generates MANA_STT_URL for the web app |
https://gpu-stt.mana.how |
MANA_STT_API_KEY |
API key for mana-stt. Never commit a real value. | (empty) |
Where to obtain a key:
- Production deploy: set
MANA_STT_API_KEYin the Mac Mini's.env(sourced bydocker-compose.macmini.yml, line ~1076). The key lives on the Windows GPU box inservices/mana-stt/.envunderAPI_KEYS=<key>:<name>and is the source of truth. - Local dev: paste the dev key into your local
apps/mana/apps/web/.envafter runningpnpm setup:env(the generator only writes an empty placeholder). Ask in#mana-devor pull from the team's password manager undermana-stt → web-key. - New dev key: SSH to the Windows GPU box (
ssh mana-gpu), append a new entry toC:\mana\services\mana-stt\.envAPI_KEYS(format:<random>:<name>), restart theManaSTTscheduled task. Use a fresh key per consumer (mana-web,chat-server, etc.) so we can revoke individually.
Endpoint: https://gpu-stt.mana.how — Cloudflare Tunnel mana-gpu-server →
Windows GPU box (192.168.178.11:3020). Health: curl https://gpu-stt.mana.how/health.
Adding New Variables
Step 1: Add to .env.development
# In .env.development
MY_NEW_PROJECT_API_KEY=your-api-key
MY_NEW_PROJECT_URL=https://api.example.com
Step 2: Update the Generator Script
Edit scripts/generate-env.mjs and add your app config:
// In APP_CONFIGS array
{
path: 'apps/my-project/apps/mobile/.env',
vars: {
// For Expo, add EXPO_PUBLIC_ prefix
EXPO_PUBLIC_API_KEY: (env) => env.MY_NEW_PROJECT_API_KEY,
EXPO_PUBLIC_API_URL: (env) => env.MY_NEW_PROJECT_URL,
},
},
{
path: 'apps/my-project/apps/web/.env',
vars: {
// For SvelteKit, add PUBLIC_ prefix
PUBLIC_API_KEY: (env) => env.MY_NEW_PROJECT_API_KEY,
PUBLIC_API_URL: (env) => env.MY_NEW_PROJECT_URL,
},
},
{
path: 'apps/my-project/apps/server/.env',
vars: {
// For Hono/Bun servers, no prefix needed
API_KEY: (env) => env.MY_NEW_PROJECT_API_KEY,
API_URL: (env) => env.MY_NEW_PROJECT_URL,
},
},
Step 3: Regenerate
pnpm setup:env
Local Overrides
If you need to override variables locally without affecting others:
- The generated
.envfiles are gitignored - You can manually edit them after generation
- Or create
.env.localfiles (also gitignored) that some frameworks auto-load
Note: Running pnpm setup:env will overwrite your changes, so use .env.local for persistent overrides.
Docker Integration
The root .env.development is also used by Docker Compose:
# Start all services with shared env
pnpm docker:up:all
Docker services read from:
- Root
.env.developmentfor shared values - Service-specific
.envfiles for service-specific values
Troubleshooting
"Variable is undefined" Error
- Check if the variable exists in
.env.development - Run
pnpm setup:envto regenerate - Restart your dev server (env changes require restart)
Generated File Has Wrong Value
- Check the mapping in
scripts/generate-env.mjs - Ensure the source variable name matches exactly
- Run
pnpm setup:envagain
New App Not Getting Generated
- Add app config to
APP_CONFIGSinscripts/generate-env.mjs - Ensure the target directory exists
- Run
pnpm setup:env
Expo Not Picking Up Changes
Expo caches environment variables. Clear the cache:
cd apps/<project>/apps/mobile
npx expo start -c
Security Notes
.env.developmentcontains development-only values- Never put production secrets in this file
- The JWT keys in
.env.developmentare for local development only - Use separate secrets management for production (1Password, AWS Secrets Manager, etc.)
Migration from Old System
If you have existing .env files with real values:
- Copy important values to
.env.development - Delete the old
.envfiles - Run
pnpm setup:env - Verify apps still work
The old .env.example files can remain as documentation.