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


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Version 0.2.0 with full Elixir syntax support (except the stuff related to parallelism), with a demo app and with a basic “getting started guide” will be done this summer.</p>
</blockquote>
</aside>
<p>Excellent news! <img src="https://forum.elixirforum.com/images/emoji/apple/rocket.png?v=15" title=":rocket:" class="emoji" alt=":rocket:" loading="lazy" width="20" height="20"></p>
<p>I really understand, so for me it’s definitely not a problem, but not everyone is enough patient and understanding or they just don’t have a knowledge about possible vacations and other things. Called update because I’m interested, but also to avoid such topics:</p>
<p><a href="https://forum.elixirforum.com/t/anyone-know-about-the-status-of-the-funwithflags-project/56670" rel="nofollow">https://forum.elixirforum.com/t/anyone-know-about-the-status-of-the-funwithflags-project/56670?u=eiji</a></p>
<p>Having in mind this net time I believe it would be worth to add just a few words on top of readme like:</p>
<blockquote>
<p>I’m rewriting project to version <code>0.2.0</code> this summer. Therefore below roadmap is outdated.</p>
</blockquote>
<p>btw. If you would have a complete guide of how to make <code>hologram</code> app feel free to ping me here. I can’t say how it would be in future, but one thing I’m sure about is that at least I would like to give it a try, search for potential edge cases and give my suggestions.</p>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Auth will use session data. I haven’t gotten to work on session yet, but I’ve got a few ideas:</p>
<ul>
<li>session will be accessible through commands at all times and on page init (so only through the server for security reasons)</li>
<li>stored in HTTP-only cookie or database</li>
</ul>
</blockquote>
</aside>
<p>It would be amazing if <code>client</code> would have 2 states. One accessible only on single page (let’s call it <code>page_state</code>) and other accessible on all pages (let’s call it <code>state</code>). For example changing <code>language</code> or <code>theme</code> could be easily done on client and should be shared on every page unlike <code>counter</code> in example.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyPage do
  use Hologram.Page

  route "/my-page-path"

  def init(_params, _conn, state) do
    initial_page_state = %{count: 0}
    {initial_page_state, state}
  end

  def template do
    # …
  end

  def action(:change_language, params, page_state, state) do
    {page_state, put(state, lang, params.lang))
  end

  def action(:increment, params, page_state, state) do
    {put(page_state, :count, page_state.count + params.by), state)
  end

  def command(:log_in, params, session) do
    # log in
    {:logged_in, Map.put(session, :current_user, current_user)}
  end
end
</code></pre>
<aside class="quote no-group" data-username="bartblast" data-post="32" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>It would be possible to implement offline SPA if all pages are downloaded in a bundle</p>
</blockquote>
</aside>
<p>I’m not really sure if bundling is needed at all. I would say that you could do one much simpler thing i.e. add a <code>hologram</code> command to cache specific page i.e. the user clicks on some button to make sure data would be available also offline and the app literally do a simple <strong>loop</strong> calling just one command:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># call hologram command
required_offline_pages = [IndexPage, ShowPage]
Enum.map(required_offline_pages, &amp;send_cache_hologram_command/1)

# call app command
required_offline_data = [Blog,Post]
Enum.map(required_offline_data, &amp;send_fetch_all_command/1)

# this way in let's say IndexPage we could replace such a custom code
data = send_fetch_all_command(Blog.Post)
# to for example
data = send_fetch_all_command(Blog.Post, fallback: &amp;read_from_cache/1)
</code></pre>
<p>Since as you said once the page is loaded it works offline, so you already have code to load specific page and call init. If so you can just use said code, but without calling page init. Do you think it’s lots of work this way?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293378" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-293378" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293378"
                     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 #32"></div>
  </section>
</div>
    <div class="postbit" id="293522" data-post-id="293522">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Eiji" data-post="33" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<p>It would be amazing if <code>client</code> would have 2 states. One accessible only on single page (let’s call it <code>page_state</code>) and other accessible on all pages (let’s call it <code>state</code>). For example changing <code>language</code> or <code>theme</code> could be easily done on client and should be shared on every page unlike <code>counter</code> in example.</p>
</blockquote>
</aside>
<p>Taking into account that pages and layouts will be components (which may have their own state - similar to LiveComponent) and that Hologram will have something similar to LiveView sticky components, the situation which you describe (language, theme, etc) can be handled by sticky layout components (I’ll probably call them something different). I will evaluate all the available options related to keeping state, but we need to take into account such things as maintainability and debugging (I plan to implement something similar to Elm Time Travel among other things). It’s very important to be able to reason about the state changes easily.</p>
<aside class="quote no-group" data-username="Eiji" data-post="33" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<p>I’m not really sure if bundling is needed at all. I would say that you could do one much simpler thing i.e. add a <code>hologram</code> command to cache specific page i.e. the user clicks on some button to make sure data would be available also offline and the app literally do a simple <strong>loop</strong> calling just one command:</p>
</blockquote>
</aside>
<p>That’s interesting, a little similar to Ember model store preloading (if I understand correctly) but I think people may find it a little “too magical”. But I agree - something like that would be very helpful for offline apps. I’ll evaluate some options in the later stages.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293522" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-293522" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293522"
                     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 #33"></div>
  </section>
</div>
    <div class="postbit" id="293529" data-post-id="293529">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="bartblast" data-post="34" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>sticky layout components</p>
</blockquote>
</aside>
<p>If you follow <code>LiveView</code> meaning then it’s not good. Sticky components are not re-rendered losing their state, but kept when changing <code>Page</code>. Look that changing language and other options that are used in many or even all <code>components</code> / <code>pages</code> may be completely outside of <code>layout</code> components.</p>
<p>The simplest example is this forum. User preferences would be a standard <code>Page</code> like any other. There is absolutely no need to make it <code>sticky</code>. Since we are talking about client code how about a simple <code>API</code> for accessing let’s say … <code>window.__HologramAppState__</code>?</p>
<p>This way developers would be able to write for example:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir"># …
def action(:change_language, params, state) do
  # save user preferences in database
  call_update_lang_command(params.lang)
  # changes page state
  put_window_state(:lang, params.lang)
  # window.__HologramAppState__.lang = params.lang
  state
end
# …
</code></pre>
<p>This way it should be simple to add <code>get</code>, <code>put</code> and <code>update</code> functions. Those functions should be easy to implement, cross browser, give lots of flexibility for an application’s global config and should not conflict with any <code>JavaScript</code> library.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293529" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-293529" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293529"
                     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 #34"></div>
  </section>
</div>
    <div class="postbit" id="293762" data-post-id="293762">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="Eiji" data-post="35" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/48/36743_2.png" class="avatar"> Eiji:</div>
<blockquote>
<p>If you follow <code>LiveView</code> meaning then it’s not good. Sticky components are not re-rendered losing their state, but kept when changing <code>Page</code>. Look that changing language and other options that are used in many or even all <code>components</code> / <code>pages</code> may be completely outside of <code>layout</code> components.</p>
</blockquote>
</aside>
<p>Actually, that’s how it’s going to work in Hologram as well, if a component is flagged as “sticky” (or “persistent” - I haven’t decided on the name yet), its state won’t be lost on new page redirect, and it will be kept in the DOM (no patch).</p>
<p>So if we have a page:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule MyPage do
  route "/hello"

  def template do
    ~H"Hello world!"
  end
end
</code></pre>
<p>Hologram implicitly wraps this page template in the default layout component, so in practice it’s:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;Layout&gt;
  &lt;Page /&gt;
&lt;/Layout&gt;
</code></pre>
<p>If we make the layout component sticky, it won’t lose its state.<br>
Page state is also implicitly passed to the layout and available in the layout template as vars, but if we’ve got <span class="mention">@lang</span> or <span class="mention">@theme</span> state on the layout only, it won’t be overwritten by page state when we redirect to a new page.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293762" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-293762" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293762"
                     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 #35"></div>
  </section>
</div>
    <div class="postbit" id="293763" data-post-id="293763">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It may be better to keep such state as theme and lang in session anyway, I just showed some examples of how it could theoretically be used.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293763" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-293763" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293763"
                     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 #36"></div>
  </section>
</div>
    <div class="postbit" id="343824" data-post-id="343824">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hey <a class="mention" href="/u/bartblast" rel="nofollow">@bartblast</a>, this looks like a really interesting way to create apps. A few questions:</p>
<ol>
<li>Do you have any updates on progress?</li>
<li>Will this work out of the box with Phoenix’s auth and PubSub?</li>
<li>What are the downsides to the approach that Hologram is taking? I mostly see upside so curious what I’m missing.</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="343824" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-343824" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="343824"
                     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 #37"></div>
  </section>
</div>
    <div class="postbit" id="343912" data-post-id="343912">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<ol>
<li>
<p>I’m in the final stages now - wrapping up feature testing and fixing minor issues that popped up during testing. We’re very close to having a playable release! <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
</li>
<li>
<p>About Phoenix integration:</p>
<ul>
<li>Authentication: Nope, Hologram will come with its own auth layer (but it’ll be there out of the box). There’s a possibility we could share sessions between Hologram ↔ Phoenix which would make auth work both ways, but I haven’t dug deep into that yet - just have a general idea how it might work.</li>
<li>PubSub: Yes, this will definitely work, but in a later release. We’ll have a nice dedicated DSL in pages and components to talk to Phoenix PubSub.</li>
</ul>
</li>
<li>
<p>Here are the downsides I can think of:</p>
<ul>
<li>Browser download size: The framework runtime (with commonly used Erlang/Elixir functions) comes in at 427 kB (minified) / 75 kB (gzipped). I haven’t done any optimization yet though, and there are definitely functions in there we don’t need, so I expect we can cut that in half eventually. Plus each page has its own separate bundle that’s way smaller than the runtime bundle - size depends on what the page uses.</li>
<li>Client-side code caution: Since we’re auto-transpiling to JavaScript, you’ll need to be careful not to include any secrets in your client code (passwords, keys, etc). Phoenix LiveView doesn’t have this issue since everything runs server-side.</li>
<li>Function limitations:
<ul>
<li>You can’t pass anonymous functions between client and server in command parameters</li>
<li>So this won’t work: <code>put_command(component, :my_command, a: 1, b: fn x → 2 * x end)</code></li>
<li>But function captures are fine: <code>put_command(component, :my_command, a: 1, b: &amp;DateTime.utc_now/1)</code></li>
<li>I’m still thinking about whether to allow this at all for security reasons</li>
</ul>
</li>
<li>DOCTYPE declaration: All pages/layouts need to use the same DOCTYPE and you can’t use template expressions in the DOCTYPE template fragment. But honestly, in 2024 this isn’t really a problem - just use <code>&lt;!DOCTYPE html&gt;</code> everywhere and you’re good to go.</li>
</ul>
</li>
</ol> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="343912" data-batch-url="/posts/batch_likers">
                        7
                      </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/hologram-full-stack-isomorphic-elixir-web-framework/45200/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-343912" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="343912"
                     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 #38"></div>
  </section>
