fasthtml icon indicating copy to clipboard operation
fasthtml copied to clipboard

[FEATURE] allow setting of default title in fast_app()

Open mmacpherson opened this issue 1 year ago • 3 comments

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.

mmacpherson avatar Oct 01 '24 05:10 mmacpherson

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.

Phrogz avatar Feb 07 '25 16:02 Phrogz

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.

jamilraichouni avatar Feb 09 '25 12:02 jamilraichouni

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"

mmacpherson avatar May 26 '25 18:05 mmacpherson

This issue was resolved by #740 .

With this change you can set a default page title via fast_app(title="my site").

mmacpherson avatar May 29 '25 16:05 mmacpherson