16 أغسطس 2026•Yousef Dawood

T3.ENV: خلي Environment Variables Type-Safe

تعرّف على T3.ENV وكيف تساعدك في التحقق من Environment Variables واكتشاف أخطاء الإعداد أثناء Build قبل أن تتحول إلى مشاكل في Production.

جدول المحتويات

T3.ENV: خلّي Environment Variables بتاعتك Type-Safe

المقال الأصلي بالإنجليزية

المقال ده ترجمة وتوسعة لمقال إنجليزي أصلي بعنوان "Type-Safe Your Environment Variables: Future You Will Thank You". تقدر تقرأ النسخة الأصلية من هنا.

عمرك حصل معاك إنك تكون عامل Integration مع Service في مشروعك، وكل حاجة شغالة تمام، وفجأة الخدمة تقرر تتوقف وترمي لك Error غريب من غير سبب واضح

في حالات كتير، السبب بيكون حاجة صغيرة جدًا:

  • Typo في اسم Environment Variable.
  • Configuration ناقصة.
  • Environment Variable مش موجودة أثناء الـ Build.
  • أو قيمة موجودة، لكن مش بالشكل اللي التطبيق متوقعه.

وهنا بييجي دور T3.ENV.

T3.ENV مكتبة بتساعدك تعمل Validation و Type Safety للـ Environment Variables، وبالتالي تقدر تكتشف المشاكل دي بدري بدل ما تستنى التطبيق يقع في Production

في المقال ده، هنفهم:

  • يعني إيه T3.ENV
  • يعني إيه Framework Agnostic
  • إزاي نستخدم T3.ENV مع Next.js
  • إزاي نعمل Validation للـ Environment Variables
  • وإزاي نخلي الـ Build نفسه يفشل لو الـ Environment ناقصة أو غلط

يعني إيه T3.ENV

خلينا الأول نشوف تعريف T3.ENV الرسمي:

Framework agnostic validation for type-safe environment variables.

الجملة دي فيها فكرتين مهمين جدًا، فخلينا نفككها واحدة واحدة.


يعني إيه Framework Agnostic

أول مصطلح محتاج نفهمه هو Framework Agnostic.

هتقابل المصطلح ده كتير جدًا في عالم JavaScript والـ Web Development.

مثلًا، مكتبات زي TanStack Query و Zod مش مرتبطة بـ Framework واحد بعينه.

كون المكتبة Framework Agnostic معناه ببساطة إنها مش مصممة علشان تشتغل مع Framework معين فقط. يعني مش لازم تكون بتستخدم:

  • Next.js
  • Nuxt
  • Remix
  • Express
  • NestJS

علشان تستفيد منها.

ببساطة

T3.ENV مش مهتم أنت بتستخدم أنهي Framework.

هو مسؤول عن حاجة واحدة أساسية: Validation و Type Safety للـ Environment Variables.

في المقال ده، هنستخدم Next.js 16 كمثال، لكن الفكرة نفسها مش مرتبطة بـ Next.js.


إعداد T3.ENV في المشروع

علشان نبدأ نعمل Type-Safe Environment Variables، محتاجين نثبت الـ Package الخاصة بـ T3.ENV بالإضافة إلى Zod اللي هنستخدمه في تعريف Validation Schema.

1. تثبيت الـ Dependencies

يمكنك تثبيت الـ Packages باستخدام Package Manager المفضل عندك:

npm install @t3-oss/env-nextjs zod

ليه Zod

T3.ENV محتاج Validation Library علشان تحدد شكل وقواعد الـ Environment Variables.

في المثال ده هنستخدم Zod، وهو الاختيار الشائع والمُوصى به مع T3.ENV.

2. شكل المشروع

قبل ما نبدأ إعداد T3.ENV، خلينا نشوف شكل المشروع:

.env
env.ts
package.json
tsconfig.json
next.config.ts

هنحط كل الـ Environment Variable Configuration الخاصة بـ T3.ENV داخل:

src/lib/env.ts
src/lib/env.ts

استخدام T3.ENV في المشروع

دلوقتي نبدأ بالجزء المهم.

داخل env.ts هنكتب الـ Schema اللي هيحدد الـ Environment Variables المطلوبة وقواعد التحقق الخاصة بكل واحدة:

src/lib/env.ts
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';

export const env = createEnv({
  server: {
    DATABASE_URL: z.url(),
    AWS_ACCESS_KEY_ID: z.string().min(1),
    AWS_SECRET_ACCESS_KEY: z.string().min(1),
    AWS_ENDPOINT_URL_S3: z.url(),
    AWS_ENDPOINT_URL_IAM: z.url(),
    AWS_REGION: z.string().min(1),
  },

  client: {
    NEXT_PUBLIC_AWS_BUCKET_NAME: z.string().min(1),
  },

  experimental__runtimeEnv: {
    NEXT_PUBLIC_AWS_BUCKET_NAME: process.env.NEXT_PUBLIC_AWS_BUCKET_NAME,
  },
});

