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، خلينا نشوف شكل المشروع:
هنحط كل الـ Environment Variable Configuration الخاصة بـ T3.ENV داخل:
src/lib/env.tsاستخدام T3.ENV في المشروع
دلوقتي نبدأ بالجزء المهم.
داخل env.ts هنكتب الـ Schema اللي هيحدد الـ Environment Variables المطلوبة وقواعد التحقق الخاصة بكل واحدة:
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
عندنا أولًا:
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
بعد كده عندنا:
client: {
NEXT_PUBLIC_AWS_BUCKET_NAME: z.string().min(1),
},الـ client مخصص للـ Environment Variables اللي مسموح إنها تكون متاحة في الـ Client.
وفي Next.js، الـ Environment Variables اللي المفروض تكون متاحة للـ Browser لازم تبدأ بـ:
NEXT_PUBLIC_مثلًا:
NEXT_PUBLIC_AWS_BUCKET_NAME=my-bucketلكن خليك واخد بالك من نقطة مهمة جدًا:
NEXT_PUBLIC_ مش معناها إن القيمة بقت آمنة. هي معناها إن القيمة مسموح إنها تكون Public.
يعني لو حطيت Secret Key بالشكل ده:
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.
علشان كده بنضيف:
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;في كل مكان، تقدر تستخدم:
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:
import { env } from '@/lib/env';
env.DATABASE_URL;
env.AWS_ACCESS_KEY_ID;
env.AWS_SECRET_ACCESS_KEY;
env.AWS_REGION;الـ Editor بقى عارف بالضبط إيه الـ Variables الموجودة وإيه أنواعها.

وده الفرق بين:
process.env.SOMETHING;وبين:
env.SOMETHING;الأولى مجرد String ممكن تكون موجودة أو لأ. الثانية بقت جزء من Schema محدد ومتحقق منه.
Validate الـ Schema أثناء الـ Build
دلوقتي وصلنا لواحدة من أهم أجزاء إعداد T3.ENV مع Next.js.
لو عايز تتأكد إن الـ Environment Variables بتاعتك صحيحة أثناء Build، ممكن تستورد env.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 ناقصة
خلينا نفترض إن عندنا:
server: {
DATABASE_URL: z.url(),
AWS_ACCESS_KEY_ID: z.string().min(1),
AWS_SECRET_ACCESS_KEY: z.string().min(1),
},لكن الـ Environment بتاعتنا ناقص منها:
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 هتفشل.

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 غير موجودة.
ممكن يتم اكتشافها بدري جدًا.
لو لقيت أي نقطة محتاجة تصحيح أو عندك إضافة، شاركني بيها ❤️ ولا تنسوني من دعائكم.