
Francisco Moschetti
Why hono is winning my ❤️
Django will always be my go to framework for any real project I do, but…
I have to say that my recent experience developing tinyletters with Hono and HTMX has been amazing.
I think JSX makes the experience of developing server driven applications way better because of a very simple reason.
The small stuff
I’m not a fan of how in Django you don’t really know what is being retrieved in a response.
Sure, you can check the template source code, or have a very descriptive folder structure to be able to differentiate between a partial response and a full template response.
Django cotton helps you a little, because it requires a fixed ‘cotton/’ directory to store the components so it’s easy to identify what is being returned.
But with Hono (any JSX BE really) that is completly different because you can ‘construct’ the reponse right in the view.
def login(request):
template_name = "views/login.html"
return render(request, template_name, {})
app.get(
"login/"
(c)=>{
return c.html(
<Layout>
<LoginForm/>
</Layout>
)
}
)
In one you assume the template has the full view, in the other one you see how the view is constructed and what components are being used. you can go one step further and indicate the hx-post attribute in the component attributes too and that will make it an awesome experience working with HTMX.
It’s a subtle difference but as your app grows, small things like these can help you navigate codebases faster.
Oh and i’m completly leaving out the fact that the route is explicit in Hono by looking at the view, while in Django you’ll have to find the urls.py file that is pointing to the view function.
Now in this example let’s assume you have an endpoint where you do your post and you return the form component if there is an error, and a redirect if successful.
""""
You can add a POST handler in the original view,
but I prefer unique views for htmx post requests most of the time.
"""
def hx_login_submit(request):
template_name = "partials/login_form.html"
if request.method != "POST":
return HttpBadRequest()
form = LoginForm(request.body)
if not form.is_valid()
return render(request, template_name, {form:form})
return redirect(dashboard)
app.post(
"login/",
(c)=>{
const payload = c.req.valid("form")
const {isValid, errors} = checkUserEmail(payload.email)
return c.html(
<LoginForm {errors}/>
)
}
)
See how it’s easy to tell in wich cases you are doing a simple component response vs a full view? In django if your folder and template naming conventions aren’t spot on, it’s hard to tell. I know it’s a minor detail but it’s worth pointing out.
The important advantage.
In Hono you can use Turso as your DB infra, and connect using Drizzle. A very sqlesque ORM with low abstractions.
This matters because it means you can deploy a true edge application with almost 0 config or heavy lifting on your end by using fly as your infra for the app. Simply replicate your db to the same locations as your app and that’s it. (Turso let’s you choose between fly and aws during setup)
So your db and app replication will match, making queries way faster by bringing everything closer to the user.
In Django there is no official support for libsql yet so using turso is a little weird. You can still deploy to fly of course but you will probably need to set up a fixed location close to your postgres db.
Conclusion
I like both, and Django’s future is super promising + the admin panel makes it a no brainer for real world stuff, but I think for some small apps Hono will be a solid option for me now.