Skip to content

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.

Terminal window
# Set a variable
tma env set DATABASE_URL=postgres://...
# Set another variable
tma env set ANALYTICS_KEY=ak_123
# List all variables
tma env list
# Remove a variable
tma env remove DATABASE_URL
# Pull variable names to a local .env.local file (values are redacted)
tma env pull

The CLI sets variables for the production environment. Environment scoping beyond production (preview, development) is managed through 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.

Every secret in TMA.sh is scoped to a specific environment:

ScopeApplied to
ProductionProduction deployments
PreviewPreview deployments
DevelopmentReserved for development-scoped workflows

Environment scoping is managed through the dashboard at Settings > Environment Variables. The CLI (tma env set) always writes production secrets. Deployment builds currently load production or preview scoped secrets based on deployment type.

Environment variables are available via the env parameter in your API routes. With Hono, access them on c.env; with plain fetch handlers, they are the second argument to fetch(request, env):

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({
subject: 'Hello',
text: 'Welcome to the app!',
}),
});
return c.json({ sent: res.ok });
});
export default app;

tma dev does not automatically pull dashboard secrets into local worker bindings. For local frontend code, Vite’s standard .env loading still applies:

Terminal window
# .env (or .env.local)
DATABASE_URL=postgres://localhost:5432/myapp
STRIPE_SECRET_KEY=sk_test_...

For worker-side local values, provide explicit test values in your local code/test setup.

VariablePurpose
DATABASE_URLExternal database connection string
BOT_TOKENTelegram bot token
STRIPE_SECRET_KEYPayment processor credentials
RESEND_API_KEYEmail service API key
SENTRY_DSNError tracking
  • Variables are encrypted at rest and only decrypted during deployment.
  • They are never included in your static SPA bundle — only API routes have access.
  • Avoid logging secret values from your own build scripts or runtime code.
  • Use the dashboard or CLI to rotate secrets without changing code — trigger a redeploy to pick up the new value.
  • Add .env to your .gitignore to prevent accidentally committing local secrets.