एक डायरेक्टरी साइट बनाना सुनने में बहुत आसान लगता है, जब तक कि आप खुद को डेटाबेस, कैशिंग लेयर्स और रिएक्टिव फ्रंट-एंड फ्रेमवर्क को जोड़ने में उलझा हुआ न पाएं, सिर्फ इसलिए ताकि आप एक क्यूरेटेड टेबल ऑफ कंटेंट्स (विषय-सूची) दिखा सकें। मैंने हाल ही में Social Tools List बनाया है, जो सोशल मीडिया सॉफ्टवेयर की तुलना करने के लिए एक साइट है। मेरा लक्ष्य इसे जल्दी ऑनलाइन लाना, इसे तेज़ रखना और उस इंफ्रास्ट्रक्चर के रखरखाव से बचना था जो ऐसे कंटेंट के लिए हो जिसकी ज़रूरत केवल तभी पड़ती है जब मैं कोई टूल जोड़ता हूँ या अपडेट करता हूँ। मैंने एक static-first स्टैक चुना: साइट जनरेशन के लिए Astro, स्ट्रक्चर्ड डेटा के लिए TypeScript, और डिप्लॉयमेंट के लिए Cloudflare Workers। इसका परिणाम एक ऐसी साइट है जो तुरंत लोड होती है, जिसे होस्ट करने में लगभग कोई खर्च नहीं आता, और जिसमें किसी डेटाबेस एडमिनिस्ट्रेशन की आवश्यकता नहीं होती।
डायरेक्टरी के लिए Static-First क्यों सही है
कई वेब ऐप्स डिफ़ॉल्ट रूप से सर्वर रेंडरिंग या सिंगल-पेज आर्किटेक्चर का उपयोग करते हैं क्योंकि वे सुरक्षित और आधुनिक विकल्प लगते हैं। लेकिन हर साइट को हर रिक्वेस्ट पर डायनेमिक यूजर इनपुट नहीं मिलता है। Social Tools List एक read-heavy रिसोर्स है। तुलनात्मक डेटा तब बदलता है जब मैं कोई अपडेट पुश करता हूँ, न कि तब जब कोई विज़िटर पेज को रिफ्रेश करता है। HTML को पहले से रेंडर करने से एज (edge) पर डेटाबेस क्वेरीज़, ऑन-द-फ्लाई टेम्पलेट कंपाइलेशन, या ब्राउज़र में हाइड्रेशन ओवरहेड की आवश्यकता समाप्त हो जाती है। मैं बिल्ड टाइम पर साइट जनरेट करता हूँ, स्टैटिक फाइलों को डिप्लॉय करता हूँ, और एक लाइटवेट वर्कर को रैपर संभालने देता हूँ। इससे रिस्पॉन्स टाइम कम रहता है और रनटाइम फेलियर की एक पूरी श्रेणी खत्म हो जाती है।
डेटा को डेटाबेस में नहीं, TypeScript में स्टोर करें
मैं डेटाबेस का उपयोग नहीं करता हूँ। डायरेक्टरी में प्रत्येक टूल को एक slug, name, domain और समर्थित workflows के एक array वाले TypeScript ऑब्जेक्ट के रूप में परिभाषित किया गया है। एक सामान्य एंट्री ऐसी दिखती है:
{
slug: 'buffer',
name: 'Buffer',
domain: 'buffer.com',
workflows: ['scheduling', 'analytics']
}
साइट बनाने वाली भाषा में ही डेटा स्टोर करने के दो तत्काल लाभ हैं। पहला, पुल रिक्वेस्ट (pull requests) कंटेंट रिव्यू बन जाती हैं। जब मैं कोई टूल जोड़ता हूँ, तो diff सटीक फ़ील्ड और वैल्यू दिखाता है, और एक टीम का साथी CMS इंटरफ़ेस सीखे बिना ही टाइपो या गलत डोमेन को पहचान सकता है। दूसरा, TypeScript कंपाइलर हर रिकॉर्ड के स्ट्रक्चर को लागू करता है। यदि मैं slug शामिल करना भूल जाता हूँ या workflow key की स्पेलिंग गलत लिखता हूँ, तो खराब डेटा पेज तक पहुँचने से पहले ही बिल्ड फेल हो जाता है।
एक डेटाबेस माइग्रेशन, कनेक्शन स्ट्रिंग्स, कैशिंग रणनीतियों और बैकअप रूटीन जैसी चीज़ें जोड़ देगा। कुछ सौ एंट्रीज़ वाली ऐसी डायरेक्टरी जिसे मैं मैन्युअल रूप से मेंटेन करता हूँ, उसके लिए यह ओवरहेड केवल एक बोझ है। TypeScript मॉड्यूल्स में स्टैटिक डेटा इस मॉडल के लिए सबसे सस्ता और सही विकल्प है। यहाँ "सही" वाला हिस्सा महत्वपूर्ण है। यह केवल पैसे बचाने के बारे में नहीं है; यह उन एब्स्ट्रैक्शन लेयर्स को हटाने के बारे में है जो उन समस्याओं को हल करती हैं जो मेरे पास हैं ही नहीं।
राउटिंग और रेंडरिंग के लिए Astro का उपयोग करें
Astro एक सिंगल डायनेमिक रूट से प्रत्येक टूल के लिए एक HTML पेज जनरेट करता है। मैं एक लेआउट कंपोनेंट परिभाषित करता हूँ, और Astro स्वचालित रूप से प्रत्येक एंट्री के लिए मेटाडेटा, हेडिंग्स और स्ट्रक्चर्ड डेटा तैयार कर देता है। क्योंकि वही डेटासेट मुख्य इंडेक्स, वर्कफ़्लो कैटेगरी हब और व्यक्तिगत डिटेल पेजों को चलाता है, इसलिए इस बात की कोई संभावना नहीं है कि होम पेज पर कोई कार्ड डिटेल पेज की तुलना में अलग विवरण दिखाए। पारंपरिक CMS सेटअप में, आप अक्सर 'ड्रिफ्ट' (drift) देखते हैं: API एक वर्शन लौटाता है, कैश दूसरा, और क्लाइंट-साइड रेंडर तीसरा। सिंगल सोर्स ऑफ ट्रुथ (single source of truth) से स्टैटिक जनरेशन इसे रोकता है।
Astro का आइलैंड आर्किटेक्चर (island architecture) पूरे पेज को JavaScript से भारी किए बिना छोटे इंटरैक्टिव हिस्से जोड़ना भी आसान बनाता है। साइट स्टैटिक HTML के रूप में आती है, और केवल फ़िल्टरिंग स्क्रिप्ट ही DOM के अपने विशिष्ट हिस्से को हाइड्रेट करती है। पूरे डॉक्यूमेंट को रैप करने वाला कोई फ्रेमवर्क रनटाइम नहीं होता है। Astro पेज मेटाडेटा को भी प्राथमिकता देता है। प्रत्येक टूल पेज को सीधे TypeScript रिकॉर्ड से प्राप्त अपना स्वयं का title tag और meta description मिलता है, इसलिए मुझे किसी अलग प्लगइन या head मैनेजमेंट लाइब्रेरी की आवश्यकता नहीं होती है।
बिना किसी फ्रेमवर्क के फ़िल्टरिंग
सर्च और फ़िल्टरिंग अक्सर डेवलपर्स को React, Vue, या किसी भारी स्टेट मैनेजमेंट लाइब्रेरी को इंस्टॉल करने के लिए प्रेरित करती है। मैंने इसका विरोध किया। Astro सर्वर पर पूरी लिस्ट को सादे HTML के रूप में रेंडर करता है। एक छोटा सा vanilla JavaScript स्क्रिप्ट, जो एक किलोबाइट से भी कम है, ब्राउज़र में चलता है और वर्कफ़्लो टैग या टेक्स्ट मैच के आधार पर लिस्ट आइटम्स की display प्रॉपर्टी को टॉगल करता है।
Serving the complete markup sounds inefficient if you come from an API-driven background. But consider the overhead of a typical dynamic approach. The browser downloads a JavaScript bundle, hydrates a component tree, calls an endpoint, waits for JSON, and then renders rows. For a directory that lists fewer than one hundred tools, that ritual is slower and less reliable than hiding divs that are already in the document. My script attaches event listeners to filter buttons, reads a data-workflow attribute on each row, and sets non-matches to hidden. The operation takes milliseconds.
Because the list is present in the initial HTML, the site is usable without JavaScript. Search engine crawlers see every link and every description. Users on slow networks or with script blockers still get the full directory. The filtering is an enhancement, not a gate.
Sitemaps and Robots as Code
Sitemaps and robots.txt are not afterthoughts written by hand. They are Astro routes that consume the same dataset and URL helpers as
