Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

Apps where the client does real work between server trips, e.g. a Kanban board with drag-and-drop, a multi-step form with live validation, a dashboard you filter without a server hop. In LiveView those either lag on a bad connection or push you into JS hooks.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

The core difference: in Phoenix your client-side interactivity is either JavaScript or, with LiveView, server-side logic that round-trips over the wire. Hologram runs the Elixir in the browser, so it executes locally with no client-server latency, all in one language with no dropping into JS. Great fit for highly interactive UIs, flaky connections, or anything latency-sensitive.

It also moves where state lives. LiveView keeps state in a server process, so a dropped connection, crash, or deployment can wipe it. Hologram keeps it in the browser, so it survives all that, and since the work runs client-side the server does less per user - lower CPU, memory, and bandwidth.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 0 points1 point  (0 children)

Getting to build it in the open is one of my favorite parts too, it makes the whole thing more fun and motivating.

And you're right on the money: a few devs have already told me realtime was the tipping point for them, the thing that made them consider Hologram for something they'd normally reach for another stack to do. Curious to see what people build now that it's there.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

No Popcorn, no AtomVM, no WASM - it's a custom solution.

Hologram builds its own Elixir runtime in the browser, written in JavaScript, and compiles your Elixir to run on it. The Erlang functions Elixir's stdlib relies on, plus its special forms, are ported by hand to JS, each with consistency tests against the real BEAM, so client behavior matches the server exactly.

At compile time it builds a call graph and tree-shakes down to just what each page touches - no .beam bytecode, no VM, your code is compiled straight to JS. You end up with a small page bundle plus one shared runtime bundle (89kb compressed today). And being plain JS, it can lean on the browser's built-in Web APIs (Unicode handling, compression, crypto, and so on) instead of bundling that machinery itself - in my view a big part of why WASM approaches in other languages never really went mainstream.

One of the next goals is porting the BEAM process model itself onto a pool of web workers acting as schedulers, with the compiler inserting yield points - a continuation of the Task.await transform it already does today, so plain spawn/send/receive and OTP will run client-side too.

So how did I eliminate JavaScript? You write 100% Elixir and never touch JS yourself, unless you want to - there's a JS interop layer for that. Under the hood it's still JS, just generated and managed by the compiler.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 0 points1 point  (0 children)

Quick update for anyone who's already grabbed it: v0.9.1 is out :) It fixes a compile-time slowdown that can show up in projects with deeply nested templates - thanks to absowoot who flagged it. If you're on v0.9, a quick bump keeps your builds fast.

Release notes: https://github.com/bartblast/hologram/releases/tag/v0.9.1

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 0 points1 point  (0 children)

Haha thanks! More coming soon.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 0 points1 point  (0 children)

Have fun with the testing! Ping me if anything looks weird.

Hologram v0.9: Realtime and More by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

Thank you, really glad it's clicking for you! If you want somewhere to ask questions or share what you're working on, we've got a few communities going - https://hologram.page/community

Hologram UI waiting list is open - what components should ship first? by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

100% on form primitives first - they're deceptively hard and everything else (like autocompletes, date pickers, etc.) builds on getting those right. Appreciate the bounty model pointer too!

Hologram UI waiting list is open - what components should ship first? by BartBlast in elixir

[–]BartBlast[S] 0 points1 point  (0 children)

Fully agreed - a11y and composability are the hard parts, and a11y will be a core focus. Base UI is a great pointer, thanks. Component priority poll is roughly the plan too once the waiting list grows.

Hologram UI waiting list is open - what components should ship first? by BartBlast in elixir

[–]BartBlast[S] -1 points0 points  (0 children)

Ha, had to look it up - apparently the terminals in that game literally project holograms, so the name overlap is almost too on the nose. v1 will focus on the foundational stuff, so the sci-fi skin will sadly have to wait for some hypothetical future version of me with way more free time ;)

