Hologram v0.5.0 released!

Congrats on the release! :tada:

1 Like

A user reported that the installation instructions were outdated after v0.5.0 removed redundant endpoint integration (which was simplified). If you’re getting errors during setup, just remove the use Hologram.Endpoint and hologram_socket/0 lines from your endpoint module and you should be good to go.

The Installation Guide on the website has been updated now. Thanks @bunnylushington for catching this!

Maybe it’s just me but I also needed to add "app" to elixirc_paths() in mix.exs otherwise visiting localhost shows the generic phoenix homepage.

defp elixirc_paths(:test), do: ["app", "lib", "test/support"]
defp elixirc_paths(_), do: ["app", "lib"]
1 Like

Thanks for sharing your perspective @garrison!

I actually considered the JSX-like path when I started working on Hologram, but ultimately decided to go with a template system because I felt JSX mixes concerns in ways I wanted to avoid. In my ideal world, I’d like to colocate component logic and presentation while still maintaining separation – moving computations like mapping, filtering, etc. into actions, computed properties, effects, and other dedicated areas outside the template itself.

I find this approach more maintainable and the presentation layer more readable. For example, I personally find:

{Enum.map(@items, fn item -> <div key={item.id}>{item.name}</div> end)}

less readable than:

{%for item <- @items}
  <div key={item.id}>{item.name}</div>
{/for}

Templates naturally enforce this separation of concerns, which aligns with my vision for the framework.

That said, choosing templates over a JSX-like system was honestly a close call, and I recognize I might be wrong on this one. The success of this approach really depends on whether I can deliver on the final vision I have in mind – particularly around computed properties, effects, and other reactive patterns.

One thing that gives me confidence in this direction is that HOLO templates compile directly to Elixir AST. For instance, syntax like {%for n <- 0..5, rem(n, 3) == 0} compiles to a plain Elixir comprehension underneath. This means that if my bet on templates proves wrong, something similar to JSX could potentially be introduced in the future without breaking backward compatibility.

4 Likes

That’s interesting! Have you done anything in this regard already?

I can understand why Ash would need to compile regexes to PostgreSQL for database queries, but I’m curious - why to JavaScript?

This could definitely be useful for Hologram when I implement the =~ operator.

The js bit will become a bit more clear in the near future, an announcement will be made :slight_smile: (not making something competitive with hologram.)

4 Likes

Thanks so much Lucas! There’s nothing that prevents hot code reloading in Hologram. In fact, the client-side runtime was specifically architected with hot-loading support in mind for future implementation.

1 Like

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:

7 Likes

My intention with that reply was primarily to argue against a :for/:if syntax as was proposed above. But still, I do think something like JSX would be ideal, so I’m happy to argue in favor of that as well :slight_smile:

I find your example rather unconvincing. Yes the Enum.map syntax is not great, but Elixir has for comprehensions!

{for item <- @items do
  <div key={item.id}>{item.name}</div>
end}

From a readability perspective this example is literally a handful of characters away from being your template syntax. But it’s enormously more powerful because, like JSX, the syntax here is a superset of Elixir rather than a subset. Who says I can’t do this?

{case @item do
  %Foo{} = foo -> <div class="foo">{foo.name}</div>
  %Bar{} = bar -> <div class="bar">{bar.name}</div>
end}

Or even…

{with {:ok, foo} <- make_foo(@item), {:ok, bar} <- make_bar(@item)
do
  <div class="foobar">{foo.name}, {bar.name}</div>
else
  _ -> <div class="error">Not so fast!</div>
end}

I will admit that last one is pretty cursed but surely you see my point. By putting HTML in Elixir rather than the other way around you gain enormous power. This is why JSX is so good.

2 Likes

I did not try to dramatise. I only mentioned in which cases it shouldn’t be considered for prod and there was no reason to say about pros. You see … when I write long messages people says they are too long, but when I stick to topic and don’t say things like that then replies like yours appear. :sweat_smile:

If I think that project which interest me is unstable I create an issue/PR like I already did for hologram for some cases (like migrating Phoenix default layout template for example). I have created many issues/PRs for credo for false positive results too.

:+1: :rocket: :heart:

Hope you count also missing mouse event(s) here as many features requires events like Click Away.

I plan to work on something like phx generator tasks, but with Ecto.Repo.stream/2 instead of list/pagination (load on scroll + notifications support out-of-the-box). However for this to work I need to asynchronously communicate on the server side (for this I need Component Subscription DSL).

My previously mentioned package called dev_joy also waits for an update with hologram support for the very similar reason. It’s not about considering migration, but a real migration, so as said depending on the case it’s unfortunately not yet production ready.

That’s why instead of just saying no I recommended to look on the Roadmap for the missing features a specific project would need. :light_bulb:

btw. if you would have even a draft of the plan for the Component Subscription DSL feature then you can send me a pm. I would be definitely interested to comment if it would fit many use cases for background/timer tasks. :+1:

2 Likes

Thanks for bringing this up. This happens because you placed your Hologram code in the app directory, and elixirc_paths/1 defines where the Elixir compiler looks for source files. By default, it only includes lib, so adding app tells the compiler to also look there.

This step isn’t strictly necessary if you keep your code in the standard lib directory, but I’ve noticed many people (myself included! :sweat_smile:) prefer organizing Hologram pages/components in a separate app directory. Since this pattern is fairly common, I added it as an optional step in the Installation Guide.

1 Like

Thanks @garrison, I do see your point about the power that comes with JSX-like syntax - the examples you provided definitely showcase that flexibility.

My main concern, though, is that when developers are given complete freedom (especially those who are unsure about code organization - where to put what), they tend to do some really funky stuff. The example code you showed is actually half the problem - I’ve seen much worse in practice! :sweat_smile:

The template system is my attempt to provide gentle guardrails that nudge developers toward better separation of concerns, even if it means sacrificing some of that raw power you’re advocating for. Once I have reactive primitives like computed properties and effects in place, developers will have proper designated areas for complex logic while keeping templates focused on presentation.

That said, you make compelling arguments and I’m definitely not set in stone on this. If the template approach proves too limiting in practice, the fact that HOLO templates compile to Elixir AST gives me a potential migration path to something more JSX-like down the road.

2 Likes

Fair point about the messaging challenge :wink:

Looks really interesting!

Cool! :+1:

1 Like

Found this reddit Q&A to be very insightful. Super excited about the direction of hologram, thanks Bart!

Hologram v0.5.0 released! : r/elixir

2 Likes

Sounds like between the forum discussions and the Reddit Q&A, I might need to start working on a proper FAQ page soon - you folks are asking all the good questions! :slight_smile:

1 Like

I heavily lean toward this side myself to the point where I wish mustache was more widely-used. @garrison, I do see your point and have the felt the pain around not having case before, but not too often—I always just extract to private components (although I’m an if-first guy when dealing with bools—seeing case .. true -> .. false -> .. with no other clauses hurts my soul). Personally, I really like :if and friends. I syntax-highlight them to really stand out and don’t feel limited by them. My biggest pain point is the lack of higher-order components. I do really like slots—I find them much nicer than visually tracking curlies in JSX—but they are limited and often times I wish I could just pass a single component to an attribute.


PS, I did not use AI to write this, I’m an OG abuser of em dashes and I’m not letting some invisible robot take that away from me.

3 Likes

A post was split to a new topic: Module aliases not working in colocated .holo templates

A post was split to a new topic: Calling external APIs from Hologram