</div>
    <div class="postbit" id="343969" data-post-id="343969">
  <section>
    <div class="post-wrap">


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

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Awesome, thanks. Look forward to giving it a go when it’s ready.</p>
<aside class="quote no-group" data-username="bartblast" data-post="39" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/48/17647_2.png" class="avatar"> bartblast:</div>
<blockquote>
<p>Browser download size: The framework runtime (with commonly used Erlang/Elixir functions) comes in at 427 kB (minified) / 75 kB (gzipped). I haven’t done any optimization yet though, and there are definitely functions in there we don’t need, so I expect we can cut that in half eventually.</p>
</blockquote>
</aside>
<p>Would definitely be nice to cut this down <img src="https://forum.elixirforum.com/images/emoji/apple/slightly_smiling_face.png?v=15" title=":slightly_smiling_face:" class="emoji" alt=":slightly_smiling_face:" loading="lazy" width="20" height="20"></p>
<p>One other question: how do you envision client-side only javascript being written? I’m guessing you’re thinking something other than Phoenix’s Hooks?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="343969" 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/hologram-full-stack-isomorphic-elixir-web-framework/45200/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-343969" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="343969"
                     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 #39"></div>
  </section>
</div>
    <div class="postbit" id="344102" data-post-id="344102">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="bartblast" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/120/17647_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  bartblast
                    <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 class="user-title">
									<span>Creator of Hologram</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="jam" data-post="40" data-topic="45200">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jam/48/36266_2.png" class="avatar"> jam:</div>
<blockquote>
<p>One other question: how do you envision client-side only javascript being written? I’m guessing you’re thinking something other than Phoenix’s Hooks?</p>
</blockquote>
</aside>
<p>To answer that question let’s first think why we need hooks in LiveView… The core reason is the server-client boundary, where application code runs on the server while maintaining state there. This creates a natural separation between server-side Elixir code and client-side JavaScript. Due to this separation, hooks become necessary for:</p>
<ol>
<li>To interact with browser APIs that are only accessible client-side, such as:
<ul>
<li>Accessing window or document objects</li>
<li>Using browser-specific APIs like geolocation</li>
<li>Direct DOM manipulations (though rarely needed, mainly for elements not directly managed by LiveView)</li>
<li>Third-party JavaScript library integration</li>
</ul>
</li>
<li>To manage client-side behaviors that require immediate responsiveness or can’t be efficiently handled through WebSocket communication, like:
<ul>
<li>Managing scroll position</li>
<li>Handling file uploads</li>
<li>Working with canvas elements</li>
<li>Managing complex form inputs</li>
</ul>
</li>
</ol>
<p>Now, consider this hypothetical scenario: If LiveView could execute directly in the browser (through transpilation), hooks would become largely unnecessary because:</p>
<ul>
<li>Code would have direct access to browser APIs</li>
<li>The server-client barrier would disappear (at least for UI management, we still need the server for database, files access, auth, etc.)</li>
<li>DOM manipulation could happen directly from the LiveView code on the client-side</li>
</ul>
<p>This is essentially what Hologram achieves. In most cases, hook-like patterns become unnecessary since Hologram can provide direct wrappers for browser APIs that are accessible through client-side Hologram actions (similarly for DOM manipulations).</p>
<p>However, some scenarios might still benefit from hook-like mechanisms:</p>
<ul>
<li>Integrating with external JavaScript libraries</li>
<li>Handling complex lifecycle events</li>
<li>Managing stateful browser behaviors that don’t fit well into Hologram’s declarative/reactive model</li>
</ul>
<p>For these JavaScript interop cases, the framework can implement a port-like system (similar to what Elm does, see: <a href="https://thoughtbot.com/blog/bridging-elm-and-javascript-with-ports" rel="noopener nofollow ugc">https://thoughtbot.com/blog/bridging-elm-and-javascript-with-ports</a>) that creates clear boundaries where data must flow explicitly through defined interfaces. These integration points would be defined alongside the components that utilize them (similarly how templates are colocated).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="344102" data-batch-url="/posts/batch_likers">
                        4
                      </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/hologram-full-stack-isomorphic-elixir-web-framework/45200/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-344102" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="344102"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>