# t3-env: Type-safe Environment Validation untuk TypeScript & Node.js

## 📌 Pendahuluan

Dalam pengembangan aplikasi modern — baik di **Next.js**, **Hono**, **Bun**, atau **Node.js murni** — kita sering menggunakan **variabel environment (**`process.env`) untuk menyimpan konfigurasi penting seperti:

* API key
    
* URL database
    
* Secret token
    
* Konfigurasi mode (production/development)
    

Namun, masalah klasik yang sering muncul adalah:

* ❌ Salah ketik nama variabel (`API_URL` vs `APIURL`)
    
* ⚠️ Variabel tidak didefinisikan di `.env`
    
* 🧩 Nilai environment tidak sesuai format (misalnya, bukan URL yang valid)
    
* 🔐 Variabel rahasia tidak sengaja terekspos ke sisi client
    

Masalah-masalah ini bisa berujung pada **bug runtime**, **error production**, atau **kebocoran data sensitif**.

Untuk itulah hadir `t3-env` — solusi dari tim **T3 Stack** (pencipta `create-t3-app`) untuk memberikan **validasi**, **keamanan**, dan **type safety** penuh terhadap variabel environment di proyek TypeScript.

---

## ⚙️ Apa itu `t3-env`?

`t3-env` adalah library yang:

* Menggunakan **Zod** untuk memvalidasi variabel environment
    
* Menghasilkan **type definitions otomatis**
    
* Membedakan antara **server-side** dan **client-side**
    
* Menjamin semua variabel environment **terdefinisi dan valid** sebelum aplikasi berjalan
    

Dengan kata lain, `t3-env` membuat `process.env` menjadi **type-safe** dan **reliable**.

---

## 💡 Perbandingan dengan `dotenv`

| Aspek | `dotenv` | `t3-env` |
| --- | --- | --- |
| Fungsi utama | Membaca file `.env` ke `process.env` | Memvalidasi dan memberi tipe pada variabel ENV |
| Level keamanan | Tidak ada validasi | Validasi ketat menggunakan `zod` |
| TypeScript support | Tidak ada (semua \`string | undefined\`) |
| Beda client/server | Tidak ada | Ada pemisahan jelas |
| Error handling | Silent (jika variabel hilang) | Throw error langsung |
| Digunakan di | Semua proyek Node.js | Proyek TS/JS modern seperti Next.js, Hono, Bun, dkk |

**Kesimpulan:**  
`t3-env` bukan pengganti langsung `dotenv`, tapi pelengkap dan peningkatnya.  
Jika framework-mu **sudah memuat** `.env` otomatis (seperti Next.js, Bun, Vite), maka **tidak perlu menginstal** `dotenv` lagi.

---

## 🚀 Instalasi

Jika kamu menggunakan **Bun**, **Node.js**, atau **Hono**:

```bash
npm install @t3-oss/env-core zod
```

Atau jika kamu memakai Next.js:

```bash
npm install @t3-oss/env-nextjs zod
```

---

## 🧩 Struktur Dasar Penggunaan

### 1\. Import dan Definisikan Schema

```ts
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    SECRET_KEY: z.string().min(1),
  },
  client: {
    NEXT_PUBLIC_API_URL: z.string().url(),
  },
  runtimeEnv: process.env,
});
```

### 2\. Akses dengan Type Safety

```ts
console.log(env.DATABASE_URL); // ✅ Sudah pasti string valid
console.log(env.NEXT_PUBLIC_API_URL); // ✅ Hanya bisa diakses jika di client schema
```

Jika ada kesalahan seperti:

* Variabel belum didefinisikan
    
* Format tidak sesuai schema  
    maka `t3-env` akan langsung menampilkan error pada runtime **dan** di IDE TypeScript.
    

---

## 🔐 Pemisahan Client dan Server

Salah satu keunggulan besar `t3-env` adalah **pemisahan konteks**.

### Server-only

Variabel seperti:

```typescript
DATABASE_URL=postgresql://...
SECRET_KEY=abc123
```

Hanya didefinisikan di:

```ts
server: {
  DATABASE_URL: z.string().url(),
  SECRET_KEY: z.string(),
}
```

### Client-only

Variabel dengan prefix `NEXT_PUBLIC_`:

```typescript
NEXT_PUBLIC_API_URL=https://api.example.com
```

Hanya boleh didefinisikan di:

```ts
client: {
  NEXT_PUBLIC_API_URL: z.string().url(),
}
```

Jika kamu mencoba mengakses `SECRET_KEY` di browser, `t3-env` akan mencegahnya secara otomatis.

---

## 🧠 Validasi dan Error Handling

Misal file `.env` kamu tidak lengkap:

```typescript
DATABASE_URL=
SECRET_KEY=supersecret
```

Maka `t3-env` akan memberikan error seperti:

```typescript
❌ Invalid environment variables:
  DATABASE_URL: Expected URL, received ""
