bartblast

bartblast

Creator of Hologram

Hologram - full stack isomorphic Elixir web framework

Hey there! There’s a new kid on the block! :smiley:

What is it?

Full stack isomorphic Elixir web framework that can be used on top of Phoenix.
https://github.com/segmetric/hologram

Inspired by

Elm, Phoenix LiveView, Surface, Svelte, Vue.js, Mint, Ruby on Rails.

How it works

To build your web app, you use basic Hologram blocks: pages, layouts and components.

Hologram builds a call graph of your code (which must follow some basic conventions) and determines which code is used on the client, and it then transpiles such code to JavaScript.

Because the state is kept on the client it makes the programming model simpler, and thanks to stateless or stateful components the app is easily scalable.

Code that is run on the client is encapsulated in “actions”, and code that runs on the server is encapsulated in “commands”. Actions can trigger commands, commands can trigger actions. Both actions and commands can be triggered directly by DOM events.

Client communicates with server through websockets - there is no boilerplate code to make it work, Hologram figures this out automatically.

What is already done

This is work in progress (although usable and used in production). To check what works and what is planned - take a look at the roadmap in the readme: GitHub - bartblast/hologram: Full stack Elixir web framework that intelligently compiles Elixir client-side code to JavaScript · GitHub

History / background

I tried to write this kind of framework first in Ruby, and I actually managed to create a working prototype, but the performance was not satisfactory. Then I tried Crystal, but it was very hard to work with its AST. Then I moved to Kotlin, but I realised that it’s better to use a dynamically typed language for that… Then I found Elixir in 2018 and fell in love with it. I started to work on Hologram in the summer of 2020.

Is it used in production?

Yes, it is used in Segmetric: https://www.segmetric.com/ Take a look at the “join beta” and “contact pages" which showcase form handling, or check the mobile menu. This all works on transpiled Elixir code! (But please, submit the forms only if you actually want to join the Segmetric beta or contact Segmetric - it is a live page, thanks!)

I want to see some code!

To see how Hologram app is structured, and see some actual code, take a look at the Hologram’s E2E modules: https://github.com/segmetric/hologram/tree/master/e2e

Basic example

defmodule MyPage do
  use Hologram.Page

  route "/my-page-path"

  def init do 
    %{
      count: 0
    }
  end

  def template do
    ~H"""
    <div>Count is {@count}</div>
    <button on:click={:increment, by: 3}>Increment by</button>
    <Link to={MyOtherPage}>Go to other page</Link>
    """
  end

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

  def command(:save_to_db, _params) do
    # Repo.update (…)
    :counter_saved
  end
end

# Action can return a new state, or a tuple {new_state, command, params}
# Command can return an action or a tuple {action, params}
# (This is similar to Elm architecture.)

I’m in the process of creating a basic website with installation guide. Let me know what you think about the project? What do you need to try it out? I will be glad to answer your questions :slight_smile:

Most Liked

bartblast

bartblast

Creator of Hologram

@Twfo326 Thanks! Here are the main selling points:

  • State on the client - and all of the problems that get solved by this approach (below)…

  • No latency issues as most of the code is run immediately on the client. This makes it possible to create rich UI or even games. At the moment with LiveView you need something like fly.io to make it bearable, but you still have latency and can’t guarantee the response time (there is always some variance). And you still need some JS or Alpine to make it work. Until someone manages to create quantum internet (e.g. by taking advantage of entanglement), there are no workarounds for this problem. Not sure if this is even technically possible, though :wink:

  • Better offline support (internet connection loss, poor signal, etc.). Since most of the code is run on the client and you only hit the server to run some command from time to time, Hologram can work offline most of the time. This would also make it possible to create PWA’s or mobile apps through WebView, assuming you use something like LocalStorage.

  • Less server RAM used - state is kept in the browser instead of the socket.

  • Less CPU used - most of the code is run by the browser not by the server.

  • Less bandwidth used - only commands need to communicate with the server, no need to send diffs to rerender components.

  • No state sync problems - state is kept only in one place (browser) and the websocket communication used is stateless.

  • No JS or Alpine.js needed except for communication with some third party scripts or widgets, but this can also be solved by creating some standardized libs for popular packages that would handle the interop.

