Celestite v0.1.2 - a drop-in view layer w/ support for Vue & Svelte components

Hey everyone - @bcardiff suggested I post here to share a project I’ve been working on the past few months (super super MVP - barely alpha stage):

Celestite is a glue framework that enables you to use Vue & Svelte components as your view layer in a Crystal MVC application. Currently built for Amber, but in theory should work with Lucky, Kemal, etc. The idea is that you focus purely on writing the components, and Celestite handles the server & client-side rendering (So no need for intermediate .ECR templates.)

I’m a self-taught dev, so apologies for any crap code, but this is a WIP and any PRs, thoughts, bugs, ideas, etc. would be hugely appreciated!

Currently working on an example project, and as soon as that’s done I’ll share to give a bit more detail. But the README covers a lot.

Thanks!
–Noah

8 Likes

Great readme! It was great at this stage to find what it provides before how to install it.

Knowing if a component does not requiere mounting on the client-side is something you needed to code or Vue and Svelte provides that from the result of the SSR in a way you can use it?

Thanks man!

What you’re asking about is what the frameworks refer to as client-side hydration – SSR gives the initial component + state, then the client mounts and picks up where it left off. Thankfully I didn’t have to write that from scratch – both Vue and Svelte offer that in slightly different ways. Vue requires a bit more glue code (though they discuss it at length in their SSR rendering guide and basically give a roadmap) and Svelte handles it via the Sapper project, which honestly is a lifesaver here – it does about 95% of the heavy lifting.

2 Likes

@noahlh But what’s exactly the real advantage over using only Sapper or Nuxt for SSR?

I think they key advantage here is that with Sapper or Next (or Nuxt if you’re a Vue fan) are pure Javascript + NodeJS frameworks. So if you’re comfortable writing your full web app in JS and having your server logic all live on Node, then they’re great and you need nothing else. But I really prefer writing Crystal as much as possible, so don’t mind mixing things (hence this framework).

In fact, if there were a way to do everything in Crystal while still getting the full benefit of a client-side reactive framework, that would be heaven. I suppose we need to wait a bit for the WASM target to be fully baked, but that would be perfection.

This is a way: https://shards.info/github/andrewc910/motioncr-demo/
Example in other languages are Phoenix Liveview, Laravel Livevire, Haskell IHP and Hotwire from RoR ppl

Yeah Motion.cr (and Liveview, and Hotwire, etc.) are super interesting approaches for sure.

The thing I don’t love about that approach, however, is that it tucks a bit of magic behind the scenes and I believe that ultimately can be limiting. Motion, for example (not to pick on it - I think it’s really a cool idea!) still requires you install a JavaScript client (import { createClient } from '@awcrotwell/motion'; const client = createClient();) in your frontend code and then handles the UI updates automagically via that client.

The reality is that there is DOM work being done by a framework, be it Motion’s JS client, React, Svelte, Vue, or whatever. And for the time being, that’s the way it needs to be. So my preference is that rather than to hide that work in the background, embrace it and empower the developer to really understand what’s going on.

Svelte, for example, makes no excuses: You have the power to directly manipulate DOM nodes and it’s very clear about what the framework does and doesn’t do. It’s also what I’d call “Turing complete-like” – which is to say not to the true scientific definition of Turing complete, but that there is basically no UI interaction that you cannot make with Svelte (or React, or Vue). It covers the full gamut.

I prefer the approach where the developer has full control (at a native level) of the various pieces of the environment. And for the time being, browsers run on Javascript, so we should do our dirty work in JS in the browser (via Svelte, in my happy place).

But! If WASM fulfills its aim, we will truly be able to compile from anything (ahem Crystal) to WASM and manipulate DOM nodes directly (or, perhaps, interact with Svelte’s API so we can keep concerns separated).

LMK if any of this makes sense :)