2026 میں بالکل شروع سے ایک کسٹم بلاگ بنانا ایک سوچا سمجھا فیصلہ ہے۔ زیادہ تر لکھاری محض ایک ہوسٹڈ پلیٹ فارم منتخب کرتے ہیں اور آگے بڑھ جاتے ہیں۔ میں نے اپنے ٹیک بلاگ کو Astro کے ساتھ دوبارہ بنانے کا فیصلہ کیا کیونکہ میں اسٹیک کے ہر لیئر کا مالک بننا چاہتا تھا اور ایسے پیٹرنز سیکھنا چاہتا تھا جو ایک اسٹیٹک سائٹ کو صرف مختلف نہیں بلکہ حقیقت میں تیز بنا دیں۔ اس کا نتیجہ ایک دو لسانی سائٹ کی صورت میں نکلا ہے جو جاپانی اور انگریزی مواد فراہم کرتی ہے، ڈیفالٹ طور پر زیرو JavaScript بھیجتی ہے، اور ہر قسم کی پیچیدگی کو وزیٹر کے براؤزر کے بجائے میری مشین تک محدود رکھتی ہے۔
یہاں وہ پانچ پیٹرنز ہیں جنہوں نے اسے کامیاب بنایا۔
Zod کے ساتھ Content Collections
Astro کے Content Collections صرف Markdown فائلوں کو فولڈرز میں ترتیب دینے سے کہیں زیادہ کام کرتے ہیں۔ وہ آپ کے مواد اور آپ کے کوڈ کے درمیان ایک معاہدہ (contract) نافذ کرتے ہیں۔ میں نے ہر آرٹیکل کلیکشن کے ساتھ ایک Zod schema منسلک کیا، جس کا مطلب ہے کہ بلڈ مرحلے میں ایک بھی پیج رینڈر ہونے سے پہلے frontmatter کی تصدیق ہو جاتی ہے۔
اس اسکیما میں ایک language فیلڈ کی ضرورت ہوتی ہے جو صرف دو ویلیوز قبول کرتی ہے: ja یا en۔ اس بارے میں کوئی ابہام نہیں رہتا کہ قاری کو کون سی زبان ملے گی۔ میں نے ایک pair فیلڈ بھی شامل کی ہے جو ترجموں کو آپس میں جوڑتی ہے۔ اگر میں جاپانی میں Astro کے بارے میں ایک پوسٹ شائع کرتا ہوں اور بعد میں اسے انگریزی میں ترجمہ کرتا ہوں، تو دونوں فائلیں ایک ہی pair ID شیئر کرتی ہیں۔ اس سے لینگویج سوئچر بنانا بہت آسان ہو جاتا ہے کیونکہ تعلق ڈیٹا میں واضح ہوتا ہے، نہ کہ فائل کے ناموں سے اخذ کیا جاتا ہے۔
تاریخیں Markdown frontmatter سے اسٹرنگز کے طور پر آتی ہیں، اس لیے اسکیما انہیں خود بخود حقیقی Date آبجیکٹس میں تبدیل کر دیتا ہے۔ اس سے میرے پیج ٹیمپلیٹس کے اندر اسٹرنگ مینیپلیشن کا لاجک ختم ہو جاتا ہے۔ تاہم، سب سے اہم فائدہ اس کا فیلر موڈ (failure mode) ہے۔ اگر کسی فائل میں کوئی مطلوبہ فیلڈ موجود نہ ہو یا غلط زبان کا کوڈ استعمال کیا گیا ہو، تو بلڈ فوری طور پر ایک واضح غلطی کے ساتھ رک جاتا ہے۔ میں اسے اپنے ٹرمینل میں ٹھیک کر لیتا ہوں بجائے اس کے کہ ڈیپلائمنٹ کے بعد کسی خراب لے آؤٹ یا خاموش 404 کا سامنا کرنا پڑے۔
آرٹیکل کنورژن پائپ لائن
میں نے پہلے دن سے ہی ہر پوسٹ اس نئے فارمیٹ میں نہیں لکھی تھی۔ برسوں کا مواد Zenn اور Dev.to پر موجود تھا، اور ہر پلیٹ فارم کی اپنی خصوصیات اور مخصوص سنٹیکس تھی۔ کاپی پیسٹ کرنے اور ہاتھ سے ٹھیک کرنے کے بجائے، میں نے ایک TypeScript اسکرپٹ لکھا جو آرٹیکلز کے پورے بیچ کو معیاری Markdown میں تبدیل کر دیتا ہے۔
Zenn ٹپس اور وارننگز کے لیے کسٹم کال آؤٹ سنٹیکس استعمال کرتا ہے۔ میرا اسکرپٹ انہیں سیمنٹک HTML aside ٹیگز میں بدل دیتا ہے تاکہ وہ پوری سائٹ پر یکساں طور پر رینڈر ہوں۔ Dev.to ایمبیڈز اور خصوصی بلاکس کے لیے Liquid ٹیگز پر انحصار کرتا ہے۔ پائپ لائن ان کا ترجمہ سادہ Markdown لنکس میں کر دیتی ہے جو ہر جگہ کام کرتے ہیں۔
کچھ پوسٹس میں ایسے اسائیڈز ہوتے ہیں جو صرف اصل پلیٹ فارم کے لیے ہوتے ہیں، جیسے کہ Medium paywalls کے بارے میں ڈسکلیمر یا Zenn-specific امیج پاتھ۔ میں انہیں HTML کمنٹس میں لپیٹ دیتا ہوں تاکہ کنورٹر مائیگریشن کے دوران انہیں نکال سکے۔ اسکرپٹ فائلوں کو لائن بہ لائن پروسیس کرتا ہے، لیکن یہ کوڈ کی حدود کا احترام کرتا ہے۔ جب یہ کسی fenced code block کا پتہ لگاتا ہے، تو یہ ٹرانسفارمیشن رولز کو مکمل طور پر چھوڑ دیتا ہے۔ کسی ٹیک بلاگ کے مقصد کو ہی ختم کرنے کے لیے سنٹیکس کے نمونے کو خراب کرنا درست نہیں، اس لیے لائن بہ لائن پارسر کوڈ بلاکس کو ناقابلِ تبدیلی زونز کے طور پر لیتا ہے۔
اب صرف ایک کمانڈ چلانے سے برسوں کی تحریریں بغیر کسی لنک یا کال آؤٹ کو توڑے دوبارہ شائع ہو جاتی ہیں۔
بلڈ ٹائم OGP امیج جنریشن
سوشل شیئرنگ امیجز عام طور پر بعد میں سوچا جانے والا معاملہ ہوتی ہیں۔ یا تو آپ انہیں دستی طور پر ڈیزائن کرتے ہیں یا ایک بھاری رن ٹائم سروس انسٹال کرتے ہیں جو ضرورت پڑنے پر کارڈز جنریٹ کرتی ہے۔ میں ان دونوں میں سے کچھ نہیں چاہتا تھا۔ اس سائٹ پر ہر Open Graph امیج بلڈ کے دوران تیار کی جاتی ہے تاکہ وزیٹرز کو ایک ہلکے پھلکے img ٹیگ کے علاوہ کچھ نہ ملے جو ایک اسٹیٹک PNG کی طرف اشارہ کرتا ہو۔
میں Satori استعمال کرتا ہوں، جو JSX مارک اپ لیتا ہے اور اسے SVG میں رینڈر کرتا ہے۔ آؤٹ پٹ واضح، قابلِ پیش گوئی اور ٹیمپلیٹ بنانے میں آسان ہے۔ اصل آپٹیمائزیشن فونٹ ہینڈلنگ سے آئی۔ ایک مکمل جاپانی ویب فونٹ آسانی سے پانچ میگا بائٹ سے اوپر جا سکتا ہے۔ اسے بلڈ کے دوران لوڈ کرنا، براؤزر سے اسے فیچ کرنے کا کہنا تو دور کی بات ہے، بالکل بے تکی بات ہوگی۔
اس کے بجائے، میں Google Fonts subsetting استعمال کرتا ہوں۔ اسکرپٹ کسی مخصوص پوسٹ کے ٹائٹل ٹیکسٹ کا معائنہ کرتا ہے اور صرف وہی مخصوص glyph set طلب کرتا ہے جو اس اسٹرنگ کو رینڈر کرنے کے لیے ضروری ہو۔ اگر ہیڈ لائن میں چالیس منفرد جاپانی حروف استعمال ہو رہے ہیں، تو صرف وہی چالیس حروف نیٹ ورک پر منتقل ہوں گے۔ بلڈ تیز رہتا ہے، اور رینڈر شدہ امیج میں کبھی بھی ٹوٹے ہوئے tofu blocks نظر نہیں آتے کیونکہ سب سیٹ بالکل درست ہوتا ہے۔ رن ٹائم کے اتفاق پر کچھ نہیں چھوڑا گیا۔
Tailwind Tokens کے ذریعے ڈارک موڈ
میں نے ہر ایلیمنٹ کو dark: یوٹیلیٹی کلاسز سے سجانے سے انکار کر دیا۔ یہ طریقہ کار بڑے پیمانے پر صحیح کام نہیں کرتا اور آپ کے مارک اپ کو شور سے بھر دیتا ہے۔ میں نے خود کلر ٹوکنز کو دوبارہ سے ڈیفائن کیا تاکہ ایک ہی کلاس کا نام ایکٹو تھیم کے لحاظ سے مختلف ویلیوز پر منحصر ہو۔
میں ہر سطح (surface) اور ٹیکسٹ کلر کے لیے CSS custom properties استعمال کرتا ہوں۔ لائٹ موڈ میں، --color-white کا تعلق #ffffff سے ہوتا ہے۔ ڈارک موڈ میں، وہی ویری ایبل نام ایک تقریباً سیاہ (near-black) ویلیو کی طرف اشارہ کرتا ہے۔ میرا HTML مکمل طور پر آزاد (agnostic) رہتا ہے۔ ایک کارڈ دن کے وقت کی پرواہ کیے بغیر bg-ui-surface اور text-ui-primary استعمال کر سکتا ہے۔ تھیم سوئچ روٹ (root) پر ویری ایبل کی تعریفوں کو تبدیل کر دیتا ہے، اور پورا انٹرفیس فوری طور پر ردعمل دیتا ہے۔
اس طریقہ کار کے ساتھ ایک خطرہ stylesheets لوڈ ہونے سے پہلے لائٹ مواد کا اچانک ظاہر ہونا (flash) ہے۔ میں نے اسے ڈاکومنٹ کے head میں ایک چھوٹے سے ان لائن اسکرپٹ کے ذریعے حل کیا۔ یہ پہلے پینٹ (first paint) سے پہلے چلتا ہے، localStorage اور سسٹم کی ترجیح (system preference) کو چیک کرتا ہے، اور فوری طور پر درست data attribute سیٹ کر دیتا ہے۔ چونکہ اسکرپٹ رینڈرنگ کو صرف چند ملی سیکنڈز کے لیے روکتا ہے، اس لیے وزیٹر کو ڈارک موڈ شروع ہونے سے پہلے کبھی بھی جھٹکے کے ساتھ سفید روشنی کا جھٹکا محسوس نہیں ہوتا۔
Island Architecture اور Zero-JS
Astro کا بنیادی تصور یہ ہے کہ ایک پیج کو static HTML کے طور پر شروع ہونا چاہیے۔ JavaScript صرف اس وقت شامل ہوتی ہے جب کسی انٹرایکشن کی واقعی ضرورت ہو۔ میں نے اسے سنجیدگی سے لیا۔
میں نے گلوبل مینو اور تھیم ٹوگل کے لیے React سے گریز کیا۔ دونوں کو vanilla JavaScript کی ایک چھوٹی سی مقدار کے ذریعے سنبھالا جاتا ہے جو ایک ہی ماڈیول میں ہوتی ہے۔ اس میں کوئی hydration overhead، کوئی virtual DOM diffing، اور ڈاؤن لوڈ کرنے کے لیے کوئی framework runtime نہیں ہے۔
واحد بھاری لائبریری جو میں استعمال کرتا ہوں وہ ٹیکسٹ سے ڈائیگرامز رینڈر کرنے کے لیے Mermaid.js ہے۔ اسے عالمی سطح پر امپورٹ کرنے کے بجائے، میں نے اسے Intersection Observer کے اندر لپیٹ (wrap) دیا ہے۔ آبزروور ڈائیگرام کنٹینرز پر نظر رکھتا ہے۔ جب کوئی صارف کسی ڈائیگرام کے چند سو پکسلز کے اندر اسکرول کرتا ہے، تو اسکرپٹ متحرک طور پر (dynamically) Mermaid ماڈیول کو شامل کرتا ہے اور ڈائیگرام کو رینڈر کرتا ہے۔ اگر کسی پوسٹ میں کوئی ڈائیگرام نہیں ہے، تو وہ لائبریری نیٹ ورک کو کبھی چھوتی ہی نہیں ہے۔ ابتدائی پیج لوڈ ہلکا رہتا ہے، اور براؤزر صرف اسی چیز کے لیے وسائل استعمال کرتا ہے جو قاری اصل میں دیکھتا ہے۔
Build-First Mindset
ہر پیٹرن میں چلنے والا بنیادی اصول سادہ ہے: اگر آپ کام بلڈ (build) کے دوران کر سکتے ہیں، تو اسے وہیں کریں۔ سائٹ کی تعیناتی (deploy) سے پہلے Zod کے ساتھ اپنے ڈیٹا کی تصدیق کریں۔ ریکوسٹ کے وقت کے بجائے پہلے سے ہی پراپرائٹری پلیٹ فارم سنٹیکس (proprietary platform syntax) کو تبدیل کر لیں۔ سرور چلانے کے بجائے سوشل امیجز کو static فائلوں میں رینڈر کریں۔ ہر کلائنٹ کو لاجک بھیجنے کے بجائے ٹوکنز کے ذریعے تھیم کلرز کو حل کریں۔ بھاری JavaScript کو اس وقت تک ملتوی کریں جب تک صارف کو اس کی واقعی ضرورت نہ ہو۔
پیچیدگی کو بلڈ مرحلے کی طرف منتقل کرنے سے runtime قابلِ پیش گوئی، payload چھوٹا، اور دیکھ بھال کا بوجھ قابلِ انتظام رہتا ہے۔ سائٹ کسی ایک ٹرک کی وجہ سے تیز نہیں رہتی، بلکہ اس لیے تیز رہتی ہے کیونکہ وزیٹر کے براؤزر کے اندر بہت کم کام ہو رہا ہوتا ہے۔ 2026 میں static architecture کا انتخاب کرنے کا اصل فائدہ یہی ہے۔
