For those that want to know more about Nim, it is "a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula." : https://nim-lang.org/
And HTMX "allows you to access AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext": https://htmx.org/
I love Nim. I been using it professionally for more than 3 years now. At first I started with it just as a faster python with types, but it so much more! You can run Nim everywhere regular places such as backend, frontend, mobile, but also in crazier places like GPU shaders and imbedded.
I also like the community. It's not so big that it feels like you only see people once but not so small that there are no useful libraries written. Just the right size for me. You can always get people to help you out on stuff, reminds me of old IRC days.
> but not so small that there are no useful libraries written...
Says the person responsible for a ton of really useful, well-done Nim libraries, such as this amazing Cairo/Skia-like library: https://github.com/treeform/pixie#readme
I wrote something similar with Go and HTMX. It's a powerful combo, and HTMX is really great for someone like me who is not interested in writing JavaScript. I had to write ~10 lines for this project, but that's much less than doing the whole thing in it.
> In Nim, converters are automatically ran to convert between types if needed.
Huh, this is an interesting take. Instead of taking either of the extremes of "coerce types aggressively" (Perl, PHP, C (kinda)) or "no type coercion ever" (CL (kinda), Rust?), Nim has programmable type coercion, so you can enable it just when you need it.
As far as Nim's dependencies go in this case, it's literally just Karax (no dependencies), Jester (depends on httpbeast which has no dependencies) and treeform's ws library (no dependencies). So the only thing in this chain that isn't transparently being used is httpbeast. Thankfully I've read through that code and contributed a bit to that project, so I can reasonably trust it.
Nim has a smaller community, so the supply chain tends not to be more than one or two levels deep in my experience. This is also because the standard library is fairly large.
If I understood your point correctly you are talking about the binary size?
Me naively compiling with `nim c -d:release` and running `strip` on it gives the server binary to be around 700kb, and it's dynamically linked to glibc. There are tricks and stuff to make this smaller [1], but it's already small enough and easy enough to deploy.
Plus Nim is fast! I can load the index page of this application at 90k requests per second single-threaded on a laptop from a few years ago.
That is a pretty neat result, it looks like with that custom linking magic you can make binaries even smaller. Makes sense if you consider the vast majority of standard libraries isn't actually used regardless of how you link.
There's some odd syntax in this post, which passes colon-delimited indented code blocks to function calls, than control flow primitives. It reminds me of Ruby/Kotlin blocks or Swift's blocks (criticized in https://blog.metaobject.com/2020/06/the-curious-case-of-swif...), but it's quite unusual from my Python/C++/Rust background and I think it's worth explaining in the blog post, since I don't know if it's passing a key-value map/struct or a lambda.
+1 to what planetis mentioned. I didn't include a full explanation of the macro because I was more or less showing off a project - not doing a full tutorial of all of the internal bits and implementation details of what libraries I was using.
So in this case, the `template` bits are doing plain code substitution at compile time, and the buildHtml `macro` is doing more advanced code generation, also at compile time. This means that it should avoid the overhead you mentioned with a key-value struct/lambda.
For what it's worth, this could also have been implemented as a `proc` which would then take in a lambda/anonymous function to generate the HTML, but that incurs additional overhead and requires a bit of extra syntax, which felt like a hassle.
Very, very cool demo! If someone decides to use this for production, don't forget about sanitizing inputs to mitigate XSS, CSRF, etc (and, of course, message storage, authentication, and all those other things.)
(Author here) Thanks! The inputs aren't sanitized in this example, but the output (the generated HTML) actually is in this case. Specifically this part:
text ": " & sentMessage.getStr()
The `text` function in the Karax DSL is actually escaped once it is converted to a string, see https://github.com/karaxnim/karax/blob/c71bc927494418c3f52f9... for the implementation if you are curious. There is a way to render raw HTML using `verbatim` instead of `text` in Karax.
So in this case, I believe it would be protected against XSS to some extent, but I obviously haven't done an in depth security check for a demo/simple project. There are plenty of other potential issues as well (username collisions, websocket errors, user lists) but I judged those to be out of the scope of a simple project like this.
This Nim example is very short. For comparison, I'd created a similar chat service from vanilla Flask and Vanilla HTML (with a tiny amount of jQuery) about 8 years ago and even though it was very basic it took ~500 lines of Python2, HTML, CSS and JS (even though it's only 3 files).
And HTMX "allows you to access AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext": https://htmx.org/