الكود شكله بسيط، لكن فيه أكتر من حاجة مهمة بتحصل هنا. خلينا نفككه خطوة خطوة.


إيه اللي createEnv بتعمله

أول حاجة عندنا:

import { createEnv } from '@t3-oss/env-nextjs';

وبعدها:

export const env = createEnv({
  // ...
});

الـ createEnv هي المسؤولة عن إنشاء الـ Environment Configuration الخاصة بالتطبيق. ومن خلالها بنحدد:

  • إيه الـ Environment Variables الموجودة عندنا
  • إيه اللي Server-side
  • إيه اللي Client-side
  • وإيه الـ Validation Rules الخاصة بكل Variable

Server Environment Variables

عندنا أولًا:

src/lib/env.ts
server: {
  DATABASE_URL: z.url(),
  AWS_ACCESS_KEY_ID: z.string().min(1),
  AWS_SECRET_ACCESS_KEY: z.string().min(1),
  AWS_ENDPOINT_URL_S3: z.url(),
  AWS_ENDPOINT_URL_IAM: z.url(),
  AWS_REGION: z.string().min(1),
},

الـ server هنا بنحط فيه الـ Environment Variables اللي المفروض يتم استخدامها على الـ Server فقط. مثلًا:

DATABASE_URL
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY

دي بيانات مش المفروض تتبعت للـ Browser.

مهم جدًا

أي Secret أو Credential زي Database Password أو AWS Secret Key لازم يفضل Server-side.

ما تحطش الـ Secrets داخل NEXT_PUBLIC_*.


Client Environment Variables

بعد كده عندنا:

src/lib/env.ts
client: {
  NEXT_PUBLIC_AWS_BUCKET_NAME: z.string().min(1),
},

الـ client مخصص للـ Environment Variables اللي مسموح إنها تكون متاحة في الـ Client.

وفي Next.js، الـ Environment Variables اللي المفروض تكون متاحة للـ Browser لازم تبدأ بـ:

NEXT_PUBLIC_

مثلًا:

.env
NEXT_PUBLIC_AWS_BUCKET_NAME=my-bucket

لكن خليك واخد بالك من نقطة مهمة جدًا:

NEXT_PUBLIC_ مش معناها إن القيمة بقت آمنة. هي معناها إن القيمة مسموح إنها تكون Public.

يعني لو حطيت Secret Key بالشكل ده:

.env
NEXT_PUBLIC_AWS_SECRET_KEY=super-secret-key

خلي بالك

NEXT_PUBLIC_ معناها إن الـ Variable هتبقى متاحة للـ Client.

فما تستخدمهاش مع Secrets أو Credentials أو أي قيمة المفروض تفضل Private.


experimental__runtimeEnv

في Next.js، T3.ENV محتاجة تعرف الـ Client Environment Variables اللي هتكون متاحة أثناء Runtime.

علشان كده بنضيف:

src/lib/env.ts
experimental__runtimeEnv: {
  NEXT_PUBLIC_AWS_BUCKET_NAME:
    process.env.NEXT_PUBLIC_AWS_BUCKET_NAME,
},

وبالتالي T3.ENV تقدر تتعامل مع قيمة الـ Client Environment Variable دي أثناء Runtime.

ليه بنعمل كده

الـ Server Environment Variables بتتقرأ مباشرة من البيئة اللي التطبيق شغال فيها.

لكن الـ Client Variables محتاجة تكون معرفة بشكل صريح علشان T3.ENV تقدر تتأكد منها وتتعامل معاها بالشكل الصحيح.


النتيجة: Type-Safe Environment Variables

بعد ما عملنا الـ Schema، بدل ما تكتب:

process.env.DATABASE_URL;

في كل مكان، تقدر تستخدم:

src/lib/database.ts
import { env } from '@/lib/env';

const databaseUrl = env.DATABASE_URL;

وهنا تبدأ تستفيد فعلًا من الـ Type Safety.

لو كتبت:

env.DATABASE_URL;

الـ TypeScript عارف إن القيمة دي موجودة في الـ Schema.

ولو حاولت تستخدم Environment Variable مش معرفة:

env.SOMETHING_THAT_DOES_NOT_EXIST;

هتاخد TypeScript Error بدل ما تستنى التطبيق يكتشف المشكلة في Runtime.


T3.ENV في VS Code

وده شكل التجربة أثناء استخدام env داخل VS Code:

example.ts
import { env } from '@/lib/env';

