bartblast

bartblast

Creator of Hologram

Hologram v0.5.0 released!

I’m excited to announce Hologram v0.5.0, a major evolution of the full-stack Elixir web framework! This release brings massive performance improvements - we’re talking execution times improved from milliseconds to microseconds in core client-side operations, making it fast enough for real-time interactions like mouse move events.

Key highlights:

  • Complete bitstring rewrite with ~50x rendering speed improvements!
  • Comprehensive session and cookie management
  • Live reload functionality for enhanced DX
  • Incremental compilation (2x-10x faster builds)
  • New pointer and mouse move events
  • HTTP-based transport layer
  • CRDT support for future distributed features

Full release notes: Hologram v0.5.0 Released! - Hologram

Check out the SVG Drawing Demo that showcases smooth, responsive drawing using the new pointer move events - it really demonstrates the performance leap!

svg-drawing-demo-600

With over 950 commits since v0.4.0, this release delivers significant architectural enhancements while maintaining the unique developer experience that makes Hologram special.

Special thanks to my current GitHub sponsors: @D4no0, @Lucassifoni, and @sodapopcan! :folded_hands:

:purple_heart: Support Hologram’s development: If you’d like to help accelerate Hologram’s growth and make releases like this possible, consider becoming a GitHub sponsor. Every contribution helps dedicate more time to new features and community support!

:open_mailbox_with_raised_flag: Stay in the loop: Don’t miss future updates! Subscribe to the Hologram Newsletter for monthly development milestones, ecosystem news, and community insights delivered straight to your inbox.

Most Liked

bartblast

bartblast

Creator of Hologram

Hologram can be used alongside LiveView in the same Phoenix application. You can have some pages running in LiveView and others in Hologram - they can coexist peacefully.

However, I don’t plan to work on direct Hologram/LiveView integration (like embedding Hologram components within LiveView pages or vice versa). This would introduce significant complexity and several drawbacks, including maintenance burden, architecture lock-in, conflicting paradigms, performance overhead, and others.

If you need to stick with LiveView for any reason (time constraints, existing codebase, etc.), you can always gradually migrate specific pages to Hologram when it aligns with your project’s requirements. This approach gives you the flexibility to use both frameworks without the complexity of trying to make them work together. Additionally, I plan to start working on a companion UI components library soon, which should significantly reduce the time investment needed to build interfaces with Hologram and make migration easier.

bartblast

bartblast

Creator of Hologram

The key insight was that every microsecond matters when you’re building a framework that needs to handle real-time interactions, render at least 60 FPS, and work with transpiled code using boxed types. I systematically profiled and optimized each layer - from the lowest-level bitstring operations up through the highest-level user interactions.

For profiling and benchmarking, I used a multi-tool approach:

  • Benchee for comprehensive Elixir performance testing
  • Custom JavaScript benchmarking scripts using process.hrtime() for precise timing
  • Chrome DevTools Performance Profiler for detailed client-side analysis

The JavaScript JIT compilation made it even more tricky, because you’ll see much different results for cold vs warm vs hot code. For the Elixir part, I was mainly optimizing the compiler, so the tricky part was balancing different project conditions - e.g., different characteristics depending on the call graph structure, module complexity, and compilation patterns.

It’s been quite a journey! The performance improvements were the result of countless hours of profiling, benchmarking, and iterative optimization. It was a very repetitive process, but strangely satisfying when you managed to squeeze out performance gains here and there :wink:

bartblast

bartblast

Creator of Hologram

Video courses are coming soon in about 2-3 weeks. :slight_smile:

The demo is a part of the website code which is currently private, but here’s the most important code:

init/3 (state initialization) and actions (event handling):

def init(_params, component, _server) do
  put_state(component, drawing?: false, path: "")
end

def action(:clear_canvas, _params, component) do
  put_state(component, drawing?: false, path: "")
end

def action(:draw_move, params, %{state: %{drawing?: true}} = component) do
  new_path = component.state.path <> " L #{params.event.offset_x} #{params.event.offset_y}"
  put_state(component, :path, new_path)
end

def action(:draw_move, _params, component) do
  component
end

def action(:start_drawing, params, component) do
  new_path = component.state.path <> " M #{params.event.offset_x} #{params.event.offset_y}"
  put_state(component, drawing?: true, path: new_path)
end

def action(:stop_drawing, _params, component) do
  put_state(component, :drawing?, false)
end

and the most important part of the template:

(...)
  <button $click="clear_canvas" class={Button.class(:md)}>Clear</button>
</div>
<svg 
  class="bg-[#0F1014] cursor-crosshair border border-[#363636] rounded w-full h-[70vh]"
  style="touch-action: none;"
  $pointer_down="start_drawing"
  $pointer_move="draw_move"
  $pointer_up="stop_drawing"
  $pointer_cancel="stop_drawing"
>
  <path d={@path} stroke="#C2BBD3" stroke-width="2" fill="none" />
</svg>
bartblast

bartblast

Creator of Hologram

While you’re definitely right that Hologram isn’t production-ready yet, I think you’re painting a bit too dramatic a picture here :wink: Yes, there are missing features, but what’s left is straightforward. The complex architectural work is done: the runtime, component system, and core primitives are solid.

My focus now is on creating escape hatches so developers don’t get stuck waiting for releases. I’ll prioritize features that users can’t implement themselves:

  • JS Interop - for when you need to interface with existing JavaScript
  • Essential DOM events - including window-level and keyboard events
  • Error handling - can’t really work around this yourself
  • Server-to-client events - including PubSub abstraction for real-time features
  • Action timing/delays - enables things like tick events for games (since we don’t have client processes yet)
  • Command failure handling - proper error states and recovery
  • Action scheduling from within init/3 - scheduling actions from init/3 functions in pages/components

Everything else can be easily worked around (provided the features listed above are implemented). Missing an Erlang function? Just use a server command - you’ll get the same performance characteristics as LiveView.

To put this in perspective: these features in total are less complexity than I put into just the bitstring rewrite in v0.5.0 (implementation | tests). The foundation is solid; now it’s about filling in the practical gaps.

I think we’re closer to real usability than it might seem - worth starting to experiment now with migration in mind! :slight_smile:

zachdaniel

zachdaniel

Creator of Ash

Random implementation detail, but I’d like to make a library for transpiling regexes from Elixir → js and Elixir → Postgresql at some point, that would be a subset (a growing subset over time) of Elixir’s regex capabilities. Might be useful when you get to =~ operators etc.

Where Next?

Popular in News & Updates Top

ConnorRigby
This week we added official Nerves support for the OSD32MP1 line of SOMs. Currently we have tested the osd32mp1-brk breakout board, and ...
New
zachdaniel
Hey folks! In order to give the new AshSqlite a trial run and make sure its got some real usage, AshHq’s multi-package search has been re...
New
mobileoverlord
New versions of the Kiosk systems are out. These systems update official Nerves systems with a local web browser for rendering user inter...
New
bartblast
Backward Incompatible Changes Change template sigil from ~H to ~HOLO Require Elixir 1.15+ and Erlang/OTP 24+ New Features Add “select”...
New
sorenone
Oban v2.23.0 has been released. Sharpens resilience under database outages, catches misconfigured unique constraints at compile time, an...
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
zachdaniel
Going into main shortly, to be released with atomics being wrapped up (which will get its own larger announcement), we will support valid...
New
fhunleth
The Nerves core team is proud to announce the Nerves v1.8.0 release. Nerves provides the core tooling for creating self-contained, BEAM-...
New
jjcarstens
Testing code destined for hardware can be tricky, but it just got one tiny bit easier! :tty0tty was just released which is an Elixir por...
New
zachdaniel
AshCloak AshCloak is small but mighty! Simply configure the extension, and it will encrypt your attributes :partying_face: Since an exam...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement