<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Nikolay Suslov</title>
    <description>The latest articles on Forem by Nikolay Suslov (@nikolaysuslov).</description>
    <link>https://forem.com/nikolaysuslov</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F327950%2Fa9df0cc7-df85-4fac-878e-fcdf85929b50.jpeg</url>
      <title>Forem: Nikolay Suslov</title>
      <link>https://forem.com/nikolaysuslov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nikolaysuslov"/>
    <language>en</language>
    <item>
      <title>Krestianstvo Electric Lazy Reflector for Croquet VM</title>
      <dc:creator>Nikolay Suslov</dc:creator>
      <pubDate>Mon, 20 May 2024 04:04:35 +0000</pubDate>
      <link>https://forem.com/nikolaysuslov/krestianstvo-electric-lazy-reflector-for-croquet-vm-4k93</link>
      <guid>https://forem.com/nikolaysuslov/krestianstvo-electric-lazy-reflector-for-croquet-vm-4k93</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/NikolaySuslov/krestianstvo-electric" rel="noopener noreferrer"&gt;Krestianstvo Electric&lt;/a&gt; introduces the Lazy Reflector for Croquet VM. This becomes possible due to implementing it in &lt;a href="https://github.com/hyperfiddle/electric" rel="noopener noreferrer"&gt;Clojure Electric&lt;/a&gt; programming architecture involving continuous-time signals with lazy sampling and streaming DAGs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoh755cv65ok215nh81f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzoh755cv65ok215nh81f.gif" alt="Lazy Reflector" width="480" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All known Croquet implementations (including the &lt;a href="https://en.wikipedia.org/wiki/Croquet_Project" rel="noopener noreferrer"&gt;Smalltalk&lt;/a&gt;, &lt;a href="https://github.com/virtual-world-framework/vwf" rel="noopener noreferrer"&gt;VWF&lt;/a&gt;, &lt;a href="https://croquet.io/" rel="noopener noreferrer"&gt;Croquet OS&lt;/a&gt; and recent &lt;a href="https://multisynq.io/" rel="noopener noreferrer"&gt;Multisynq protocol&lt;/a&gt;) also OSS &lt;a href="https://play.krestianstvo.org/" rel="noopener noreferrer"&gt;Krestianstvo on Solid JS&lt;/a&gt; are involving discrete timestamp generator (aka Reflector server). The Reflector should produces periodic ticks (~25-50 ms) and also timestamps all external messages coming from the views, then replicates these messages back to all connected peers of some concrete session (Island). If Reflector will not produce any messages, the Croquet VM will be suspended, waiting for any. In simple words, Reflector periodic ticks are needed for any animated in time simulation go forward in Croquet. But, the high frequency Reflector becomes redundant for simulations with slow rates for example or in the applications with no time-animated simulations at all.&lt;/p&gt;

&lt;p&gt;The Lazy Reflector is "ticking" and "time-stamping" only on demand, staying the most time idle and laziness - not producing any work at all! However it guarantees, that all connected peers will get just the same ticks and time stamped messages, without missing a single one! As it is based on backpressured Electric continuous lazy server clock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;actQueue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reset!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;!reflectorTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;e/server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e/system-time-ms&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That perfectly fits Croquet architecture, as in general the most application work is done locally by the clients themselves. That includes involving Future messages with temporal recursion that producing no network traffic at all (future messages never going to the Reflector).&lt;br&gt;&lt;br&gt;
Also Lazy Reflector ticks are now not added to the Croquet VM priority queue. They are only moving local virtual time forward, pulling lazy server clock on demand by the future messages.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r8gmulxqidt8v4ynj2k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r8gmulxqidt8v4ynj2k.gif" alt="Past &amp;amp; Present Virtual Time" width="480" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To try it in action, there are several example applications in &lt;a href="https://e.krestianstvo.org/" rel="noopener noreferrer"&gt;Krestianstvo Electric&lt;/a&gt;.&lt;br&gt;
Want to mention, that in the &lt;a href="https://e.krestianstvo.org/(krestianstvo.fiddles!%43ounter)/" rel="noopener noreferrer"&gt;Counter example&lt;/a&gt;, the button "Loop" is not triggering Reflector to start ticking periodically. The button send only one external message launching temporal recursion on all connected peers. Then future messages pull the lazy server clock with the sample rate defined in the future step amount (after every virtual 0.5 sec in future do :step).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight clojure"&gt;&lt;code&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;swap!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;!objData&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;update-in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;seloID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objID&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:x&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sendFutureMsg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;:name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:step,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="n"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;:objid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;objID&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source code is available on &lt;a href="https://github.com/NikolaySuslov/krestianstvo-electric" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>clojure</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Answering Common Questions about Krestianstvo SDK 4</title>
      <dc:creator>Nikolay Suslov</dc:creator>
      <pubDate>Wed, 28 Sep 2022 05:26:38 +0000</pubDate>
      <link>https://forem.com/nikolaysuslov/answering-common-questions-about-krestianstvo-sdk-4-1pep</link>
      <guid>https://forem.com/nikolaysuslov/answering-common-questions-about-krestianstvo-sdk-4-1pep</guid>
      <description>&lt;p&gt;Started writing documentation with answering common questions about &lt;a href="https://play.krestianstvo.org"&gt;Krestianstvo SDK 4&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Is it using the Smalltalk version of Croquet: &lt;a href="https://wiki.c2.com/?OpenCroquet"&gt;Squeak Open Croquet&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/OpenQwaq"&gt;Open Qwaq&lt;/a&gt;?