env.DATABASE_URL;
env.AWS_ACCESS_KEY_ID;
env.AWS_SECRET_ACCESS_KEY;
env.AWS_REGION;

الـ Editor بقى عارف بالضبط إيه الـ Variables الموجودة وإيه أنواعها.

Type-Safe Environment Variables في VS Code

وده الفرق بين:

process.env.SOMETHING;

وبين:

env.SOMETHING;

الأولى مجرد String ممكن تكون موجودة أو لأ. الثانية بقت جزء من Schema محدد ومتحقق منه.


Validate الـ Schema أثناء الـ Build

دلوقتي وصلنا لواحدة من أهم أجزاء إعداد T3.ENV مع Next.js.

لو عايز تتأكد إن الـ Environment Variables بتاعتك صحيحة أثناء Build، ممكن تستورد env.ts داخل next.config.ts.

next.config.ts
import type { NextConfig } from 'next';

import './src/lib/env';

const nextConfig: NextConfig = {
  // Your Next.js configuration
};

export default nextConfig;

لاحظ السطر ده:

import './src/lib/env';

إحنا مش محتاجين نستخدم الـ env هنا. مجرد Import الملف كفاية علشان يتم تنفيذ الـ Validation أثناء عملية الـ Build.

ملاحظة مهمة

الفكرة هنا إن مجرد استيراد ملف env.ts بيشغّل createEnv أثناء الـ Build، وبالتالي أي Validation Error هتظهر بدري بدل ما تستنى Runtime.


إيه اللي بيحصل لو Environment Variable ناقصة

خلينا نفترض إن عندنا:

src/lib/env.ts
server: {
  DATABASE_URL: z.url(),
  AWS_ACCESS_KEY_ID: z.string().min(1),
  AWS_SECRET_ACCESS_KEY: z.string().min(1),
},

لكن الـ Environment بتاعتنا ناقص منها:

.env
DATABASE_URL=postgresql://localhost:5432/mydb
AWS_SECRET_ACCESS_KEY=secret

لاحظ إن:

AWS_ACCESS_KEY_ID

مش موجودة.

لما تعمل Build، T3.ENV هتعمل Validation للـ Environment. وبما إن:

AWS_ACCESS_KEY_ID: z.string().min(1);

مطلوبة، فالـ Validation هتفشل.

مثال على Validation Error عند فقدان Environment Variable

Build Failed 🚨

بدل ما التطبيق يكمل Build وبعدها تكتشف المشكلة في Production، الـ Build نفسه هيفشل ويقولك إن الـ Environment Configuration فيها مشكلة.

وده بالضبط اللي إحنا عايزينه.


رحلة الـ Environment Variable

ممكن نبسط الموضوع كله في الخطوات دي:

تعريف Environment Variables

بنحدد الـ Environment Variables المطلوبة في .env أو في Environment الخاصة بالـ Deployment.

تعريف الـ Schema

بنحدد داخل createEnv كل Variable ونوعها والـ Validation Rules الخاصة بيها باستخدام Zod.

تشغيل Validation

T3.ENV تقرأ القيم الموجودة وتقارنها بالـ Schema اللي إحنا عرفناه.

اكتشاف الأخطاء

لو Variable ناقصة أو قيمتها غير صحيحة، الـ Validation هتفشل.

منع الـ Build

لو استوردنا env.ts داخل next.config.ts، الخطأ هيظهر أثناء الـ Build بدل ما يتحول لمشكلة في Production.


تجربة T3.ENV عمليًا

وده فيديو قصير بيوضح النتيجة النهائية وتجربة استخدام T3.ENV داخل المشروع:


ملاحظات عن Documentation الخاصة بـ T3.ENV

فيه نقطة مهمة لازم ناخد بالنا منها أثناء قراءة Documentation الخاصة بـ T3.ENV — ملاحظات إضافية مش أساسية لفهم الموضوع، فحطيناها هنا في Accordion علشان تقرأها لو حابب تتعمق أكتر:


الخلاصة

وبكده قدرنا نبني Environment Configuration أكثر أمانًا وتنظيمًا باستخدام:

الفكرة في النهاية بسيطة جدًا:

بدل ما تسيب الـ Environment Variables عبارة عن مجموعة Strings ممكن تكون موجودة أو ناقصة أو مكتوبة غلط، أنت بتحولها إلى Configuration لها Schema وقواعد واضحة.

وده معناه إن أخطاء زي:

  • Environment Variable ناقصة.
  • اسم Variable مكتوب غلط.
  • URL غير صالح.
  • قيمة فاضية.
  • استخدام Variable غير موجودة.

ممكن يتم اكتشافها بدري جدًا.

لو لقيت أي نقطة محتاجة تصحيح أو عندك إضافة، شاركني بيها ❤️ ولا تنسوني من دعائكم.