Lightweight framework for building dynamic HTML pages in pure Python.
Project description
Ludic
Documentation: https://ludic.readthedocs.io/
Ludic is a lightweight framework for building HTML pages with a component approach similar to React. It is built to be used together with htmx.org so that developers don't need to write almost any JavaScript to create dynamic web services. Its potential can be leveraged together with its web framework which is a wrapper around the powerful Starlette framework. It is built with the latest Python 3.12 features heavily incorporating typing.
[!IMPORTANT] The framework is in a very early development/experimental stage. There are a lot of half-functioning features at the moment. Contributions are welcome to help out with the progress!
Features
- Seamless </> htmx integration for rapid web development in pure Python
- Type-Guided components utilizing Python's typing system
- Uses the power of Starlette and Async for high-performance web development
- Build HTML with the ease and power of Python f-strings
- Add CSS styling to your components with themes
Ideals
This framework allows HTML generation in Python while utilizing Python's typing system. Our goal is to enable the creation of dynamic web applications with reusable components, all while offering a greater level of type safety than raw HTML.
Key Ideas:
- Type-Guided HTML: Catch potential HTML structural errors at development time thanks to type hints. The framework enforces stricter rules than standard HTML, promoting well-structured and maintainable code.
- Composable Components: Define reusable, dynamic HTML components in pure Python. This aligns with modern web development practices, emphasizing modularity.
Type-Guided HTML
Here is an example of how Python's type system can be leveraged to enforce HTML structure:
br("Hello, World!") # type error (<br> can't have children)
br() # ok
html(body(...)) # type error (first child must be a <head>)
html(head(...), body(...)) # ok
div("Test", href="test") # type error (unknown attribute)
a("Test", href="...") # ok
Composable Components
Instead of using only basic HTML elements, it is possible to create modular components with the support of Python's type system. Let's take a look at an example:
Table(
TableHead("Id", "Name"),
TableRow("1", "John"),
TableRow("2", "Jane"),
TableRow("3", "Bob"),
)
This structure can be type-checked thanks to Python's rich type system. Additionally, this Table
component could have dynamic properties like sorting or filtering.
Requirements
Python 3.12+
Installation
pip install "ludic[full]"
Similar to Starlette, you'll also want to install an ASGI server:
pip install uvicorn
Full Example
components.py:
from typing import override
from ludic.html import a
from ludic.types import Attrs, Component
class LinkAttrs(Attrs):
to: str
class Link(Component[str, LinkAttrs]):
classes = ["link"]
@override
def render(self) -> a:
return a(
*self.children,
href=self.attrs["to"],
style={"color": self.theme.colors.primary},
)
Now you can use it like this:
link = Link("Hello, World!", to="/home")
web.py:
from ludic.web import LudicApp
from ludic.html import b, p
from .components import Link
app = LudicApp()
@app.get("/")
async def homepage() -> p:
return p(f"Hello {b("Stranger")}! Click {Link("here", to="https://example.com")}!")
To run the application:
uvicorn web:app
More Examples
For more complex usage incorporating all capabilities of the framework, please visit the folder with examples on GitHub.
Contributing
Any contributions to the framework are warmly welcome! Your help will make it a better resource for the community. If you're ready to contribute, read the contribution guide.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.