Creating an Inclusive Django Community with Kenya Phelps
Published July 15, 2026
This video features Hernan Lozano at DjangoCon US 2024 in Durham, North Carolina, USA.
We pay great attention to how to write composable python code (with inheritance, decorators, modules, namespaces, etc). But when it comes to architecting the templates of your website, this is often overlooked, which rapidly degenerates in tons of copy&paste of html, css and javascript.
Some might say that this is what React or Vue (et al) are all about and already solve, but having to render HTML on the client can increase the complexity of the application (introducing build steps, another language, more dependencies, etc).
Writing reusable and composable UI components can be achieved using the good 'ol django templates, with the help of some libraries to fill in the gaps (like django-components, django-cotton and TailwindCSS) that we will explore and suggest as a possible solution.
This talk was presented at: https://2024.djangocon.us/talks/reusable-django-template-components-for-perfectionists-with-deadlines/
LINKS:
Follow Hernan Lozano 👇
On Mastodon: https://fosstodon.org/@hernantz
Follow DjangoCon US 👇
https://fosstodon.org/@djangocon
https://x.com/djangocon
Follow DEFNA 👇
https://www.defna.org/
Video production by the presenter and DjangoCon US 2024 volunteers.
Hernan Lozano argues that Django projects can avoid the accidental complexity of a separate React or Vue front end by using a pragmatic, server-rendered architecture. He recommends HTMX for server-driven interactivity, Alpine.js for small client-side state changes, Tailwind CSS and daisyUI for maintainable styling, and component libraries such as Django Cotton or Django Components for reusable, composable HTML widgets. The approach keeps state, validation, business logic, and rendering close to Django while still supporting interactive interfaces, and he points to related options including template partials, Django Unicorn, and FastHTML.
Summarised automatically from the transcript.
Automatically transcribed, so expect mistakes in names and technical terms.
Carbon Hello and welcome to my talk UI Components for Perfectionists with Deadlines. I prepared this talk because building a maintainable front-end architecture is a common problem any Django project needs to solve. In Django we have ways to architect our code into reusable apps, views, and models. But when it comes to the front-end side of things, it's not necessarily strongly opinionated on this matter. Let's see what this means and what we can do about it. There is a famous saying that states that anyone can build a bridge. It means that anyone can just throw money, people, energy, take their time, and eventually something will be built. But it takes an engineer to build the right bridge timely and a budget.
This applies to any kind of project that needs to take you from where you are to where you want to be, like a bridge does. And software projects are not the exception. As engineers, we must understand that we live in a world of constraints and trade-offs Every project has a complexity budget and that means that you need to care about what features are worth building and how to spend your time and resources. Budgeting your efforts is not an easy task and you need to place your bets wisely. Unless you are on the edge of innovation, most of your problems might already being solved. You just need to stand on the shoulders of giants. Or ride unicorns rather. There is a reason Django's pet used to be a lovely winged pony, and there is a reason why its motto it's a framework for perfectionists with deadlines.
After 19 years as of today, it is still a solid and cohesive framework that solves most of your problems with great documentation, an awesome community, authentication. an admin interface, an ORM, migrations, permissions, routing, third-party extensions for everything else, and it's 90% of what you ever need. But like we said, it doesn't have strong opinions on how you build your front-end architecture. Sadly, this left an empty space for other frameworks and solutions outside our love Django universe to take place. It is still very common to see pronounc heavy frameworks like View or React used for this. But these frameworks introduce a ton of accidental complexity State management and synchronization between your front
end and your back end is now a big deal. API churn becomes a problem. This is how much data you expose on JSON endpoints. If you expose too little, now you need to hit many endpoints to render a single screen. If you expose too much, now you might be leaking data or making the endpoints slower for unrelated pages. Your team skills are now divided, hiring is more complicated, more coordination is needed, and your code base is now polyglot Which is harder to maintain. There is duplication of business logic and validation, framework works still common with a ton of changes version after version, causing some fatigue Um you introduce more build steps, more dependencies, more repositories, you need to keep an eye on load times and time to interactive like
metrics. And it turns out that you still need to make the database query and render that HTML after all. We say that history doesn't repeat itself but often rhymes. Well guess what? Luckily for us, in the recent years the tides are turning. Postgres was the database you needed, monoliths are not seen as something necessarily wrong, and server-side rendering is cool again So let's rethink this front-end architecture, but this time with the Django-centric approach. What are the problems a good front-end architecture needs to solve, anyways? For a modern front-end you need three pillars. First, interactivity, to dynamically display or update fragments of the page. Then a maintainable and composable CSS framework, and lastly a way to create reusable snippets
of HTML. Let's explore each in more detail. For interactivity, I chose a tiny library that is becoming very popular called HTMX, which by adding some attributes on your HTML templates lets you interact with the server and update portions of the page The server knows the state of your data, it has all the business logic, all the validations, and a privileged access to the database. The client, your browser, simply needs to request it and since it already understands HTML natively, it will draw the UI for you. The browser becomes the front-end application or client, but one you didn't have to program yourself. In this case, I'm showing that within the element declaration,
You can specify all you want this element to do without the need for writing JavaScript on a separate file. Everything is contained within the same template In this case, the button will perform an HTTP request to the slash clicked endpoint, and whatever the HTML the server sends back is gonna be placed on this uh target element which is in this case the div indicated there. Now not all the interactivity implies the need to reach the the server. There is also the need for client-size state manipulation as well. For example, disabling a button, showing or hiding a drop down, clearing a form, these are all UI interactions that do belong to the front end
This is where a small library like Alpine. js shines, which like HTMX also follows the same pattern of inlining directives as part of the HTML element declaration. In this case, the data being declared is a counter and it's scoped to the this div element and all its children element. When the button is clicked, the counter is incremented and automatically the span below will reflect its value thanks to another directive. Moving on to the next pillar in our front end is the styling. If you are like me and struggle to center a div on a page, you will agree that CSS is hard. CSS is a global mutable object that every browser interprets with their nuances.
It's easy to start writing spaghetti styles, making your style sheets hard to maintain by using generic names for your classes. Yes, naming is hard, that can cause collisions later on on different pages. Classes might be doing too much by mixing layout definitions with coloring or spacing styles that aren't responsive. And then you need to add super-specific selectors to adjust the rules for each page. You will notice that this probably implies that you might be building an in-house styles framework. Is it well documented? Is it responsive enough? A better question I would ask would be, this has to be a solved issue, right? A very popular tool nowadays is Tailwind CSS, a utility-first
CSS framework that provides a well-documented set of composable classes. With some sane yet customizable defaults that you can cherry-pick and combine. These classes provide utilities for managing everything from spacing, coloring, responsive layouts, transition effects, etc. Yes, it looks like a ton of text on the screen, but this is an approach called atomic CSS, similar to the locality of behavior principle used by HTMX and Alpine. js we saw before where you have all the context you need inline when working with a piece of your codebase. And yes, I know you might be asking, do I have to copy and paste all this text every time I need a button? And the answer is of course no. In case you wanted to reduce repetition, one way to do so is to extract some styles into a single class and give it a semantic and descriptive name like button primary.
This is well documented on the Tailwind CSS talks. But if you abuse of this technique, you will be recreating the styles frameworks again. And remember, we have deadlines to meet Better off, we want to stand on the shoulders of giants. This giant is called DayCUI. It is a CSS library built on top of Tailwind, and it's one of many. It offers many of these well-documented descriptive and semantic class names that you can also theme and customize to use on your templates. I'm start giving this button a base style by applying the button class, but also I'm specifying which type of button this button should be by specifying a modifier class. Also provided by DACUI, which is the button primary.
And remember, DACUI is Tailwind CSS after all, so you can mix these classes with regular Tailwind CSS classes Another way to reduce the repetition of classes is to think in terms of widgets and components. This UI also provides a ton of widgets like cards, tabs, profile pictures, and forms ready to use The thing with widgets is that they often include a mix of CSS and HTML in their structure. And sometimes you need to have variations of those widgets, like having a product card widget show a button or some tags. depending on which page or section this card is being displayed on. Like we said, a component might combine different HTML elements in some hierarchy or structure and require some styles on those elements.
The structure in this example includes some containers like a card and a card body divs and some child elements with the card title and card actions classes. How would you turn this into a reusable template in Django? Django already comes with a template engine that is pretty powerful. We can parameterize text or variables like the title and the description of the product, but what about the child HTML nodes like the card action section? Can we make those elements replaceable We have flow control directives for conditionally rendering different HTML snippets. In this case, we will need to add each possible child element in an if-else block. And then in the template where we want to display the product card, we need to pass what type of child widget we would like to render using the built-in
include tag. The problem here is that every new possible variation of this widget would require us to modify that ill-felds structure we implemented earlier. Alternatively, we could create a base template with certain block tags. This is something very common for page layouts, but the technique can be used for widgets as well. In this case, I added an actions block that can be extended by other components to place anything in there. So then we can use the extends template tag to create each variation of this component or widget. In this example, this would be the product card that shows a button in the Actions log We can finally include this new widget anywhere by referencing its template name.
This way we elegantly solve the extensibility of the base product card for any type of actions we need. But again, this might result in having multiple instances of templates for each variation of this widget. Is there a way to still write decoupled and reusable widgets templates for with minimal overhead Yes, this is a solved issue. A better solution for writing widgets as components that have small variations is to use a component library like Django Cotton. In this case, we are using regular template variables for the title, but you will notice that we are referencing the actions variables as a block, and that there is also a slot special variable or placeholder. By placing this template in a special location in your project, this library suggests using the cotton folder inside your app
's structure. You have created a reusable component. It's that simple. If you named the template something like product. html and you placed it in the right location, You will now have access to a special tag derived from that name to create instances of that component. In this case, the component will be named c product. And you can still pass variables as text for the title, but you can also inline any HTML like the p tag for the description of this product. And this is the content that will replace the unnamed slot variable we had defined in our base component. You can also reference other variables using the c-slot special element And this will be interpreted as a named HTML snippet that will replace, in this case, the actions placeholder inner
based template. With this approach, we can instantiate and define any number of variations of our product cards in line and without any modifications to our base templates. You can also nest or embed components into other components. In this case I'm showing that the button inside the actions slot Could be a separate component. This allows for a great deal of composability in all our widgets in our project. I would like to also mention that Django Cotton is one of many libraries competing in this market Django Components has a very similar set of features but uses a Python class first approach, similar to how we work with forms or views. With many methods that you can override and a registration mechanism like how we work with Django admin
views. This is how you could define the same product component we use for Django Cotton, but in this case you will notice that we need to take some extra steps to set up this component. Basically you will need to set tell it which template it should use. Tinker with what contextual data you can pass to the component. And lastly, it has a way to tell it which extra CSS or JavaScript tags it should include. Here is an example of how you render it. You load the library tags and you specify the component's name and the parameters it can receive, while also placing some HTML in the component's placeholder by using the field template block.
As you can appreciate, this syntax is much closer to how other template tags are used in Django. And this is what I would like to highlight about this library. It follows similar approaches to how other Django utilities are used. Now we have covered all the pillars we needed for a modern frontend architecture. This is the front-end I would suggest for perfectionists with deadlines. By building on top of what Django already provides, I believe this is a more pragmatic and competitive approach, without too much overhead or any of the accidental complexity we mentioned at the beginning I would claim that all these technologies you can learn and master in a weekend, and what's funny is that in their talks they have references and examples of how they interoperate with each other.
I would say that HTMX and Tailwind are very solid choices now, and we shall see which component library gains more popularity for Django. Ideally, some of these libraries To define and manipulate reusable components, make it into the framework as an included battery in the near future. I would like to mention some other libraries that are worth checking out. There's Django Template Partials that lets you define and render fragments of templates, which works great when used with HTMX for partial page updates. And also Django Unicorn that mixes the idea of components with templates and views that can be updated dynamically. Another noteworthy mentions, but this time related to other talks in this conference, that address similar topics are the ones listed in gear.
There's API maybe by Carton, Django Altmine, HTMX, Ups and Downs by Karen, Juicing Wisely, SPA versus HTMX by Chris. And one that addresses a very important topic I purposely left out of my talk because it would be lengthy otherwise. It's an opinionated guide to modern Django Forms by Josh. All these talks are discussing some of the technologies I presented and should give you the encouragement to start playing with them and appreciate that There is a need indeed for an alternative and much simpler architecture for front ends. One more thing I think it's interesting to consider is that there is a very recent project called Fast HTML.
It is yet another Python web framework, but this one has a very different approach for solving the UI composability problem. If you think about it, templating HTML is no different to building a tree of nodes. So why cannot we use Python for this? By using Python for building your template structure, you no longer needed to learn a new syntax or place logic in separate files. You have access to all the language constructs like classes, functions, decorators, lambdas, etc. And your favorite debugger now works. I don't think something like this will ever make it into Django since it's already married to template, but it is an interesting idea nevertheless. These topics I presented are something I wanted to share with the community for a while, so I would like to thank the organizers of DjangoCon for this opportunity and all of you for listening.
Hopefully you take some valuable insights from this talk to share and discuss with your teammates and maybe implement in your next project. My name is Hernan. I'm assistant Django Nout and Python dev from Argentina, which loves anything related to software engineering and architecture in general. So don't hesitate to reach out should you have any comments or questions about this talk or anything. You can find me on X and post it on as Arnans. And with that, I'd like to thank you all and till next time. Oh no, no, no.
They can introduce state synchronization, API design and churn, duplicated business logic, divided team skills, extra build steps and dependencies, and a more complicated polyglot codebase. You still ultimately need to query the database and render HTML.
Discussed at 1:48The talk identifies three pillars: interactivity for updating parts of a page, a maintainable and composable CSS system, and reusable HTML snippets or components.
Discussed at 3:21HTMX uses HTML attributes to request content from the server and replace a targeted portion of the page. The server retains the data state, business logic, validation, and database access, while the browser renders the returned HTML.
Discussed at 4:09Alpine.js is suited to small client-side interactions that do not need a server request, such as incrementing a counter, disabling a button, showing a dropdown, or clearing a form. Its inline directives keep the state and behavior in the HTML.
Discussed at 5:42Tailwind provides documented, composable utility classes for spacing, colors, responsive layouts, transitions, and more. Its atomic approach keeps the relevant styling context close to the markup, while DaisyUI can provide higher-level themed component classes on top of Tailwind.
Discussed at 7:13Django Cotton lets you define a component template with variables and slots, then instantiate it with a component tag while supplying inline HTML or named slot content. Components can be varied and nested without modifying the base template, making widgets composable.
Discussed at 11:21Django Cotton uses component templates and special tags with slots, while Django Components takes a more Python-class-first approach, similar to Django forms or views. Django Components also supports registration, contextual data, and declaring extra CSS or JavaScript assets.
Discussed at 13:49The suggested pragmatic stack builds on Django with HTMX for server-driven interactivity, Alpine.js for small client-side state, Tailwind CSS and DaisyUI for styling, and a Django component library such as Cotton or Django Components for reusable markup.
Discussed at 14:37Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 15, 2026
Published July 14, 2026