&lt;/h4&gt;

&lt;p&gt;No. Krestianstvo SDK 4 is entirely written in JavaScript and is running on top of JavaScript VM.&lt;br&gt;
Open Croquet architecture is used in &lt;a href="https://krestianstvo.org/sdk1/"&gt;Krestianstvo SDK 1&lt;/a&gt;. Open Qwaq architecture is used in &lt;a href="https://krestianstvo.org/sdk2/"&gt;Krestianstvo SDK 2&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Is it using &lt;a href="https://croquet.io"&gt;Croquet OS&lt;/a&gt; or any of croquet.io services written in JavaScript?
&lt;/h4&gt;

&lt;p&gt;No. Krestianstvo SDK 4 is introducing its own implementation of Croquet Application Architecture in JavaScript, based on &lt;a href="https://solidjs.com"&gt;Solid JS&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/adamhaile/S"&gt;S.js&lt;/a&gt; using Functional Reactive Programming (FRP). Also, that implementation is not limited just to the JavaScript language. Rust, Swift and Squeak Smalltalk versions are in work.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Is it using JavaScript version of Croquet known as &lt;a href="https://en.wikipedia.org/wiki/Virtual_world_framework"&gt;Virtual World Framework&lt;/a&gt;?
&lt;/h4&gt;

&lt;p&gt;Only implementations of Reflector server and Virtual Time are used and modified to suit FRP.&lt;br&gt;
Virtual World Framework provides its own unique implementation of Croquet Application Architecture based on prototypes, nodes and drivers. VWF architecture is used in &lt;a href="https://krestianstvo.org/sdk3/"&gt;Krestianstvo SDK 3&lt;/a&gt;. The 4th version of Krestianstvo SDK contains no elements of it.&lt;/p&gt;
&lt;h4&gt;
  
  
  4. Is it compatible with &lt;a href="https://croquet.io"&gt;Croquet OS&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Virtual_world_framework"&gt;Virtual World Framework&lt;/a&gt;?
&lt;/h4&gt;

&lt;p&gt;Not out-of-the-box. Although Croquet OS / VWF and Krestianstvo SDK 4 share the same original Open Croquet roots, some effort will be required in porting an application between their different implementations, alongside pros and cons.&lt;br&gt;
The application development (&lt;a href="https://codesandbox.io/s/krestianstvo-helloworld-pnimfu?file=/src/index.js"&gt;code example&lt;/a&gt;) with Krestianstvo SDK 4 is looked quite different, comparing to the  development in Croquet OS or VWF one's. Croquet OS and VWF Application Architecture is based on Model - View pattern, implemented in Class/Instance programming paradigm. In the contrary, Krestianstvo SDK 4 Application Architecture is based just on pure functions in form of Signals and Computations (Effects). Croquet OS uses pub/sub messaging for interconnecting Model/View instances. VWF is using drivers for that interconnection. In the contrary, Krestianstvo SDK 4 is using "glitchless" automatic dependency graph with a synchronous execution engine found in Solid JS and S.js&lt;/p&gt;
&lt;h4&gt;
  
  
  5. Do I need to run my own Reflector server to start developing with Krestianstvo SDK 4?
&lt;/h4&gt;

&lt;p&gt;No. You can use any of publicly available already running reflector servers. Like &lt;a href="https://time.krestianstvo.org"&gt;https://time.krestianstvo.org&lt;/a&gt; or &lt;a href="https://time.livecoding.space"&gt;https://time.livecoding.space&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  6. Can I run my own Reflector server?
&lt;/h4&gt;

