State & Plans of GUI development with Crystal

Does it not have the following potential drawbacks:

  1. The GUI has to be written in JS (or compiled to web assembly)

  2. The data has to be copied back and forth between the app and the front-end hosted by Webview.

  3. The communication between the app (back-end) and the Webview part has to go via a network port (loopback), which is potentially slow (and hackable).

Good questions!

  1. This is a positive aspect instead of a drawback.

Writing GUI directly in HTML/CSS/JS is one of the very few ways to provide fully consistent UIs with responsiveness, among completely different devices, resolutions, DPIs and operating systems.

It works consistently on every minimally capable device in the world, today and in the future.

  1. When done right, this is a good practice.

Having an independent layer for the UI is a good step in direction of separation of concerns, thus, it’s a good architecture practice (like front-end apps that communicates to back-ends through their APIs).

Also, it helps with mobile app encapsulation through Cordova or Capacitor. It can be extremely lightweight and fast as native when (1) reusing the mobile OS web engine (as webview on dekstop) and (2) when using a good processing model on JS side, like Svelte does with real reactivity.

  1. This is not the only way.

We can use the same strategy of Tauri (see security), where they use the webview library but with no server nor open ports, using only the two-way language bindings for communication.

It’s fast and secure.

Also, the Crystal webview port from naqvis (GitHub - naqvis/webview: Crystal bindings to Webview library) provides this two-way binding as well. So, no server is needed.

3 Likes
  1. Would it not be possible to generate JS or TS or Wasm from Crystal in order to have only one language server side and client-side ?

  2. Does Crystal compile into JS or Wasm ?

  3. How would you pass the data back and forth : JSON or something similar ?

If you use a framework like Axino (Getting Started With Axino. A crash course in app development using… | by Serge Hulne | The Startup | Medium) or Mint (https://www.mint-lang.com/), it will minimise the number of languages to deal with (client-side), otherwise you’ll have to juggle with Crystal + HTML + CSS + JS.

PS: The advantage of Axino (my experimental TS framework) is that an app written with Axino is 100% TS, so:

  • No complex bundler (no webpack config files). Jut Parcel.
  • It is compiled and packaged in one simple step.
  • There is compile-time check and type check etc. so it is basically safer than JS (and works better with VSCode).

But as I said in my previous post, it would be even simpler if it was 100% Crystal (if crystal could generate the JS or Wasm code needed on client-side).

1 Like

Since Webview for Crystal also has an eval() function in addition to the bind() function, it is theoretically possible to skip JS entirely by generating the dom elements one needs from Crystal, as follows Question : example of use of : webview::Webview#eval · Issue #6 · naqvis/webview · GitHub

This would make it possible to create apps in 100% Crystal (no HTML, CSS, JS, etc. needed for the users or the library).

In other words, it is possible to create 100% isomorphic apps (i.e. using Crystal on the « server-side » as well as on the « client-side »), hence resulting in a true app development kit 100% in Crystal.

To to put it another way : by using eval() and bind() the dom and its behavior (responding to events) can be written in Crystal, provided that the one creates a library which creates all the needed DOM elements from :

Crystal + eval() + bind()

Another way to look at it is : All that is needed to achieve an isomorphic app développement kit in Crystal / Webview is a an equivalent to Axino (or something similar) translated from TS to Crystal (which is a bit tedious to do, but not complicated).

2 Likes

This an interesting and also technically valid approach :)

I did the same thing for Golang (build a isomorphic GUI kit for Golang, which wraps JS code into Go functions):

  1. Using GopherJS.
  2. Using Go to Wasm compilation (transpiling).

And it works as expected.
(I have not published that code, because it is not ripe, but as an experiment it works)

I will try to test the concept with Crystal, as soon as I can install Webkit for Crystal on my Mac (does not work at the moment: I filed a bug report).

6 Likes

Actually Webview for Crystal works fine (I was using an outdated version of Xcode)

2 Likes

Little late to the party but here it goes.

As of 2024, I’ve been working on a GUI library from the ground up.
It has fairly different design goals than other GUI frameworks that I’ve seen and the layout rules are quite different.

showcase

Features include

  • composable reactive components that can be templated together.
  • exposes a drawing API for freely rendering shapes / text / etc
  • decoupled from a backend (although currently only supports raylib out of the box)
  • automation capabilities baked in
  • some basic components provided

The library privileges the ability to easily create components as opposed to providing them. There is also support for font clamping/wrapping.

I’m in the process of learning a lot about a lot of technology I’ve taken for granted (a lot of ground to cover), so conversations are preferred over PRs and development will be a medium-slow burn.

If anyone wants to learn more, I put together a demo for a friend. (Thanks to nuclearbananana from reddit for compressing it). There are a few misteps and inaccuracies, but you’ll get the gist easily.

https://file.skinnyjames.net/hokusai-demo/index.html

Project is on codeberg

5 Likes

Why do you define UI and layout through templates (loosey strings, full of typos, which you need to parse at runtime?) and not through some similar nice DSL (pure code, checked by compiler)? What led you to this design? Thanks!

Hi, thanks for the criticism. I’m not sure what you mean by loosey strings full of typos, but the templates are parsed on mount. once. Decoupling the template from the code means that the code can focus on behavior and the presentation requires much less typing. Does this help?

Really happy to see non-html non-JS GUI work happening in crystal!
I hope you continue to have fun and keep working on it!

3 Likes

Another one that is not really a GUI framework but rather a step below it is GitHub - yxhuvud/wayland_client: A basic wayland client library. , which provide wayland client bindings with a thin convenience layer on top.

1 Like

A post was split to a new topic: Following users

I’m not sure what you mean by loosey strings full of typos,

I guess i can use some doc for lucky (it write template use purl Crystal) for explain what pfischer means.


Lucky uses Crystal methods for rendering HTML. The Crystal methods map as closely as possible to how HTML is used.

Using Lucky HTML adds an additional layer of type-safety, is auto-formatted with Crystal’s formatter, and can be much easier to refactor with regular Crystal methods as HTML gets larger.