<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="116658" data-post-id="116658">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="houshuang" data-post="2" data-topic="9736">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/houshuang/48/7030_2.png" class="avatar"> houshuang:</div>
<blockquote>
<p>having a compatibility mode with ShareDB would let a lot of products switch easily, and would work well with existing extensions like Rich text etc, but investigating a more efficient transmission format would be interesting too…</p>
</blockquote>
</aside>
<p>I’ve just been reading the ShareDB binary wire protocol, and it seems like a poor match for Phoenix. Phoenix channels seem to work pretty well if there is a one-to-one map between channels and documents. That is, a single channel should handle a document. That way, subscribing to a given document is trivial: just “join” the channel in question. Keeping binary compatibility with SharDB would require defining my own incompatible channel abstraction on top of Phoenix’s PubSub, which doesn’t seem very easy.</p>
<p>I think I’ll playy a little with having one channel per document and see where it goes.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="116658" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-116658" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="116658"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="116670" data-post-id="116670">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="rodrigues" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/rodrigues/120/23387_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  rodrigues
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="1" data-topic="9736">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Instead of OT, some people advocate CRDTs, but they have some important disadvantages in practice. They have a much higher memory overhead (and sometimes a higher bandwidth overhead) and they don’t resolve conflicts. OT with a central server has low overhead and gives us a canonical document (the one that lives on the server) at each moment in time.</p>
</blockquote>
</aside>
<p>In this area of collaboration, I’m looking forward to see things like <a href="https://github.com/gritzko/swarm" rel="noopener nofollow ugc">Swarm</a> and <a href="https://github.com/gritzko/ron" rel="noopener nofollow ugc">RON</a> getting traction, looks like it can <a href="http://swarmdb.net/articles/papoc/" rel="noopener nofollow ugc">address some of the overheads of CRDTs</a>, and be more offline-sync friendly than OT solutions.</p>
<p>Something like this for Draft.js would be amazing.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="116670" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-116670" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="116670"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="116714" data-post-id="116714">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="houshuang" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/houshuang/120/7030_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  houshuang
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You could do this translation on the client - the ShareDB client library doesn’t require access to a raw websocket, but to a websocket-like object, which only needs to implement a few minimal methods. This would still require a tiny bit of overhead, but now it would be distributed among all the clients, which is not where the bottleneck is.</p>
<p>I still think you’d get a ton of leverage if you built on ShareDB, there are a lot of “devil is in the detail” which they have solved over years, lot’s of libraries with built-in support etc. Here’s a recent tech talk I gave going over how we use ShareDB and React in detail: <a href="https://www.youtube.com/watch?v=gN37rJRmISQ" rel="noopener nofollow ugc">https://www.youtube.com/watch?v=gN37rJRmISQ</a></p>
<p>And here is a demo of the kinds of things we’re currently capable of: <a href="https://www.youtube.com/watch?v=zuUG9a5tiVM" rel="noopener nofollow ugc">https://www.youtube.com/watch?v=zuUG9a5tiVM</a></p>
<p>This is all open source (and I’m happy to help if you’d like to reuse any of our components). I’m currently working on building a wiki/knowledge base on top of these components, with live editing, rich components etc. I’d love to be able to put this up on a public server and offer everyone free accounts, and that would be so much easier with a reliable easy-to-scale backend like Elixir.</p>
<p>(In fact, I’d be happy to write the client code required to get ShareDB to interop with native Elixir websockets, if we had the server-side code to actually do the operational transforms etc).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="116714" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-116714" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="116714"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="116881" data-post-id="116881">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="houshuang" data-post="15" data-topic="9736">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/houshuang/48/7030_2.png" class="avatar"> houshuang:</div>
<blockquote>
<p>the ShareDB client library doesn’t require access to a raw websocket, but to a websocket-like object, which only needs to implement a few minimal methods</p>
</blockquote>
</aside>
<p>I know, that seems like the easy part. As usual, you trade complexity in implementing the client in exchange for complexity when implementing the server. If you have a phoenix channel per document, you can simply <code>broadcast!</code> your operations to all clients that subscribe to that document. If you share a channel between multiple documents things get much harder.</p>
<p>I don’t know how to route the raw binary ShareDB messages into their own channels. Unless I define a websocket-like object that parses the message and translates them into channel subscriptions and events. Which canbe done, of course, but it seems very wasteful,</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="116881" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-116881" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="116881"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="116921" data-post-id="116921">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="houshuang" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/houshuang/120/7030_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  houshuang
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="16" data-topic="9736">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>I don’t know how to route the raw binary ShareDB messages into their own channels. Unless I define a websocket-like object that parses the message and translates them into channel subscriptions and events. Which canbe done, of course, but it seems very wasteful,</p>
</blockquote>
</aside>
<p>This is what I was suggesting. I don’t actually think it’s very expensive, and given that it’s running on the client, it doesn’t matter for scaling. My concern for scaling is having a single beefy server which could serve thousands of users, in this situation a tiny bit of overhead distributed in each browser makes no difference. And compared to all the overhead of sending and receiving websockets etc, I am confident this wouldn’t even be noticeable, and not a lot of code.</p>
<p>The other question is whether the workflow you’re suggesting of broadcasting all changes works with ShareDB… I think it might - a client submits some changes, the server applies those changes and broadcasts, the original client updates its own version, rebases any pending changes onto the new changes (which could include also updates from other clients), other clients also update their local version, submit their changes etc… Could work, but I would have to look more at exactly how the ShareDB protocol works first.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="116921" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-116921" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="116921"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="117515" data-post-id="117515">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’ve been reading a little more, and it looks like Phoenix supports custom transports in channels. That means I can write a new transport that receives websocket messages just like the default ShareDB client and dispatches it into the Phoenix PubSub adapters. That might allow me to efficiently dispatch the messages to the correct clients</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="117515" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-117515" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="117515"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #17"></div>
  </section>