&lt;p&gt;Yes, you can host your own &lt;a href="https://github.com/NikolaySuslov/lcs-reflector"&gt;Reflector server&lt;/a&gt; anywhere in LAN or WAN. Just point to it in the &lt;code&gt;&amp;lt;Selo/&amp;gt;&lt;/code&gt; component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Selo&lt;/span&gt;
    &lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;simple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;seloID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Simple&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;worlds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;worlds&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;fallbackWorld&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;EmptyWorld&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;reflectorHost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://url.to.my.reflector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or just use directly in Web Browser url with &lt;strong&gt;r&lt;/strong&gt; parameter: &lt;a href="https://play.krestianstvo.org/demo1?r=https://time.krestianstvo.org"&gt;https://play.krestianstvo.org/demo1?r=https://time.krestianstvo.org&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Does Reflector server used in Krestianstvo SDK 4 aware of a client's application logic or store any application state?
&lt;/h4&gt;

&lt;p&gt;No. Reflector server, that is used in Krestianstvo SDK 4 is fully conform the Croquet Application Architecture. Meaning, that Reflector server is used only for initial connection, ticking, stamping and reflecting the messages received from the clients with the data they want to share (e.g. 2D coords from a mouse movement). It knows nothing about application logic, and don't relay any data, that can be generated with a future messages locally on every synced client, running Croquet deterministic computations.&lt;/p&gt;

&lt;h4&gt;
  
  
  8. Can I use different Reflector servers at the same time for different worlds linked by Portals, but existed in one world/web page?
&lt;/h4&gt;

&lt;p&gt;Yes. When creating a Portal, just use url with &lt;strong&gt;r&lt;/strong&gt; parameter pointing to any other running reflector server.&lt;/p&gt;

&lt;h4&gt;
  
  
  9. Are Portals using iFrames to make inter-linked worlds?
&lt;/h4&gt;

&lt;p&gt;No. Portal is just a pure function in form of Solid JS component. Thus, portal can be used inside any other Solid JS component, with no need on creating the new JavaScript context and iFrame. You can freely create a stacks of portals and manipulate them as a single functional component, by passing props and sending messages through it.&lt;/p&gt;

&lt;h4&gt;
  
  
  10. Does Portals support linking to themselves?
&lt;/h4&gt;

&lt;p&gt;Yes. Portals are recursive. By default portal's recursion depth is set to &lt;strong&gt;2&lt;/strong&gt;. Use parameter &lt;strong&gt;d&lt;/strong&gt; in the url to set the depth manually.&lt;/p&gt;

</description>
      <category>solidjs</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Krestianstvo SDK 4 | Implementing Croquet and Recursive Portals on Solid JS</title>
      <dc:creator>Nikolay Suslov</dc:creator>
      <pubDate>Thu, 01 Sep 2022 04:42:02 +0000</pubDate>
      <link>https://forem.com/nikolaysuslov/krestianstvo-sdk-4-implementing-croquet-and-recursive-portals-on-solid-js-54ai</link>
      <guid>https://forem.com/nikolaysuslov/krestianstvo-sdk-4-implementing-croquet-and-recursive-portals-on-solid-js-54ai</guid>
      <description>&lt;p&gt;Let me introduce to you the new &lt;strong&gt;4th&lt;/strong&gt; version of &lt;strong&gt;&lt;a href="https://play.krestianstvo.org/"&gt;Krestianstvo SDK&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;The main feature of the 4th version is the full-featured implementation of the &lt;a href="https://croquet.io/"&gt;&lt;strong&gt;Croquet Application Architecture&lt;/strong&gt;&lt;/a&gt; in &lt;strong&gt;Functional Reactive Paradigm&lt;/strong&gt; using &lt;strong&gt;&lt;a href="https://www.solidjs.com/"&gt;SolidJS&lt;/a&gt; / &lt;a href="https://github.com/adamhaile/S"&gt;S.JS&lt;/a&gt;&lt;/strong&gt; and introduction of &lt;strong&gt;Recursive Portals&lt;/strong&gt;. The only parts, that stayed the same as in the 3rd version of Krestianstvo SDK are: Reflector and Virtual Time. Their implementations are based on the &lt;a href="https://github.com/virtual-world-framework/vwf"&gt;Virtual World Framework&lt;/a&gt;, thus they were just slightly modified to suit Functional Reactive Paradigm.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/742885266" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The 4th version of Krestianstvo SDK is distributed as a standalone &lt;a href="https://www.npmjs.com/package/krestianstvo"&gt;ESM module&lt;/a&gt; for JavaScript. It could be easily bundled with any &lt;a href="https://www.solidjs.com/"&gt;Solid JS&lt;/a&gt; or &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; web application being hosted and running just in the Cloud.&lt;/p&gt;

&lt;p&gt;The work on the 4th version was started in 2019, when I was working on &lt;a href="https://blog.krestianstvo.org/en/krestianstvo-luminary-for-open-croquet-architecutre-and-virtual-world-framework-in-peer-to-peer-web/"&gt;Luminary&lt;/a&gt; and introduced the Functional Reactive Streams into the Croquet application architecture. &lt;a href="https://blog.krestianstvo.org/en/collaborative-robots-rubiks-cube-lego-boost/"&gt;The project with Rubik’s Cube&lt;/a&gt; has shown, how Croquet gets a new look on Virtual Time and Promises inside actions, all backed by FRP. For example, the participants could delay the Virtual Time and observe their actions in virtual world in “slow motion”.&lt;/p&gt;

&lt;p&gt;Then in 2021 I participated in the first &lt;a href="https://browsersound.com/"&gt;Festival for Web based Music&lt;/a&gt;. At the festival me and artist Delia Ramos were creating the web art project — &lt;a href="https://concert.livecoding.space/"&gt;“THIS IS NOT A CONCERT”&lt;/a&gt;. In that project, an audience collaboratively explored the artwork inside virtual canvas space within multi-contextual / conceptual creative layers by touching the virtual objects, interacting or viewing through “filters” in Web Browser. The core object, that I needed to for that project was a Recursive Portal, that should work as a filter, portal to other virtual canvas spaces and also as a portal to itself.&lt;/p&gt;

&lt;p&gt;But, comparable to the original Smalltalk version of the Croquet, as in the Virtual World Framework and in the 3rd version of Krestianstvo SDK there are still lack of Portals, including dependence on global object Window. The &lt;a href="https://croquet.io/"&gt;Croquet.io&lt;/a&gt; has introduced Portals for the Web, by using sandboxed HTML iFrames (&lt;a href="https://davidasmith.medium.com/multiplane-portals-for-the-metaverse-a4b7af913e8e"&gt;Multiplane Portals for the Metaverse&lt;/a&gt;). But in Krestianstvo I wanted to implement Portals the same way as Croquet Smalltalk version does, as pure objects with an ability to make links to themselves, forming a Recursive Portals.&lt;/p&gt;

&lt;p&gt;Finally, I was lucky to do it just in pure JavaScript, thanks to Solid JS! To make these all happen, it demanded of me to implement the Croquet application architecture nearly from scratch using functional reactive paradigm in Solid JS / S.JS.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/745245330" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The typical application in the 4th version of &lt;a href="https://play.krestianstvo.org/"&gt;Krestianstvo SDK&lt;/a&gt; is an application, that will be build up from Solid JS main types of building blocks: Components and Reactive Primitives. Solid’s fine-grained reactivity is built on three core primitives: Signals, Memos, and Effects. Together, they form an auto-tracking synchronization engine. Reactive computations take the form of function-wrapped expressions that execute synchronously (&lt;a href="https://www.solidjs.com/guides/getting-started#learn-solid"&gt;more in SolidJS documentation&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Krestianstvo uses Solid JS reactivity for implementing Croquet’s concept of Model — View interconnection. Croquet Models — are just pure Solid JS Signals, Memos and Stores. Croquet Views — are just Solid JS lightweight Components with no state and no instances. All received external messages from Reflector and all internal Future messages, that responsible for actions are wrapped in a Signals and then dispatched by an Effects accordingly. For example, Smalltalk like “&lt;strong&gt;doesNotUnderstand&lt;/strong&gt;” message is easily realised in Krestianstvo.&lt;/p&gt;

&lt;p&gt;Here is an example of simple working app in Krestianstvo SDK | 4 (run it on &lt;a href="https://codesandbox.io/s/krestianstvo-helloworld-pnimfu"&gt;codesandbox&lt;/a&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;solid-js/web&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Selo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createLocalStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;krestianstvo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLocal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createLocalStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;ticking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;initialized&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setLocal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;properties&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;future&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;selo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;initialize&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Selo&lt;/span&gt;
      &lt;span class="nx"&gt;nodeID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;seloID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sandbox_counter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;reflectorHost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://time.krestianstvo.org&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be continued…&lt;/p&gt;

&lt;p&gt;Demo playground: &lt;a href="https://play.krestianstvo.org"&gt;https://play.krestianstvo.org&lt;/a&gt;&lt;br&gt;
Glitch demo project: &lt;a href="https://krestianstvo-playground.glitch.me"&gt;https://krestianstvo-playground.glitch.me&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code for &lt;strong&gt;Krestianstvo SDK 4&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playground: &lt;a href="https://github.com/NikolaySuslov/krestianstvo-playground"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Core library on Solid JS: &lt;a href="https://github.com/NikolaySuslov/krestianstvo"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Prototype on S.js: &lt;a href="https://github.com/NikolaySuslov/krestianstvo-s.js"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Reflector server: &lt;a href="https://github.com/NikolaySuslov/lcs-reflector"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>webxr</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