Another important selling point is the dev experience. I envision Hologram to be very friendly to new Elixir converts or beginner devs. I want it to be very, very intuitive, so that you can focus on working on new features in your project instead of solving technical problems and writing boilerplate code.
To achieve that Hologram will provide out of the box such things as UI component library (CSS framework agnostic), authentication, authorization, easy debugging (with time travel), caching, localization and some other features that you typically use in a web app.

I think that using Hologram’s approach, i.e. Elixir-JS transpilation, code on client and action/command architecture it’s possible to create something as productive as Rails, but without its shortcomings related to scalability, efficiency, etc.

josevalim

josevalim

Creator of Elixir

I want to clarify this section a bit. This sentence only applies if you try to use LiveView for client-only interactions, but the docs are very clear that you should not use LiveView for that.

I am aware that you know this, I am commenting to avoid confusion in other threads. :slight_smile:

Assuming you have to hit the server, for example to talk to a database, LiveView response time is actually better than regular HTTP requests because it works over an existing authenticated web socket connection. So the work of parsing headers, authenticate users, etc is not done on every server interaction. Hologram and LiveView should be similar here, as both are WebSockets based.

Similarly, Fly.io gets you closer to your users, which means any server-based application could benefit from Fly.io.

In other words, LiveView is for server based interactions and it excels at that, with or without Fly.io. Indeed, for more complex cases on the client, then you need custom JS (or something that aims to fully cover both server and client, like Hologram).

bartblast

bartblast

Creator of Hologram

@christhekeele I initially tried to use ElixirScript, but I couldn’t make it work. When I went through its GitHub issues I realized the creator stopped maintaining the project and focused all of his efforts on Lumen: Still alive? · Issue #495 · elixirscript/elixirscript · GitHub So I tried Lumen, but too much work was in progress. And now it looks that the project is stalled at the moment: Project Status · Issue #698 · GetFirefly/firefly · GitHub

I also tried another route: Erlang → PureScript → JavaScript through Erlscripten, Erlscripten – Transpiling Erlang to Javascript. Yes, you read it right - News and Announcements - æforum but I wasn’t convinced with it, because one of my goals was easy debugging of the transpiled code, and for that it helps if the transpiled code resembles what was actually written in Elixir.

So I decided to write my own transpiler, because that gives me much more control over the output code and I can fix any errors myself. I do this by first converting the code to AST, then building IR (intermediate representation) containing context and metadata, which makes it easier to reason about the code and finally the IR is encoded into JavaScript. You can take a glance at its structure here: hologram/lib/hologram/compiler at master · bartblast/hologram · GitHub

11
Post #4

Where Next?

Popular in News & Updates Top

fhunleth
We recently released Nerves 1.4.0 and an update to the Nerves new project generator, nerves_bootstrap. The biggest change is support for ...
New
zachdaniel
Hey folks! We’ve just released the beta 0.1.0 version of ash_sqlite. Take a look at the guide here: https://hexdocs.pm/ash_sqlite/get-sta...
New
zachdaniel
Working with nested forms in Ash was already great, but it’s even better now with a the new features that will be in the next release of ...
New
DominikWolek
Hey everyone! The Membrane Framework has a new website! It contains tutorials, blog posts, and other resources you’ll find handy while u...
New
mat-hek
Hi everyone, I’d like to share with you a new library from the Membrane team - Boombox. It’s a simple streaming tool built on top of Mem...
New
fhunleth
We’ve released Nerves v1.3.0 with support for Elixir 1.7 and Distillery 2.0! We encountered a few bumps over the past week, but it’s look...
New
hugobarauna
Discover Livebook 0.9’s new security features, including Hubs for centralized secret management, notebook stamping, and a sneak peek into...
New
jjcarstens
I know you might be thinking ¬ “Why make another SSH daemon wrapper when there already exists many like sshex and esshd??” Well, grea...
New
fhunleth
We recently released Nerves 1.5.0 and corresponding updates to the Nerves new project generator, nerves_bootstrap and our official system...
New
jjcarstens
Hey friends! :waving_hand: With NervesConf 2024 around the corner, Frank, myself, and the greater Nerves team wanted to share a survey w...
New

Other popular topics Top

TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41539 114
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
marick
I had some trouble figuring out how to make many-to-many associations work. Once I got it working, I wrote a blog post. Because I’m a nov...
New
Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 126479 1222
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement