Readit News logoReadit News
paveldedik · a year ago
I've been working on a lightweight framework called Ludic that focuses on web development using Python, htmx.org, and a somewhat React-like component approach. It leverages Starlette for performance and the latest Python 3.12 typing features.

Interested in feedback!

* Docs: https://ludic.readthedocs.io/ * Code: https://github.com/paveldedik/ludic/ * Examples: https://github.com/paveldedik/ludic/tree/main/examples

sesm · a year ago
By React-like component approach, do you mean using functions instead of templating language?
paveldedik · a year ago
I think it is somewhat similar to React, for example, you can create a Link component like you can see in the README.md

Now you can use it in f-strings, and well, other components.

The idea from the beginning was to integrate it with htmx.org, so to me, it feels kind of similar when you are writing endpoints using these "components".

But I understand why you are raising this question, I also didn't know how to name it, and React is a completely different framework. I didn't know how to describe the framework in just a few sentences but wanted to somehow. I might change the description at some point.

I still don't know how useful the framework is, I am playing around with it and I like it. Who knows what other people think, though.

// edit - code block don't work here, removed code sample.

danpalmer · a year ago
Nice release! This looks good, docs look really nice too. I'd use HTMX anywhere I can to improve a basic HTML site.

One word of warning for people considering HTMX though – it's not a framework, it's an appliance.

In my experience with it, I ran into problems integrating with HTMX very quickly. Drop it into your project, use the HTML attributes, and it'll be great. However if you need custom Javascript, HTMX provides little in the way of an integration path (the lifecycle events are basic), and nothing in the way of structure, and can even get in the way in places where its lifecycle causes issues in the lifecycle of whatever you're adding. To add your own Javascript you'll almost certainly want Jquery or React/Svelte/etc, and with the latter you'll get interactions between their lifecycles.

If you're using it entirely via the HTML API, and you're happy to accept that sometimes it won't do something, you'll be fine. If you're looking to add units of more complex client-side functionality in places, try prototyping with it to make sure it works well, it didn't for me.

unclebucknasty · a year ago
I think those are all good points, but do cringe a little at the idea that "to add your own JavaScript you'll want React". Seems like a lot to bring in if you're really just wanting to add some JavaScript.
danpalmer · a year ago
Ha, fair point. I don't mean so much that for any JS you'd want to bring in React, but more that something like that will likely be needed to manage a codebase of any scale.

My context here is a mostly server-side application using HTMX, where I wanted to add a few small bits of additional client-side code. I tried to do it without any libraries but rapidly realised that Jquery would simplify things a lot, and managed to do ok with that, but was still fighting HTMX throughout, and I ended up with a lot of poorly managed local state quite quickly. It doesn't take much complexity to need some better form of state management, and something like React provides some direction there, but of course there are other options, my point was only really to say that HTMX will not do any of this for you, and may get in the way depending on what you need to do.

jerrygenser · a year ago
React can be added by rendering into a dom node that's not necessarily the root of your app.

Yes, it can be used to render the entire UI app with rich state management across all pages, routing, etc.

However it can just as simply be used to render 1 complex part of an app that has an isolated but possibly complex state. In this scenario I think sprinkling react is reasonable.

_heimdall · a year ago
I've actually found HTMX to work really well with custom elements for basic interactivity.

If most of your logic is server-side and client JS is kept small, custom elements let you lean on lifecycle events built right into the browser specs.

Epskampie · a year ago
True, I can recommend hotwire turbo as an alternate similar to htmx, it has a js framework called Stimulus that integrates nicely for those instances where you need some custom interactivity.
rokkitmensch · a year ago
django-turbo is awesome, author abandoned it for reasons that I do not quite understand, as it's entirely functional.
cipherself · a year ago
Generating `HTML` from lisps has poisoned any other approach for me, see for example https://www.neilvandyke.org/racket/html-writing/, https://reagent-project.github.io/, and https://edicl.github.io/cl-who/
callamdelaney · a year ago
That's very nice, I wonder if we can write a sort of dsl for this in python.
skgough · a year ago
fermigier · a year ago
aitchnyu · a year ago
Wish GVR updates pyxl4(used by Mixt) and includes it into Python. It could be used for html, xml, yaml and its config language friends and declarative UIs like React. IMO if and for are better implemented in Jinja or JSX better than Python's ternary and list comprehension. Comparison at bottom.

