डेवलपमेंट नोट्स

विज़ुअल नॉवेल तस्वीरों का एक समूह है। Builder इतना जटिल क्यों हो गया?

Fibber नाम का छोटा प्रोटोटाइप सहयोग, संस्करण आधारित प्रकाशन और एक साझा स्टोरी runtime वाले वितरित प्लेटफ़ॉर्म में कैसे बदला।

बाहर से विज़ुअल नॉवेल लगभग मामूली लगता है: एक पृष्ठभूमि, पारदर्शिता वाला पात्र, टेक्स्ट बॉक्स, अगले दृश्य तक ले जाने वाले कुछ विकल्प और थोड़ा संगीत। जब मैंने पहला संस्करण बनाना शुरू किया, तब मैं भी इसे ठीक इसी तरह देखता था।

मुझे अब भी लगता है कि इसका मूल सरल है। आज, खासकर AI की मदद से, लगभग कोई भी डेवलपर विज़ुअल नॉवेल प्लेयर बना सकता है। कठिनाई तब शुरू होती है जब लक्ष्य केवल एक कहानी बनाना नहीं, बल्कि ऐसा साधन बनाना हो जिसमें कोई दूसरा व्यक्ति, शायद कोई बच्चा भी, अपनी कहानी बना, जाँच, प्रकाशित और लगातार विकसित कर सके।

पहले संस्करण का केवल एक काम था

Romergo का नाम Romergo होने से पहले वह Fibber था। वह जुड़े हुए दृश्यों से एक क्वेस्ट बनाता था, मुझे उनमें टेक्स्ट और तस्वीरें भरने देता था और शाखाओं वाले विकल्पों का समर्थन करता था। स्टैक TypeScript, React, Strapi और Ant Design था।

उस संस्करण ने अपना काम किया। फ्लो ग्राफ ने कहानी को दिखाई देने योग्य बनाया, दृश्य संपादित किए जा सकते थे और परिणाम का पूर्वावलोकन किया जा सकता था। प्रोटोटाइप के लिए इतना पर्याप्त था। असली समस्या दिखाने के लिए भी इतना पर्याप्त था।

पहली असली रुकावट कोड नहीं थी

जब हमने एक वास्तविक क्वेस्ट में टेक्स्ट और तस्वीरें भरना शुरू किया, तो दस मिनट का दृश्य तैयार करने में लगभग पूरा दिन लग सकता था। दृश्य बनाएँ। पृष्ठभूमि अपलोड करें। पात्र अपलोड करें। उन्हें रखें। संवाद जोड़ें। अगला दृश्य जोड़ें। फिर दोहराएँ।

इसका कुछ हिस्सा इंटरफ़ेस की समस्या था। मैंने UX बेहतर किया, अपलोड तेज किए और प्रकाशन को अधिक भरोसेमंद बनाया। लेकिन सबसे बड़ी लागत जस की तस रही: हर छोटी कार्रवाई अब भी किसी व्यक्ति को हाथ से करनी पड़ती थी।

अगर दो लोग एक साथ बना सकें तो?

पहला उत्तर सरल था: अगर एक व्यक्ति रुकावट है, तो कई लोगों को एक ही कहानी पर काम करने दें। मैंने Liveblocks से शुरुआत की, उस मॉडल से सीखा और बाद में Yjs को केंद्र में रखकर अपनी सहयोग परत की ओर बढ़ा।

नीचे का प्रयोग दो एडिटर विंडो को साथ बदलते हुए दिखाता है। इसके भीतर उत्पाद की सोच में बड़ा बदलाव है: संपादन अलग-अलग फ़ॉर्म सबमिशन के बजाय साझा दस्तावेज़ के अपडेट बन जाते हैं। यहीं से उपस्थिति, दोबारा जुड़ना, टकराव संभालना, अनुमतियाँ और परियोजना के हमेशा जीवित रहने की अपेक्षा आती है।

हर उपयोगी शॉर्टकट अंततः एक सीमा बन गया

Strapi जल्दी backend पाने का शानदार तरीका था, लेकिन कहानी की हर नई विशेष सुविधा CMS से थोड़ा कम CMS जैसा व्यवहार माँगती थी। Ant Design ने पहले इंटरफ़ेस को गति और एकरूपता दी, फिर धीरे-धीरे उत्पाद को किसी और की विज़ुअल प्रणाली में बाँधने लगा।

बाद का Remix आधारित serverless संस्करण एक महत्वपूर्ण कदम था। फिर भी application, media और deployment को जोड़ने के मेरे तरीके ने वह क्षैतिज स्वतंत्रता नहीं दी जिसकी उत्पाद को जरूरत होने लगी थी। इनमें से कोई चुनाव गलती नहीं था। हर चुनाव ने अगली सीमा खोजने के लिए समय दिया।

तस्वीरें अटैचमेंट नहीं हैं। वे इंफ्रास्ट्रक्चर हैं।