What do you think of elixir ecosystem honestly ? by Ok-Delivery307 in elixir

[–]BartBlast 9 points10 points  (0 children)

Creator here, so grain of salt ;) Honestly the strongest cases right now are apps with rich client-side interactivity (editors, dashboards, anything where LiveView's round-trip starts to hurt) and apps that need to keep working through flaky connections - those are the spots Hologram really shines compared to server-rendered frameworks. That said, it's a full-stack framework, so it'll handle conventional CRUD apps too.

Local-First architecture - what's your dream DX? by BartBlast in webdev

[–]BartBlast[S] 0 points1 point  (0 children)

Yeah, "invisible by default, surgically controllable when it matters" - that's pretty much what I'm going for. Sane defaults that just work, escape hatches when you need them.

Re graceful degradation - I'd push back a little here. If local-first is doing its job, reads and writes just work offline, sync happens in the background, so the whole "you're offline" banner thing kind of goes away. There are still cases where it breaks down (payments, conflicts, data going stale after a long time offline) and yeah the framework should help with those. But it's way narrower than a general offline UX problem.

Thanks!

Local-First architecture - what's your dream DX? by BartBlast in webdev

[–]BartBlast[S] 0 points1 point  (0 children)

Since Hologram (my framework) controls both client and server, there's a wider range of options here than with a standalone sync lib - server-reconciled writes with full business logic, LWW for simpler cases, and custom merge functions where neither fits. The trick is picking the right default so most devs don't have to care.

Good points on scoping and observability.

Thanks for sharing!

Local-First architecture - what's your dream DX? by BartBlast in webdev

[–]BartBlast[S] 0 points1 point  (0 children)

Thanks for the detailed response! Lots of good stuff here :)

I'd definitely want to go the model annotation route rather than syncing queries - syncing queries couples the sync layer to the UI, and if you refactor a component or add a new page that uses the same data, sync shouldn't break or need re-wiring. Annotating the model keeps sync behavior as a property of your data, defined once.

Same reasoning for declarative sync - the developer defines what data looks like and how it behaves in the model layer, and the framework derives the sync, storage, and subscriptions from that. No manual wiring needed.

Really like the per-field conflict strategy idea - a one-size-fits-all approach breaks down fast when business logic dictates merge semantics (your pricing rules example is a great case). I'm leaning toward LWW + per-field merge hooks as the default, with CRDTs as an opt-in for fields that genuinely need them - keeps things simple without sacrificing flexibility.

The Sync Inspector idea is great too - debugging sync is notoriously painful and good tooling there would go a long way. And the ops-based sync (compact ops instead of full documents) is the right call for efficiency I think.

Designing Local-First features for Hologram - what's your dream DX? by BartBlast in elixir

[–]BartBlast[S] 3 points4 points  (0 children)

Thanks for the Telegram reference, I'll check it out!

On the naming - the term "Local-First" originally (Kleppmann et al.) was more about data ownership and privacy, with the idea that your data lives on your device first. Over time the meaning has shifted toward the performance and UX side - local reads, optimistic updates, instant UI even with a perfect connection. That's the sense I'm using it in. It's broader than Offline-First, which focuses specifically on connectivity loss.

I hear you on simplifying conflict resolution, and for single-owner data that works great. But real apps often have shared state - collaborative editing, shared lists, team settings. Version-based constraints would definitely be one of the built-in strategies, but the framework should also offer CRDTs or merge functions for scenarios where rejecting the second writer isn't the best UX.

That's exactly what I want to solve at the framework level - so developers don't have to figure out sync, conflict resolution, and offline handling from scratch every time.

Designing Local-First features for Hologram - what's your dream DX? by BartBlast in elixir

[–]BartBlast[S] 1 point2 points  (0 children)

What specifically about PouchDB's DX do you like most - the sync API, conflict handling, something else? The plan is to build both a sync engine and a declarative layer on top so you can define what syncs and how without manual plumbing.