[FEATURE] allow setting of default title in fast_app()
If you'd like to discuss your feature idea first with the community (highly recommended!) please visit our Discord channel.
Is your feature request related to a problem? Please describe.
Right now, the default title for all (non-htmx) routes is "FastHTML page". I think it would be useful to be able to set a default title that is relevant to one's own project. This would guarantee that a non-sequitur title would not appear if one neglected to add a title to a given route, and would save a little boilerplate for routes where a custom title isn't warranted.
This question has previously been raised here: https://github.com/AnswerDotAI/fasthtml/issues/208
JPH notes that the standard pattern is to set a title per route, and notes that "it would be a bit tricky to support having titles defined in headers too." Both those points make sense, and JPH is of course best-positioned to make judgments about the difficulty of supporting features.
Describe the solution you'd like
There might be a fast_app(..., title="my site", ...) or fast_app(..., default_title="my site", ...) that effectively replaces the default "FastHTML page" with "my site".
Or the pattern might be to allow the definition of a Title() in the hdrs= argument to fast_app(). (This is allowed now, it just doesn't have the intended effect because the headers defined via hdrs= appear after the default title.)
Example code
For the moment [this no longer works (May 26), see comment below], I have been implementing a default title using Beforeware, as follows:
def inject_title(req, sess):
req.injects = [Title("my site"), *req.injects]
app, rt = fast_app(..., before=[..., inject_title], ...)
(The code where the contents of req.injects gets converted into headers is here, i.e. in fasthtml.core:_xt_cts().)
This same mechanism might be used, i.e. adding a default_title= value to req.injects.
Alternative 2
Another way might be to, in fasthtml.core:_xt_cts(), flip the order of titles and req.hdrs from:
resp = Html(Head(*titles, *flat_xt(req.hdrs)), ...)
to
resp = Html(Head(*flat_xt(req.hdrs)), *titles, ...)
This way any included Title() in fast_app(hdrs=...) would precede those in titles, and be shown in the browser.
Alternative 3
A .default_title attribute defined via fast_app(), a la def fast_app(..., default_title: str="FastHTML page", ...): ... could be added to the req object, so the line in fasthtml.core:_xt_cts():
if not titles: titles = [Title('FastHTML page')]
might become:
if not titles: titles = [Title(req.default_title)]
Similar implementations N/A
Problem solved
Mentioned above. Avoids non sequitur titles, minor arguable boilerplate reduction.
Additional context
None.
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.
I don't want a default title for the whole app, but I do want a way to set the from the body_wrap. This does not do what one might hope:
def my_wrap(*contents):
return (ft.Title("My Page Title"), *contents)
@rt("/", body_wrap=my_wrap)
def get():
return ft.Div("Hello World")
In this simple case it is trivial to change the route to:
@rt("/")
def get():
return my_wrap(ft.Div("Hello World"))
but when I am setting a default body_wrap for an application instance outside of this file, this is not longer possible.
I am also after a way to set the title with every request ti an endpoint returning an FT component. That matters for the title of history entries on the client side.
Update: that inject_title beforeware method I'd presented above began to fail somewhere between 0.12.12 and 0.12.18.
What we're using now -- to set a default title that's not "FastHTML page" for routes that don't otherwise set one -- is to assign to app.title just after app creation:
app, rt = fast_app(...)
app.title = "my site"
This issue was resolved by #740 .
With this change you can set a default page title via fast_app(title="my site").