मीडिया अपने आप में एक सीख बन गया। कहानी की तस्वीर एक बार अपलोड हो, जरूरत पर बदली जाए, सुरक्षित रखी जाए और दुनिया के किसी भी खिलाड़ी तक जल्दी पहुँचे। उसे बढ़ते application server के साथ रखने से backend और भारी हुआ, इसलिए पहला अलग समाधान Cloudinary था।

एक शाम dashboard में मैंने देखा कि एक उपयोगकर्ता ने वही तस्वीर सैकड़ों बार अपलोड कर लगभग 500 MB खर्च कर दिए थे। मेरे आपातकालीन सुधार ने image hash मिलाकर duplicates रोके। यह चला, लेकिन rate limits और quotas उस व्यवहार को सीधे रोकते। बड़ा आश्चर्य bandwidth था: एक शाम की testing मुफ्त सीमा का दस प्रतिशत से अधिक खा सकती थी।

उस घटना ने मॉडल बदल दिया। मीडिया अब दृश्य का एक field नहीं रह सकता था। उसे storage, deduplication, delivery, caching और access की अपनी pipeline चाहिए थी।

आज वह सरल विचार कैसा दिखता है

आज का Romergo Builder को player से अलग रखता है, लेकिन दोनों एक ही story runtime का उपयोग करते हैं। editor का preview और प्रकाशित playthrough समान नियम मानते हैं, इसलिए contract drift पैदा करना बहुत कठिन है।

Yjs सहयोगियों के बीच संपादन योग्य project को sync करता है। प्रकाशन story data और media का जाँचा हुआ snapshot बनाता है, इसलिए creators उस version को चुपचाप बदले बिना draft पर काम जारी रख सकते हैं जिसे खिलाड़ी चला रहे हैं। API Hono पर है, interface shadcn और Radix primitives का उपयोग करता है, और cloud layer distributed coordination, object storage और CDN delivery देता है।

यही shared runtime अब कहानी को browser और PWA, Telegram और synchronized Discord अनुभव तक ले जाता है। versions की compatibility, offline behavior और multiplayer state अब page के आसपास के side effects नहीं, अपने आप में product systems हैं।

वर्तमान आर्किटेक्चर

एक संपादन योग्य कहानी। एक प्रकाशित contract।

Romergo की वर्तमान आर्किटेक्चर का सामान्य दृश्य।

1. संपादन योग्य project

  • Builder UI: दृश्य · flow · media
  • AI / MCP: प्रमाणित editing operations
  • Realtime / Yjs: Durable Objects · साझा working document
  • Editor API: CAS writes · draft materialization
  • Draft runtime snapshot: PublishedQuestLocalizedContentV2 · D1 / R2
  • Draft media: R2 objects · D1 metadata

2. संस्करण आधारित प्रकाशन

  • प्रकाशन जाँच: Runtime schema · लेखक पुष्टि · media की मौजूदगी
  • अपरिवर्तनीय प्रकाशन vN: Runtime snapshot · copy और remap किया media
  • दृश्यता contract: सार्वजनिक · unlisted · private

3. एक execution contract

  • Draft snapshot: नवीनतम संपादन योग्य स्थिति
  • प्रकाशन vN: स्थिर player state
  • Shared player-runtime: दृश्य · transitions · conditions · variables · saves
  • Builder preview: उसी engine में draft चलाता है

4. प्लेबैक चैनल

  • Web / PWA: Browser player
  • Telegram Mini App: Embedded player
  • Discord Activity: सिंक्रोनाइज़्ड समूह खेल

5. प्लेटफ़ॉर्म इंफ्रास्ट्रक्चर

  • Clerk + OAuth: पहचान और MCP access
  • Hono Workers: API और MCP services
  • Cloudflare D1: Projects · versions · metadata
  • Cloudflare R2: Media · बड़े runtime snapshots
  • Durable Objects: Yjs rooms · Discord sessions
  • खिलाड़ी की प्रगति: D1 sync · local offline queue

नॉवेल अब भी सिर्फ तस्वीरें ही है

मज़ेदार बात यह है कि शुरुआती धारणा बची रही। विज़ुअल नॉवेल अब भी पृष्ठभूमि, पात्र, टेक्स्ट, विकल्प और ध्वनि है। Romergo जटिल हुआ क्योंकि इस सरल केंद्र के आसपास सब कुछ भरोसेमंद होना था: सहयोग, मीडिया, प्रकाशन, संस्करण, offline play और एक ही कहानी अनुभव करने के कई तरीके।

इस विकास ने मुझे एक बात सिखाई है: केवल अंतिम स्क्रीन दिखाने वाले कोड को नहीं, मनुष्य के पूरे रास्ते को मापो। Player को पाँच मूल तत्व चाहिए हो सकते हैं। किसी विचार को पूरी, खेलने योग्य कहानी बनाने में मदद करने वाले उत्पाद को एक system चाहिए।

डेव ब्लॉग पर वापस जाएँ