</div>
    <div class="postbit" id="117520" data-post-id="117520">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="houshuang" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/houshuang/120/7030_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  houshuang
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Let me know if you ever want to Skype about this or if I can help in any way. My Elixir is quite rusty, but I’m quite familiar with ShareDB and the client-side stuff as well as JS in general.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="117520" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/19">Post #18</a>
	                </div>
	            </div>
              <div id="likers-container-117520" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="117520"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #18"></div>
  </section>
</div>
    <div class="postbit" id="137678" data-post-id="137678">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tangui" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/tangui/120/12091_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tangui
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="tmbb" data-post="9" data-topic="9736">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/77aa72/48.png" class="avatar"> tmbb:</div>
<blockquote>
<p>Text editing (editing a chain of characters), again, easy. Editing trees (and enforcing the fact that it remains a tree)? Acyclic DAGs? You’re out of luck…</p>
</blockquote>
</aside>
<p>How about XML patches for trees? I don’t much about collaborative editing though. There are a few research papers on that when typing “collaborative editing xml” but I’m not sure what are the pros and cons of this approach.</p>
<p>Implement it with Elixir could make use of:</p>
<ul>
<li>XML patch of the document changes on the client (JS lib), then sending it to an API</li>
<li><a href="https://github.com/zadean/xqerl" rel="noopener nofollow ugc">Xqerl</a> on the server to apply the patch, including detecting (and resolving?) conflicts</li>
<li>Liveview to render back the document (be it a text document, an SVG whiteboard…)</li>
</ul> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="137678" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/20">Post #19</a>
	                </div>
	            </div>
              <div id="likers-container-137678" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="137678"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #19"></div>
  </section>
</div>
    <div class="postbit" id="137707" data-post-id="137707">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>You can think of XML as a strict subset of JSON. That means that whatever works for collaborative editing of JSON documents will also work for colaborative editing of XML documents.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="137707" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/21">Post #20</a>
	                </div>
	            </div>
              <div id="likers-container-137707" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="137707"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #20"></div>
  </section>
</div>
    <div class="postbit" id="151807" data-post-id="151807">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="tmbb" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  tmbb
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>After a long time, I’ve decided to go back to realtime collaboration on Phoenix. The plan is to implement something compatible with <code>ShareDB</code>’s protocol. There are already some tools using <code>ShareDB</code> in the wild, and the most important case (collaborative editing of text) is already covered by ´ShareDB` pretty well (there’s a demo under 20 LOC doing exactly that with some extensions).</p>
<p><code>ShareDB</code> has a client and a server implementation, both written in Javascript. In an ideal world, I’d port the protocol to Elixir and reuse the client without requiring any changes. However, the protocol expects messages to be sent through “bare” websockets, and Phoenix expects messages to be sent through “channels”. Channels are ingrained so deeply in Phoenix that I don’t think it’s possible to use bare websockets wthout reimplementing the whole channel machinery. In fact, Phoenix doesn’t even know what an websocket is.</p>
<p>The client-side API for ShareDB starts with something like this:</p>
<pre data-code-wrap="javascript"><code class="lang-javascript">var ShareDB = require('sharedb/lib/client');
var socket = new WebSocket('ws://localhost:8080');
var connection = new ShareDB.Connection(socket);
</code></pre>
<p>The <code>socket</code> really must be a <code>WebSocket</code>, or at least something that implements the websocket methods. That’s actually very easy with Phoenix channels: you just have to create an object (class, prototype, whatever) which implements those methods and behaves as a webocket. However, there is a problem.</p>
<p><code>ShareDB</code> allows you to create several “documents”, which can be updated in parallel. That means each document should live in its own process and be connected to the client though its own topic. Our “custom” websocket implementation would have to route each message into the appropriate phoenix topic. But the <code>WebSocket</code> object is sent raw JSON and doesn’t know which document/topic the message refers to. The only way to know that is to parse the JSON again and extract the document’s ID, which is unacceptable.</p>
<p>This means I will have to rewrite both the <code>Connection</code> object and the <code>WebSocket</code> object so that the <code>WebSocket</code> is compatible with Phoenix channels and the <code>Connection</code> object can send objects into the <code>WebSocket</code> (so that it can route the messages into the correct topics).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="151807" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/realtime-collaboration/9736/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-151807" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="151807"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/9736/load_more?page=3">Load more posts (11 remaining)</a>
</div></template></turbo-stream>