Most of the frameworks here are calling side effects upon shared objects in the guise of `with` statements. Not to mention the extreme verbosity.

> <if cond>

> <long code 1>

> <else>

> <long code 2>

>

> [longcode1() if cond else longcode2()]

>

> <for i in ls>

> <long code 1>

>

>[longcode() for i in ls]

hawski · a year ago
I can only say that I like fast_html and how simple it is. Very easy source to read and understand. It is based on generators internally.

I started using it for some documentation generation purposes. I'm not a web-dev.

jpgvm · a year ago
I encourage anyone looking to do htmx to consider Kotlin and it's excelent kotlinx-html DSL. Lets you do stuff like this: https://github.com/corlaez/kotlin-htmx/blob/master/src/main/...

Disclaimer: Not my code, just an example I found.

smallerfish · a year ago
I second this. kotlinx-html is poorly documented and has a couple quirks, but is fantastic. As I've been building one of my current projects, I've also been building a framework based on jooq + kotlinx.html + javalin + htmx + flowbite (+kotlinjs for a few fancy bits, e.g. the charting library). Aside from tailwind, you end up with a fully typed and compiler-checked application end to end, i.e. no magic strings to be seen. I'm exclusively using HX-Retarget, so the backend is in charge of where things land, meaning that the frontend can do things like:

   div {
      onClick(loadItems)
   } 
I don't know whether I'll ever actually get it in good enough shape to release, but I do plan to blog about how some of the tricks I've found it fitting it together. One thing I definitely need to do before anybody looks at it is clean up how routes and targets are managed.

hjadal · a year ago
That sounds like a lovely way to develop, what is your blog? So I can watch for your post.
Neikius · a year ago
This is a lovely use of the DSL..too bad I prefer plain java.
unclebucknasty · a year ago
Call me traumatized by the Web framework wars, but this seems like the path back to some of the issues that HTMX is trying to solve.

There is a strong developer instinct to "simplify through complexity". That is, to stuff down so much functionality and saw off all edges in an effort to hide complexity. "Let's expose a simple interface that will allow devs to do everything they want to do."

It starts with good intentions and initially provides some improvements in productivity. But it continues to evolve to the point of untenability: the complexity starts to ooze out and become a thing to manage, but with abstractions that make it more difficult; the framework becomes so opinionated that it begins to stifle; performance issues are introduced as we drift farther from the metal.

We continue to try to solve with newer constructs and abstractions, frequently introducing more issues. Eventually, it comes full circle ("hey, let's add SSR!"), and we're again looking for another solution. One that's simpler.

Then the cycle starts over again.

I think there is an inflection point with all of these things, wherein whatever perceived productivity gains are had by pushing more functionality into the framework quietly begins the path to regression. I don't exactly know where it is, but I would bet that it happens far sooner than we suspect.

So, I kind of like HTMX where it is, in spirit and implementation. Whatever additional productivity I can pick up via helper functionality and reuse is something I believe there is value in devs doing on their own, for their individual use cases and preferences. There's a tendency to think "well why reinvent the wheel? Let's make it a framework". I've come to believe that impulse is somewhat pernicious in its effect. Ultimately we're going to have to write our own code at some point. I'd suggest that we're better off doing it much sooner than frameworks encourage.

m_rpn · a year ago
Spot on, in my opinion we need at least a 10 years ban on the creation of any new web framework of any kind. Hope that AI coders will make frameworks obsolete, but maybe i'm crazy :-).
rmbyrro · a year ago
I don't know, every time I see people sneaking html into Python feels weird and wrong to me...
kissgyorgy · a year ago
Until you try it out and realize the benefits!

- Type safe HTML: you get an exception instead of malformed HTML

- Truly reusable components: any Python web framework, component packages are truly reusable in any other projects. I never seen this with template engines.

- Huge productivity boost: not even close! No hunting for templates, no jumping between files, everything is in Python functions.

- Composable elements: you can nest things as much as you want, refactor very easily. Doing this with templates is not even possible, or such a pain I never did it.

- Storybook: There are a couple ones for Django, but they are clunky and not reusable at all.

I felt the same for a long time, but started thinking about a nice API. It took me months, but I finally got it: https://github.com/kissgyorgy/compone