```

Artinya aplikasi **tidak akan berjalan** sebelum environment valid — memastikan keamanan sejak awal.

---

## 🔄 Integrasi dengan `dotenv` (Opsional)

Jika kamu menggunakan Node.js tanpa framework seperti Bun atau Next.js, tambahkan:

```bash
npm install dotenv
```

Lalu di file `env.ts`:

```ts
import "dotenv/config";
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    PORT: z.string().default("3000"),
  },
  runtimeEnv: process.env,
});
```

---

## 🧱 Contoh Implementasi di Hono + Bun

```ts
// src/env.ts
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";

export const env = createEnv({
  server: {
    DATABASE_URL: z.string().url(),
    API_SECRET: z.string(),
  },
  runtimeEnv: process.env,
});

// src/index.ts
import { Hono } from "hono";
import { env } from "./env";

const app = new Hono();

app.get("/", (c) => c.text(`Connected to: ${env.DATABASE_URL}`));

export default app;
```

---

## 📈 Manfaat Penggunaan `t3-env`

1. **Type safety penuh**
    
    > Tidak ada lagi [`process.env.MY`](http://process.env.MY)`_KEY as string`.
    
2. **Validasi otomatis**
    
    > Aplikasi gagal start jika ENV tidak valid.
    
3. **Keamanan terjaga**
    
    > Variabel rahasia tidak bocor ke client.
    
4. **Error cepat dan jelas**
    
    > Developer tahu persis variabel mana yang salah.
    
5. **Terintegrasi mulus**
    
    > Cocok dengan Next.js, Hono, Bun, dan semua framework modern.
    

---

## ⚠️ Tips dan Best Practice

* Gunakan **prefix** `NEXT_PUBLIC_` untuk variabel yang boleh diakses di frontend.
    
* Jangan definisikan variabel rahasia di `client`.
    
* Selalu commit file `env.example` (bukan `.env`!) untuk panduan environment rekan tim.
    
* Gunakan `z.union()` atau `z.enum()` untuk nilai pilihan seperti `NODE_ENV`.
    

Contoh:

```ts
NODE_ENV: z.enum(["development", "production", "test"]),
```

---

## 🧾 Kesimpulan

`t3-env` membawa **revolusi kecil tapi penting** dalam dunia JavaScript/TypeScript modern:  
dari sekadar “membaca file `.env`” menjadi **validasi environment yang aman, kuat, dan terintegrasi penuh dengan TypeScript**.

Jika kamu sudah terbiasa menggunakan `dotenv`, migrasi ke `t3-env` akan membuat workflow-mu lebih:

* Aman
    
* Jelas
    
* Profesional
    

---

## 📚 Rangkuman Cepat

| Fitur | `dotenv` | `t3-env` |
| --- | --- | --- |
| Load `.env` file | ✅ | ❌ (bisa lewat dotenv) |
| Validasi nilai | ❌ | ✅ (via Zod) |
| Type safety | ❌ | ✅ |
| Pemisahan client/server | ❌ | ✅ |
| Cocok untuk Next.js / Bun / Hono | ⚠️ | ✅ |
| Throw error bila salah | ❌ | ✅ |

---
