2026-இல் ஆரம்பத்திலிருந்தே ஒரு தனிப்பயன் (custom) பிளாக்கை உருவாக்குவது என்பது ஒரு திட்டமிட்ட முடிவு. பெரும்பாலான எழுத்தாளர்கள் ஒரு ஹோஸ்டட் பிளாட்ஃபார்மைத் தேர்ந்தெடுத்துவிட்டுத் தொடர்கிறார்கள். ஆனால், நான் எனது தொழில்நுட்ப பிளாக்கை Astro கொண்டு மீண்டும் உருவாக்கத் தீர்மானித்தேன், ஏனெனில் ஸ்டேக்கின் (stack) ஒவ்வொரு அடுக்கையும் நான் சொந்தமாக வைத்திருக்க விரும்பினேன், மேலும் ஒரு ஸ்டேடிக் தளம் (static site) வெறும் வித்தியாசமாக இல்லாமல், உண்மையில் வேகமானதாக மாறுவதற்குத் தேவையான முறைகளைக் கற்றுக்கொள்ள விரும்பினேன். இதன் விளைவாக, ஜப்பானிய மற்றும் ஆங்கில உள்ளடக்கங்களை வழங்கும் ஒரு இருமொழித் தளம் உருவானது; இது இயல்பாகவே பூஜ்ஜிய ஜாவாஸ்கிரிப்டை (zero JavaScript) வழங்குகிறது, மேலும் பார்வையாளரின் பிரவுசருக்குப் பதிலாக அனைத்துச் சிக்கல்களையும் எனது கணினியிலேயே வைத்திருக்கிறது.
இது சிறப்பாகச் செயல்பட உதவிய ஐந்து முறைகள் இதோ.
Zod மூலம் Content Collections
Astro-வின் Content Collections என்பது Markdown கோப்புகளை ஃபோல்டர்களாக அடுக்கி வைப்பதோடு மட்டும் நின்றுவிடுவதில்லை. அவை உங்கள் உள்ளடக்கத்திற்கும் உங்கள் குறியீட்டிற்கும் (code) இடையே ஒரு ஒப்பந்தத்தை உறுதி செய்கின்றன. ஒவ்வொரு கட்டுரைத் தொகுப்பிற்கும் (article collection) நான் ஒரு Zod schema-வை இணைத்துள்ளேன், இதன் மூலம் ஒரு பக்கம் ரெண்டர் (render) ஆவதற்கு முன்பே பில்ட் (build) நிலை frontmatter-ஐச் சரிபார்க்கிறது.
இந்த schema language என்ற புலத்தை (field) கோருகிறது, இது ja அல்லது en ஆகிய இரண்டு மதிப்புகளை மட்டுமே ஏற்கும். வாசகர் எந்த மொழியைப் பெறுவார் என்பதில் எந்தக் குழப்பமும் இருக்காது. மொழிபெயர்ப்புகளை இணைக்க நான் ஒரு pair புலத்தையும் சேர்த்துள்ளேன். நான் Astro பற்றிய ஒரு பதிவை ஜப்பானிய மொழியில் வெளியிட்டு, பின்னர் அதை ஆங்கிலத்தில் மொழிபெயர்த்தால், இரண்டு கோப்புகளும் ஒரே pair ID-யைப் பகிர்ந்து கொள்ளும். இது ஒரு மொழி மாற்றும் வசதியை (language switcher) உருவாக்குவதை மிக எளிதாக்குகிறது, ஏனெனில் அந்தத் தொடர்பு தரவிலேயே (data) தெளிவாக உள்ளது, கோப்புப் பெயர்களில் இருந்து ஊகிக்கப்படுவதில்லை.
தேதிகள் Markdown frontmatter-லிருந்து சரங்களாக (strings) வருகின்றன, எனவே schema அவற்றை தானாகவே உண்மையான Date ஆப்ஜெக்ட்களாக மாற்றுகிறது. இது எனது பக்க டெம்ப்ளேட்களுக்குள் (page templates) சரங்களை கையாளும் (string-mangling) சிக்கலைத் தவிர்க்கிறது. இருப்பினும், மிக முக்கியமான நன்மை அதன் தோல்வி முறை (failure mode) ஆகும். ஒரு கோப்பில் தேவையான புலம் இல்லையென்றாலோ அல்லது தவறான மொழி குறியீட்டைப் பயன்படுத்தினாலோ, பில்ட் உடனடியாகத் தெளிவான பிழையுடன் நின்றுவிடும். டிப்ளாய்மென்ட் (deployment) செய்த பிறகு ஒரு உடைந்த லேஅவுட் அல்லது மௌனமான 404 பிழையைக் கண்டறிவதற்குப் பதிலாக, நான் அதை எனது டெர்மினலிலேயே சரிசெய்துவிட முடியும்.
கட்டுரை மாற்றும் செயல்முறை (Article Conversion Pipeline)
நான் முதல் நாளிலிருந்தே ஒவ்வொரு பதிவையும் இந்த புதிய வடிவத்தில் எழுதவில்லை. பல ஆண்டுகால உள்ளடக்கங்கள் Zenn மற்றும் Dev.to தளங்களில் இருந்தன, ஒவ்வொன்றும் அதன் சொந்தத் தனித்துவங்களையும் பிரத்யேகமான தொடரியல்களையும் (proprietary syntax) கொண்டிருந்தன. அவற்றை நகலெடுத்துப் பார்த்து (copy-pasting) கைமுறையாகச் சரிசெய்வதற்குப் பதிலாக, கட்டுரைகளின் முழு தொகுப்பையும் நிலையான Markdown-ஆக மாற்றும் ஒரு TypeScript ஸ்கிரிப்டை நான் எழுதினேன்.
Zenn தளம் குறிப்புகள் மற்றும் எச்சரிக்கைகளுக்காகத் தனிப்பயன் callout தொடரியலைப் பயன்படுத்துகிறது. எனது ஸ்கிரிப்ட் அவற்றை அர்த்தமுள்ள (semantic) HTML aside டேக்குகளாக மாற்றுகிறது, இதனால் அவை தளத்தின் அனைத்துப் பகுதிகளிலும் சீராகத் தோன்றும். Dev.to தளம் எம்பெட்கள் (embeds) மற்றும் சிறப்பு பிளாக்குகளுக்காக Liquid டேக்குகளைப் பயன்படுத்துகிறது. இந்தச் செயல்முறை அவற்றை எங்கு வேண்டுமானாலும் செயல்படும் சாதாரண Markdown இணைப்புகளாக மாற்றுகிறது.
சில பதிவுகளில் அசல் தளத்திற்கு மட்டுமே உரிய கூடுதல் தகவல்கள் இருக்கலாம், உதாரணமாக Medium paywalls பற்றிய அறிவிப்பு அல்லது Zenn-குறிப்பிட்ட படப் பாதை (image path). அவற்றை நான் HTML கமெண்ட்களில் (comments) சுற்றிக் கொள்கிறேன், இதனால் மாற்றத்தின் போது (migration) அவற்றை நீக்க முடியும். ஸ்கிரிப்ட் கோப்புகளை வரி வரியாகச் செயலாக்குகிறது, ஆனால் அது குறியீட்டு எல்லைகளை (code boundaries) மதிக்கிறது. ஒரு fenced code block-ஐக் கண்டறியும்போது, அது மாற்ற விதிகளைத் தவிர்த்துவிடுகிறது. ஒரு தொழில்நுட்பப் பிளாக்கின் நோக்கத்தையே சிதைத்துவிடும் வகையில் ஒரு தொடரியல் மாதிரியை (syntax sample) மாற்றுவது சரியாக இருக்காது, எனவே வரி வரியாகப் பகுப்பாய்வு செய்யும் இந்த ஸ்கிரிப்ட், code block-களைத் தொட முடியாத பகுதிகளாகக் கருதுகிறது.
இப்போது ஒரே ஒரு கட்டளையை (command) இயக்குவதன் மூலம், ஒரு லிங்க் அல்லது callout கூட உடையாமல் பல ஆண்டுகால எழுத்துக்களை மீண்டும் வெளியிட முடியும்.
பில்ட்-நேர OGP பட உருவாக்கம் (Build-Time OGP Image Generation)
சமூகப் பகிர்வுப் படங்கள் (Social sharing images) பொதுவாகப் பின்னாளில் கவனிக்கப்படுபவை. நீங்கள் அவற்றை கைமுறையாக வடிவமைக்கலாம் அல்லது தேவைப்படும்போது கார்டுகளை உருவாக்கும் ஒரு கனமான ரன்டைம் சேவையை (runtime service) நிறுவலாம். எனக்கு இவை இரண்டுமே வேண்டாம். இந்தத் தளத்தில் உள்ள ஒவ்வொரு Open Graph படமும் பில்ட் செய்யும் போதே உருவாக்கப்படுகிறது, இதனால் பார்வையாளர்கள் ஒரு நிலையான PNG-ஐக் குறிக்கும் ஒரு லேசான img டேக்கை மட்டுமே பெறுவார்கள்.
நான் Satori-யைப் பயன்படுத்துகிறேன், இது JSX மார்க்கப் (markup) குறியீட்டை எடுத்து அதை SVG-ஆக மாற்றுகிறது. இதன் வெளியீடு துல்லியமாகவும், கணிக்கக்கூடியதாகவும் மற்றும் டெம்ப்ளேட் செய்வதற்கு எளிதாகவும் இருக்கும். உண்மையான மேம்பாடு (optimization) எழுத்துரு கையாளுதலில் (font handling) இருந்து வந்தது. ஒரு முழுமையான ஜப்பானிய இணைய எழுத்துரு (web font) எளிதாக ஐந்து மெகாபைட்டிற்கும் அதிகமாக இருக்கலாம். அதை பில்ட் செய்யும் போது ஏற்றுவது என்பது ஒரு விஷயமென்றால், ஒரு பிரவுசரை அதைத் தரவிறக்கச் சொல்வது என்பது அபத்தமானது.
அதற்குப் பதிலாக, நான் Google Fonts subsetting முறையைப் பயன்படுத்துகிறேன். ஸ்கிரிப்ட் ஒரு குறிப்பிட்ட பதிவின் தலைப்பு உரையை ஆய்வு செய்து, அந்த உரையை உருவாக்கத் தேவையான துல்லியமான குறியீட்டுத் தொகுப்பை (glyph set) மட்டுமே கோருகிறது. ஒரு தலைப்பு நாற்பது தனித்துவமான ஜப்பானிய எழுத்துக்களைப் பயன்படுத்தினால், அந்த நாற்பது எழுத்துக்கள் மட்டுமே இணையம் வழியாகப் பயணிக்கும். இதனால் பில்ட் வேகம் குறையாது, மேலும் அந்தத் தொகுப்பு துல்லியமாக இருப்பதால், ரெண்டர் செய்யப்பட்ட படத்தில் உடைந்த எழுத்துக்களும் (broken tofu blocks) தெரியாது. எதுவும் ரன்டைம் வாய்ப்புகளின் (runtime chance) அடிப்படையில் விடப்படவில்லை.
Tailwind டோக்கன்கள் மூலம் டார்க் மோட் (Dark Mode via Tailwind Tokens)
ஒவ்வொரு உறுத்தையும் dark: utility கிளாஸ்களால் அலங்கரிக்க நான் மறுத்துவிட்டேன். அந்த அணுகுமுறை சரியாகச் செயல்படாது மற்றும் உங்கள் மார்க்கப் (markup) குறியீட்டில் தேவையற்ற இரைச்சலை (noise) உண்டாக்கும். நான் வண்ண டோக்கன்களையே (color tokens) மறுவரையறை செய்தேன், இதனால் செயலில் உள்ள தீம் (active theme) பொறுத்து ஒரே கிளாஸ் பெயர் வெவ்வேறு மதிப்புகளை வழங்கும்.
நான் ஒவ்வொரு மேற்பரப்பு (surface) மற்றும் உரை நிறத்திற்கும் (text color) CSS custom properties-ஐப் பயன்படுத்துகிறேன். Light mode-இல், --color-white என்பது #ffffff-ஐக் குறிக்கும். Dark mode-இல், அதே மாறிப் பெயர் (variable name) கருப்புக்கு நெருக்கமான ஒரு மதிப்பைக் குறிக்கும். எனது HTML முற்றிலும் சுயாதீனமாக (agnostic) இருக்கும். ஒரு கார்டு (card), பகல் அல்லது இரவு நேரத்தைப் பற்றி கவலைப்படாமல் bg-ui-surface மற்றும் text-ui-primary-ஐப் பயன்படுத்த முடியும். தீம் மாற்றம் (theme switch) ரூட் (root) மட்டத்தில் மாறி வரையறைகளை (variable definitions) மாற்றுகிறது, மேலும் முழு இடைமுகமும் (interface) உடனடியாகப் பதிலளிக்கிறது.
இந்த அணுகுமுறையில் உள்ள ஒரே ஆபத்து, stylesheets ஏற்றப்படுவதற்கு முன்பு வெளிச்சமான உள்ளடக்கம் மின்னல் போலத் தெரிவதாகும் (flash). இதை ஆவணத்தின் head-இல் ஒரு சிறிய inline script மூலம் நான் தீர்த்தேன். இது முதல் முறை திரையில் தோன்றுவதற்கு (first paint) முன்பே இயங்கி, localStorage மற்றும் கணினி விருப்பத்தேர்வைச் (system preference) சரிபார்த்து, சரியான data attribute-ஐ உடனடியாக அமைக்கிறது. இந்த script சில மில்லி விநாடிகள் மட்டுமே render செய்வதைத் தடுப்பதால், dark mode செயல்படுவதற்கு முன்பு பார்வையாளர் ஒரு திடுக்கிடும் வெள்ளை நிறத் தோற்றத்தை (white burst) பார்ப்பதில்லை.
Island Architecture மற்றும் Zero-JS
ஒரு பக்கம் static HTML ஆகத் தொடங்க வேண்டும் என்பதே Astro-வின் அடிப்படைத் தத்துவமாகும். ஒரு செயல்பாடு (interaction) உண்மையாகவே தேவைப்படும்போது மட்டுமே JavaScript நுழைகிறது. நான் அதைத் தீவிரமாக எடுத்துக்கொண்டேன்.
உலகளாவிய மெனு (global menu) மற்றும் தீம் டொகிள் (theme toggle) ஆகியவற்றிற்கு நான் React-ஐத் தவிர்த்தேன். இவை இரண்டும் ஒரு தனி மாட்யூலில் (module) இருக்கும் சிறிய அளவிலான vanilla JavaScript மூலம் கையாளப்படுகின்றன. இதில் hydration overhead, virtual DOM diffing அல்லது பதிவிறக்கம் செய்ய வேண்டிய framework runtime போன்ற சுமைகள் இல்லை.
உரையில் இருந்து வரைபடங்களை (diagrams) உருவாக்க நான் பயன்படுத்தும் ஒரே கனமான library Mermaid.js ஆகும். அதை உலகளாவிய ரீதியில் (globally) இறக்குமதி செய்வதற்குப் பதிலாக, ஒரு Intersection Observer-க்குள் நான் அதைச் சுற்றியுள்ளேன் (wrapped). அந்த observer வரைபடக் கொள்கலன்களைக் (diagram containers) கண்காணிக்கிறது. ஒரு பயனர் ஒன்றிற்கு சில நூறு பிக்சல்களுக்குள் ஸ்க்ரோல் செய்யும்போது, script அந்த Mermaid மாட்யூலைத் தானாகவே செலுத்தி (injects) வரைபடத்தை உருவாக்குகிறது. ஒரு பதிவில் வரைபடங்கள் இல்லையென்றால், அந்த library நெட்வொர்க்கைத் தொடாது. ஆரம்பக்கட்ட பக்கப் பதிவேற்றம் (initial page load) லேசாக இருக்கும், மேலும் வாசகர் உண்மையில் பார்ப்பதற்கே பிரவுசர் செலவிடும்.
Build-First மனநிலை
ஒவ்வொரு முறையையும் இணைக்கும் அடிப்படைத் தத்துவம் எளிமையானது: ஒரு வேலையை build செய்யும் போதே செய்ய முடியும் என்றால், அங்கேயே செய்துவிடுங்கள். தளம் பயன்பாட்டுக்கு வரும் முன் (deploys), Zod மூலம் உங்கள் தரவைச் சரிபார்க்கவும் (validate). கோரிக்கை நேரத்தில் (request time) செய்வதற்குப் பதிலாக, பிரத்யேகத் தளத் தொடரியலை (proprietary platform syntax) முன்கூட்டியே மாற்றவும். ஒரு சர்வரைத் தொடங்குவதற்குப் பதிலாக, சமூகப் படங்களை (social images) static கோப்புகளாக மாற்றவும். ஒவ்வொரு கிளையன்ட்டிற்கும் லாஜிக்கை (logic) அனுப்புவதற்குப் பதிலாக, tokens மூலம் தீம் நிறங்களைத் தீர்மானிக்கவும். பயனர் உண்மையில் தேவைப்படும் வரை கனமான JavaScript-ஐத் தள்ளிப்போடவும் (defer).
சிக்கல்களை build படிநிலைக்குத் தள்ளுவது (pushing complexity leftward), runtime-ஐக் கணிக்கக்கூடியதாகவும், payload-ஐச் சிறியதாகவும் மற்றும் பராமரிப்புச் சுமையை (maintenance burden) நிர்வகிக்கக்கூடியதாகவும் வைக்கிறது. தளம் வேகமாக இருப்பது ஏதோ ஒரு தனிப்பட்ட தந்திரத்தினால் அல்ல, மாறாக பார்வையாளரின் பிரவுசருக்குள் நடப்பவை மிகக் குறைவு என்பதால் தான். 2026-இல் ஒரு static architecture-ஐத் தேர்ந்தெடுப்பதன் உண்மையான பலன் இதுதான்.