mixmastamyk · a year ago
Yes, I quite like the idea of being able to run pyflakes/flake8/black/pytest/mypy over my "html templates", and benefiting from all the power that entails.
grrandalf · a year ago
Insightful summary. Thx.
rougemine · a year ago
It feels weird at the beginning, but after a bit of practice I found it pretty nice to write HTML in Python.

Here is an example of a HTML page layout written with the DOMinate [1] library for example, in a "JSX-like" way:

https://github.com/olivierphi/zakuchess/blob/main/src/apps/w...

It may hurt your eyes at first sight, for sure... But similarly to technologies like Tailwind CSS, it's mostly a matter of getting used to it - and after a while it end ups feeling very natural to use :-)

1: https://github.com/Knio/dominate#readme

VagabundoP · a year ago
Dominate is quite fast as well. I did a few tests vs jinja for my flask app and it beat the pants off it.
icyfox · a year ago
I imagine a lot of this comes down to personal preference. In the early days of Mountaineer [^1] (gee, almost two months ago at this point), I played around with the idea of embedding html into python instead of needing a JS layer. Eventually my consensus was:

- The most flexible shim approaches typically end up wrapping JS/React components anyway (like Reflex/Pinecone)

- We really need better IDE support for html strings that are within python strings. The editing problem is a big setback.

The ergonomics of Python + JS in separate code files won out and the user experience has been better than forcing them both into a common language would be.

This has the benefit of leveraging whatever the two languages are best at, in native code, so you have access to all the native APIs without having to learn a shim on top of it. Way more longevity to that approach too. Context switching between two languages isn't that bad if you minimize the glue layer that you have to write between them.

[^1]: https://github.com/piercefreeman/mountaineer

AsthmaBoy · a year ago
I agree and I don't fully understand the why of it.

I remember coding PL/SQL to emmit HTML in Oracle around 1999 or 2000 and using functions to code the various elements.

That got old and repetitive very quickly - for instance, everytime I had to correct a spelling error, I had to recompile the code.

To get around it I used one or two tables to hold html snippets to decouple the business/backend logic from the frontend, and stopped using the PL/SQL functions completely.

My speed of developmet skyrocketed, and separating and abstracting the frontend from the backend made so much sense.

A few years later, I was doing web developemt with Python using the Zope framework (not many people know about it tiday, I think).

It uses a specialised serverside templating language called TAL (Template Attribute Language)[1] that basically builds the front end dynamically, and then you feed it data from the backend.

Very neat and allowed me to build reusable compoments as well as collections of a schema definition (basically a dict), html template(s) and the code to validate that the input matched the schema and could be rendered.

Or something like that - its been 2 employers and almost 20 years since I worked with that :)

I did build a small extension for Wordpress using a PHP implementation[2] of TAL a few years ago, and TAL still works like a charm :)

My point is that I still believe there is value in keeping python out of the html-templating, and in keeping the front end logic apart from the backend logic.

There is something I am not understanding about the renewal of mixing HTML/GUI template with code, but I haven't fully found it yet.

[1] https://en.m.wikipedia.org/wiki/Template_Attribute_Language

[2] I believe it was this one https://phptal.org/

paveldedik · a year ago
Yeah, I understand that. Now that Python 3.12 has better support for f-strings, I thought there might be a way to make it possible. But I am still not sure it will work. There is a pretty weird hack to make f-strings work while avoiding the possibility of rendering unsafe user input.
creshal · a year ago
It's nice for small hacks, but for anything longer than a couple dozen characters you're probably still better off making jinja2 (or similar) templates as painless as possible.
andybak · a year ago
Do you feel the same about sneaking html into javascript? Just curious if it's a Python-specific objection.
legutierr · a year ago
In general, this usually results in front-end logic being very tightly coupled with back-end logic. In some of the examples given, you even have database access in the same line that is generating the HTML document.

https://github.com/paveldedik/ludic/blob/main/examples/click...

It's the kind of thing that looks very cool and concise in small examples, but tends to become a nightmare when you are working on larger projects.

shinryuu · a year ago
same feeling there tbh. Though generally, when it's done in javascript it's done completely in a string, without javascript objects.
whalesalad · a year ago
recall python server pages ... good old index.psp
kissgyorgy · a year ago
I also started working on a Python Component library, but it's fully independent of any web framework, and you can generate XML/RSS with it too. I'm using it for months now, I will release the first version soon: https://github.com/kissgyorgy/compone