Environment Variables
Environment variables let you store secrets and configuration outside your codebase. They are encrypted at rest, decrypted at deploy time, and injected into your API routes as environment variables.
Setting variables
Section titled “Setting variables”Via the CLI
Section titled “Via the CLI”# Set a variabletma env set DATABASE_URL=postgres://...
# Set another variabletma env set ANALYTICS_KEY=ak_123
# List all variablestma env list
# Remove a variabletma env remove DATABASE_URL
# Pull variable names to a local .env.local file (values are redacted)tma env pullThe CLI sets variables for the production environment. Environment scoping beyond production (preview, development) is managed through the dashboard.
Via the dashboard
Section titled “Via the dashboard”Navigate to your project’s Settings > Environment Variables page. Add, edit, or remove variables from the web interface. Changes take effect on the next deployment.
Environment scoping
Section titled “Environment scoping”Variables can be scoped to specific environments:
| Scope | Applied to |
|---|---|
| Production | Production deployments (tma deploy) |
| Preview | Preview deployments (pull request branches) |
| Development | Local development (tma dev) |
If a variable is set without a scope, it applies to all environments. Scoped variables override unscoped ones.
Environment scoping is managed through the dashboard at Settings > Environment Variables, where you can set different values for each environment. The CLI always targets the production environment.
Accessing variables in API routes
Section titled “Accessing variables in API routes”Environment variables are available on the c.env object in your Hono API routes:
import { Hono } from 'hono';
type Env = { Bindings: { DATABASE_URL: string; STRIPE_SECRET_KEY: string; RESEND_API_KEY: string; };};
const app = new Hono<Env>();
app.post('/api/send-email', async (c) => { const res = await fetch('https://api.resend.com/emails', { method: 'POST', headers: { Authorization: `Bearer ${c.env.RESEND_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ from: 'noreply@myapp.tma.sh', to: 'user@example.com', subject: 'Hello', text: 'Welcome to the app!', }), });
return c.json({ sent: res.ok });});
export default app;Local development
Section titled “Local development”During tma dev, environment variables scoped to development are loaded automatically. You can also use a .env file in your project root for local overrides:
# .env (git-ignored by default)DATABASE_URL=postgres://localhost:5432/myappSTRIPE_SECRET_KEY=sk_test_...The CLI loads .env values as a fallback when development-scoped variables are not set in the dashboard.
Common use cases
Section titled “Common use cases”| Variable | Purpose |
|---|---|
DATABASE_URL | External database connection string |
BOT_TOKEN | Telegram bot token |
STRIPE_SECRET_KEY | Payment processor credentials |
RESEND_API_KEY | Email service API key |
SENTRY_DSN | Error tracking |
Security
Section titled “Security”- Variables are encrypted at rest and only decrypted during deployment.
- They are never included in your static SPA bundle — only API routes have access.
- Variables are not logged in build output or deployment logs.
- Use the dashboard or CLI to rotate secrets without redeploying code — trigger a redeploy to pick up the new value.
- Add
.envto your.gitignoreto prevent accidentally committing local secrets.