Experimenting with FastHTML and HTMX

fasthtml
htmx
Author

Alex Kelly

Published

September 18, 2024

FastHTML logo

Introduction

Welcome to my thoughts and learnings from developing a FastHTML app. I wanted to learn a web technology that is simple and fun, allowing me to focus on my main project. It feels that there is currently a gap in the market for a web technology focused on simplicity and ease of use, with an emphasis on the developer experience in the AI age—an “AI stack,” if you will. My aim is not to be the best web developer but to have fun and create a front-end or a shop window for my projects. That’s not to say I don’t want beautiful presentations, but I want to focus on the ML and logic without getting bogged down in a complex web development project that doesn’t work well with LLMs.

I’m writing this to understand and solidify my understanding of FastHTML/HTMX and, as a consequence, provide a guide for anyone who wants to try FastHTML. I worked on this blog while reading the book Hypermedia Systems, building the web app using FastHTML, and watching various videos including those by the makers of FastHTML, such as FastHTML overview, FastHTML tutorial, FastHTML deep dive, and FastHTML comparison.

Introduction to FastHTML

FastHTML is a new framework for building HTML applications designed to be fast and easy to use without templates. You write Python functions that send HTML to the client browser. The key technologies the library brings together are:

I won’t dive too deep into Starlette and Uvicorn, but I will focus on HTMX and how Python is used in this stack.

Expanding on HTMX

I recently had to develop an application in a full-stack framework, and it was a frustrating experience. There are multiple programming languages, and the server, database, templating engine, and frontend are all separate things that need to be learned and interrelated. FastHTML using HTMX eliminates the need for this complexity by creating HTMX elements that are processed on the server and sent to the client browser. There’s no need for a frontend framework like React, just Python functions and HTMX attributes all in one Python script to make rich web applications. This makes it much easier to learn, understand, and maintain. You can read more about HTMX in Carson Gross’s free book here, where he talks about HTMX in more detail and places it in the hypermedia concept. Some of the benefits and drawbacks of developing with HTMX-style web apps are below. This is not a comprehensive list but just some points I made while learning to understand the boundaries and capabilities of HTMX and, therefore, FastHTML.

Benefits:

  • Simpler Frontend: Reduces complexity by eliminating the need for heavy JavaScript frameworks.
  • Faster Development: Easier to implement features and fixes due to simpler code.
  • Easier Onboarding: New developers can quickly contribute without learning complex frameworks.
  • Minimal JavaScript: Allows for dynamic features with little to no JavaScript.
  • Easy Integration: Can be added gradually to existing projects without major changes.
  • Better Performance: Avoids over-fetching data, leading to more efficient page updates.

Drawbacks:

  • No Clear Best Practices: Lacks established libraries and guidelines like a establishd framework React.
  • Not for All Use Cases: Poor choice for offline apps or complex client-side interactivity. However, for complex client-side interactivity, you could just use a frontend framework like React for just that part of the app.
  • Enterprise Scaling: Limited evidence on how it scales for large teams or codebases.

Key Concepts of FastHTML

  • FastHTML is a functional approach to creating web apps; it has a one-to-one mapping with HTML elements. For example, a Div() function is a div element in HTML, and a P() function is a paragraph element in HTML.
  • Seamless integration with existing code: Any Python library or code you already have can now have a web UI using FastHTML.
  • Simplified code: Replacing JavaScript with hx attributes in HTML makes the code concise and easier to read and understand.
  • Minimal setup:
    • Create a web app with just one Python file for the app.
    • If you need a database, one additional file for SQLite that can scale to thousands of users.
  • Locality of Behavior: Carson and Jeremy talk about locality of behavior; anything relevant to the site or route you are looking at is displayed in that file, not spread across 20 other files.

Tips for Getting Started with FastHTML

  • It’s a new library, so visit the documentation and Discord; the community help is great. As of writing, it’s not in any of the top LLM chatbots’ weights, so to be able to chat and ask questions and get a good quality answer, the people at Answer AI have created a text file for LLMs—just add to Claude or any other LLM to get a good quality answer.
  • Start a project by modifying one of the examples in the gallery and keep changing and adding features.
  • Read the HTMX book (it’s free); it will help you understand the concepts of HTMX and how to use it.
  • Post in the Discord channel for help; the maintainers and other users are very helpful.

FastHTML by Example

This is a demo of the “Hello World” app and another slightly more complex example that shows how to add HTMX attributes and inline CSS.

Hello World

This is a simple example of a FastHTML app that displays “Hello World!” when the user navigates to the root URL. I use uvicorn main:app --reload to run the app, which will display a link in the terminal. Click to open in the browser and display the “Hello World!” message. This is the minimum code to run a FastHTML app, which gives you a starting point to iterate on. Read the docs here for more tutorials and examples.

1from FastHTML.common import *

2app, rt = fast_app()

3@rt('/')
4def get(): return Div(P('Hello World!'))

5serve()
1
Importing necessary modules from FastHTML.common
2
Creating a FastHTML application
3
Defining a route for the root URL. This is the first page the user sees when they navigate to the domain.
4
The Python Div() function is used to create a div element in the HTML, which in turn contains the P() function used to create a paragraph element in the HTML. This returns both of those HTML elements with the text “Hello World!” inside of them.
5
Starting the server and running the application.

Adding HTMX Attributes and Inline CSS

1from FastHTML.common import *

2app, rt = fast_app()

3@rt('/')
def get():
4    return Div(
5        P('Hello World!', style='color: blue; font-size: 24px;'),
6        Button('Click Me', hx_get='/clicked', hx_target='#message'),
7        Div('', id='message')
    )

8@rt('/clicked')
def clicked():
9    return P('Button clicked!', style='color: green;')

10serve()
1
Import necessary modules from FastHTML.common
2
Create a FastHTML application
3
Define a route for the root URL
4
Return a Div containing multiple elements
5
Styled paragraph with blue text and larger font size
6
Button with HTMX attributes for dynamic interaction
7
Empty Div as a placeholder for dynamic content
8
Define a new route for the clicked action
9
Return a green paragraph when the button is clicked
10
Start the server and run the application

Conclusion: Would I Use FastHTML?

Creating web apps is an important and useful skill to market your work and yourself. To answer the main question: yes, I would use FastHTML for future projects. It allows me to create powerful web apps where I can start small and scale up to whatever size I need. I’m enjoying learning about the technology stack and, more importantly for me, getting some Machine Learning web apps up and running to solve real-world problems or entertain users.

In the end, FastHTML and HTMX have made web development more accessible and enjoyable for me. It’s like having a toolbox where all the tools fit perfectly, and you don’t need an instruction manual to figure out which one to use.