So I guess this is a crunchy one No images? Click here A layer built of jigsaw puzzles piecesThe reception of BEAM Radio has been delightful. Thank you all for listening that do and let me know if you have any questions. There is also a give-away right now where if you tweet a questions at @beamradio1 and we pick it to be read on the show you get a T-shirt with our glorious brand. The Noted application I built that was the basis for the Telegram Bot blog post has seen quite a few updates and if you are curious it is a quick and dirty romp of a PETAL stack application that you can pull down, register for a Telegram Bot and run on your own. And then you can shout at me to fix things that I haven't gotten to yet, if you like. I hope I'm going to like using this app, I'm putting some time into it. I also have a number of very exciting projects brewing. Some community, some client-related, some probably both. I shouldn't speak of them yet, but know that I am very excited! User interfaces are finickySo the PETAL stack idea has more and less controversial parts. Phoenix and Elixir are not very controversial in the Elixir community. So we can set them aside. LiveView has had me both excited and skeptical at once. It goes against some things I really like such as Progressive Enhancement and plain old web pages via Server-Side Rendering. But once you take the leap into web applications rather than web sites I think most of my reservations fade. Because basically no-one builds deep Progressive Enhancement and Single Page Applications (SPA) are definitely not that. So LiveView plays in that application-focused, not website-focused, arena. After using it for a few things, I'm thrilled. What LiveView allows you to do is to limit the number of places you need to reason about your state. It simplifies things immensely. Just like Elixir in general. In a given GenServer or LiveView you only care about messages that you want to handle. Those messages either update state or produce side-effects, maybe both. But your state is dependent on those events to change. Whether a user is clicking a button or a background process is informing you that it is now at 50% complete, they are events and they work the same. And then in your template you deal with the shape of that state. Only that state. You can provide helper functions and generally make your templates easier to work with in a variety of ways but overall they are conceptually simple and the available data unsurprising. With the way LiveView defines actions that cause events, such as phx-click, phx-change and phx-submit you define all your interactivity in the markup that defines your UI. You don't tie in event listeners in some other JS file. It is very explicit. Those events are UI concerns and your UI is defined by markup and this lets you define those events right there. You can write things top to bottom and worry about implementing the handling afterwards. So where does Alpine.js come in? Well. That's a JS framework meant for this type of interactivity, it focuses on paving over the parts where you don't want the server roundtrip that LiveView feeds off of. Want your user to have to confirm deletion of something? Alpine makes that very straight-forward. Also by just defining minimal code in your markup. UI concerns in your UI definitions, it is the exact same approach that LiveView takes. So you'll recognize the way it works. It is surprisingly capable while keeping a very small API to learn and fits a role right next to the LiveView use-case without much overlap and really no conflict. And Tailwind CSS? So Alpine.js and Tailwind CSS are community buddies. Tailwind Labs seem to be sponsoring Alpine and that's quite neat. And it makes sense to me. They are philsophically compatible. I personally found getting started with Tailwind CSS really weird. Super weird. Because I already know CSS and at first this seems like just defining CSS in the markup but without knowing what they named my CSS properties. But with a bit of effort it is starting to make a lot of sense. Most Tailwind CSS classes are slightly higher abstraction level than normal CSS properties. They don't expose all of CSS but they expose almost everything I've needed to implement designs. And once you start to get rolling and familiar the naming schemes mostly make sense. The docs are good, just search for whatever you need. Clicking around didn't quite get me rolling. I also picked up the Refactoring UI book by the Tailwind folks. That was a good read I thought and it helped get the design-side ideas that Tailwind CSS builds on and sort of match the mindspace of the creators. It helped more than I expected and was a quick read, mostly pictures. So the philosophical similarity to Alpine.js and LiveView? It places the absolute majority of UI concerns at the piece of UI definition you are working on, part of the markup. It does away with semantic and carefully maintained classes in a central CSS file and brings all of the UI concerns into the markup. Again, we define the UI concerns in one place. It is a bit iconoclastic, it can even look quite messy. It is also quite unsurprising. It doesn't hide things, you don't need to hunt for the truth or for some odd combination of selectors. This goes further than what Vue.js did for single file components. I've worked with those and found them an improvement in some ways but it was still a lot of scrolling back and forth between template, logic and CSS. And compared to the SPA + API paradigm it just removes an entire layer of contracts and communication. It still helps you maintain the boundary between this particular interface, the user interface, and the deeper layers of your system. The LiveView is an Actor, it is a natural boundary point. You need the state there and it is well suited to hold that state. Maybe this all falls apart when an application gets bigger but I'm banking on that it won't. You build your reusability with components, rather than CSS selectors and semantic classes. I've been delighted with how these tools come together so far. And at first glance I found LiveView suspect, Alpine.js ugly and Tailwind CSS inscrutable. They really are quite different from how I've been doing things previously and I think that's good. Because that way had a ton of issues. The CSS files turn into sprawling messes over time. The JS frontend SPA becomes a massive system all on its own, duplicating massive amounts of the backend API just to manage local state. I think this has the potential to constrain that sprawl at the component level, remove entire classes of it and make reasoning about state much, much easier. Next I'm curious to look at the Surface library which makes nicer abstractions on LiveComponents for even more of this. I also need to look at what approaches Bruce and Sophie recommend in the LiveView book if I can get to it. Curious if you have thoughts, concerns or experiences with these tools, especially different ones. You'll reach me via lars@underjord.io or on Twitter where I'm @lawik. Thank you for your attention, I appreciate you reading this. - Lars Wikman |