AnswerDotAI / AnswerDotAI/fasthtml

[FEATURE] It is hoped that the hx_post parameter can support directly assigning functions decorated by router to implement reverse routing.

Open
#864 1 comment 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Jupyter Notebook
Stars
7k
Forks
319
Avg merge
28m
Merged PRs (30d)
3

Description

If you'd like to discuss your feature idea first with the community (highly recommended!) please visit our [Discord channel](https://discord.gg/qcXvcxMhdP).

**Is your feature request related to a problem? Please describe.**
I believe hardcoding route strings directly in FastHTML's `hx_*` attributes is poor practice, especially as projects grow larger and undergo early‑stage iteration. This creates significant friction when distinguishing view vs. action routes, refactoring paths, or maintaining consistent routing across the codebase.

Most full‑stack frameworks provide a reverse‑routing mechanism to solve this problem, but I have not found an equivalent function in FastHTML.

**Describe the solution you'd like**
I initially planned to request a `url_for(name: str)` utility function that returns the URL for a named route.

However, I was pleasantly surprised to discover that `hx_*` attributes already support passing route functions directly, as they are implicitly converted to strings. The following example works perfectly:

```python
from fasthtml.common import (
fast_app,
Div,
P,
serve,
Button,
Main,
H1,
A,
Form,
Input,
Title,
)

app, router = fast_app()

count = 0

@router("/")
def home():
return Title("Count Demo"), Main(
H1("Count Demo"),
P(f"Count is set to {count}", id="count"),
Button(
"Increment", hx_post=str(increment), hx_target="#count", hx_swap="innerHTML"
),
)

@router("/increment")
def increment():
print(increment, type(increment))
print("incrementing")
global count
count += 1
return f"Count is set to {count}"

serve()
```

In other words, FastHTML already supports reverse routing: simply convert a route function to a string with `str()`, and the result is its corresponding path, which can then be passed to `hx_post` and similar attributes.

Therefore, my proposal has evolved. I would like the maintainers to evaluate the validity of this pattern and consider:

1. Automatically converting values passed to `hx_post`, `hx_get`, `hx_put`, etc., to strings internally, so users no longer need to explicitly call `str()`.
2. Updating the type annotations for `hx_post`, `hx_get`, `hx_put`, and related attributes to accept route functions directly.

**Example code**
```python
from fasthtml.common import (
fast_app,
Div,
P,
serve,
Button,
Main,
H1,
A,
Form,
Input,
Title,
)

app, router = fast_app()

count = 0

@router("/")
def home():
return Title("Count Demo"), Main(
H1("Count Demo"),
P(f"Count is set to {count}", id="count"),
# NOTE: hx_post directly accepts the increment function and converts it to str internally
Button(
"Increment", hx_post=increment, hx_target="#count", hx_swap="innerHTML"
),
)

@router("/increment")
def increment():
print(increment, type(increment))
print("incrementing")
global count
count += 1
return f"Count is set to {count}"

serve()
```

```python
# Your example code here
```

**Similar implementations**
If available, provide links to similar features in other libraries:
1. [Library Name](link-to-feature)
2. [Another Library](another-link-to-feature)

**Problem solved**
This improvement eliminates the need to hardcode route strings throughout the codebase, enabling type‑safe, refactor‑friendly reverse routing. Users will benefit from fewer routing errors, easier path renaming, cleaner code, and better IDE support when referencing routes. It aligns FastHTML’s syntax with modern full‑stack framework conventions while leveraging existing internal behavior.

**Additional context**
This pattern already works today with explicit `str()` conversion, suggesting the underlying implementation is stable. Formalizing it would improve developer experience without breaking changes.

**Confirmation**
Please confirm the following:
- [x] I have checked the existing issues and pull requests to ensure this feature hasn't been requested before.
- [x] I have read the project's documentation to ensure this feature doesn't already exist.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.