Including page titles, favicon, etc in dash app?

I’m wondering if there is a way to specify a head element with title, etc? I’ve tried searching through the dash-html-components and have worked through the tutorials, but cannot figure this out.

Any help is appreciated!

2 Likes

Ideally, this functionality would be set entirely through the dash-html-components, consistent with the rest of the app. For things like favicon, you should be able to set this with html.Link(rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>). There are a couple of things to keep in mind:

  • Right now, Dash renders itself inside the <body/> instead of the <head/>. There may be some properties where this matters more than others, I haven’t researched this thoroughly.
  • The title element is actually hard coded by Dash. See https://github.com/plotly/dash/blob/a8fc53ba880d26e3c131f7849795d173596405ec/dash/dash.py#L343-L364. It is possible to override this with app.title='my title' for now but know that this is likeley to change in the future (it’s just a temporary workaround).
  • Dash apps don’t support hosting arbitrary content like favicon.ico, so you’ll either need to host this remotely or add a static view to your dash app (by accessing the flask instance in app.server) that serves an icon. We’ll add serving static content in the future.
  • Dash apps are rendered on the client instead of the server. If the app takes a long time to load, some items like meta descriptions may not be recognized by e.g. a search engine since they aren’t loaded in the first initial request.
8 Likes

Great - thank you for such an excellent answer!

Hi,

In dash_html_components, html.Link doesn’t have type as a property. I wasn’t able to set the favicon because of this.

EDIT:
Just in case it’s neccessary, the version of dash_html_components is 0.7.0

Thank you!

Hello, all!
I am confused too about favicon.
Here is my code.
app.layout = html.Div([ html.Meta(name='viewport', content='width=device-width, initial-scale=1.0'), html.Link(rel='shortcut icon', href='https://rawgit.com/../favicon.ico'), html.Div([...]) ])

Favicon did not change.

If there are some thoughts or solutions, it will be really helpful.
Thank you.

1 Like

If you’re happy with Flask serving the favicon, then one option is to add an explicit route for it. Here’s how I got it working:

from dash import Dash
from flask import Flask, send_from_directory

server = Flask(__name__, static_folder='static')
app =  Dash(server=server)

@server.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(server.root_path, 'static'),
                               'favicon.ico', mimetype='image/vnd.microsoft.icon')

And copy your favicon into the ‘static’ directory which should be in the same directory as the app file.

7 Likes

The content of <head> is set by the Dash.index() function. One workaround is subclassing dash.Dashand modifying that function as you wish. See here

1 Like

Trying to set up the favicon as well. I have only used dash, and not flask. @nedned I have this in my setup in order to serve html files:

app = dash.Dash(__name__)
server = app.server

...
@app.server.route('{}<file_name>'.format(static_file_route))
def serve_static(file_name):
    return flask.send_from_directory(base_dir, file_name)

How would I modify your example based on that? For instance, I tried this but it isn’t working:

@app.server.route('/favicon.ico')
def favicon():
    return flask.send_from_directory(os.path.join(app.server.root_path, 'static'),
                                                  'favicon.ico', mimetype='image/vnd.microsoft.icon')

I’m not sure what I’m doing wrong. favicon.ico exists both in the app dir and app_dir/static.

1 Like

It looks like the same setup I had as far as I can see, which worked for me, so not sure what’s going on. What do you see under the favicon.ico request when you look in the the Network tab of the Dev Tools? (you’ll need to have it open when you load the page)

1 Like

I think it was an issue of not knowing what a .ico was, exactly. I had a .svg, which I figured would work, but downloaded a random example .ico just to be sure and it worked! Sorry for the noise. Based on the slightly different ways of defining the dash vs. flask parts, I did drop the app prefix from my stuff though. I ended up with:

@server.route('/favicon.ico')
def favicon():
    return flask.send_from_directory(os.path.join(server.root_path, 'static'),
                                     'favicon.ico')

Just to understand what’s going on here, this is sort of like a callback? I’m interpreting this like “When the browser asks for /favicon.ico, serve up this file, which is app_root_directory/static/favicon.ico.” Is that accurate? For serving other files, I’m guessing this does’t work, as the request for favicon.ico is built in vs. requests for some other random file are not; is that also the case?

Thanks again!

2 Likes

Yeah, that’ accurate. server is referencing the underlying flask server, so server.route is actually a flask thing not a a Dash thing.

That’s right - the browser automatically makes these requests for every page it loads unless you specify the favicon markup in your html itself (e.g. Favicon Code | The Icon Handbook)

Did you add a html.Link in your Dash app to get this working?

1 Like

@mikesmith1611 in my case, no but it looks possible from above? I was able to use the example from @nedned above. I made a minimal example on github for you if you’d like to take a look!

1 Like

You can’t wire up different files to be used for the favicon (as @chriddyp pointed out), but if you’re wondering whether you can use this method to expose arbitrary files, then the answer is yes. You just need to be careful not to let the routes you create clash with the routes that Dash creates, such as ‘_dash-layout’ and ‘_dash-dependencies’. obviously this is unlikely, but you can set the config param url_base_pathname, which will be prefixed to Dash’s routes.

It’s worth noting that, in production, it’s better to let a web server like Apache or Nginx serve your static files – which is optimised for such tasks – rather than slowing down the Flask app that’s running Dash. But for low-traffic sites/prototypes etc, just using Flask works fine.

2 Likes

Thanks, it turns out chrome was caching the favicon so I had to restart chrome to see it !

@mikesmith1611 ahh. Yeah, I had a load of that too. In the example I made for you, I was specifically seeing if it would render from just the base directory (vs. ./static/) and was just baffled by what in the world was happening. I’d even change the filename and it would still show the old file!?

Yes, turns out chrome (chromium on linux in my case) was caching something somehow. There were a couple suggestions here I found for others who stumble on this issue. Like Shift + F5 and actually going to localhost:port/static/favicon.ico.

2 Likes

Here is a PR that addresses this issue (including page titles, favicon, etc in the app) among others: https://github.com/plotly/dash/pull/171. Feedback welcome! (Please comment on the PR itself)

1 Like

Did you finally get it to work ? If you did I would really appreciate if you told me how.

1 Like

https://github.com/plotly/dash/pull/171 was replaced by https://github.com/plotly/dash/pull/286 and is now documented in https://dash.plot.ly/external-resources

1 Like

from dash import Dash
from flask import Flask, send_from_directory
import dash_core_components as dcc
import dash_html_components as html

server = Flask(name, static_folder=‘static’)
app = Dash(server=server)
app.layout = html.Div(html.H2(‘dash favicon example’))
@server.route(’/favicon.ico’)
def favicon():
return send_from_directory(os.path.join(server.root_path, ‘static’), ‘favicon.ico’))

if name == ‘main’:
app.run_server(debug=True)

Hi, I am trying to set the favicon by this code. I am not having any luck. I suspect there is something wrong with the root_path.
I have folder called favicon which contains this python file and static folder. The static folder has favicon.ico file. Let me know if I am going wrong somewhere. Or have i missed something, please let me know