Specifying a favicon without the use of a template?

I have an interactive visualization that I’ve put together in a Jupyter notebook and am rendering with a viz.show() at the end of the notebook. Is there a way to specify a favicon for the resulting webpage that is created upon execution of the notebook? The examples I’ve seen so far this morning for specifying a favicon all seem to be in the context of a template.

1 Like

I found the below solution, but it briefly flashes the panel favicon before loading yours.

import panel as pn

pn.extension()

FAVICON_PATH = "assets/favicon.ico"

def enforce_favicon():
    html = f"""
    <script>
      // Function to set your favicon and remove defaults
      function setFavicon() {{
        // Remove all existing favicon links
        document.querySelectorAll('link[rel="icon"], link[rel="shortcut icon"]').forEach(e => e.remove());
        // Create new link tag for your favicon
        const link = document.createElement('link');
        link.rel = 'icon';
        link.href = '{FAVICON_PATH}';
        document.head.appendChild(link);
      }}

      // Immediately attempt to set favicon (for preload)
      setFavicon();

      // Observe head for any favicon changes (Panel sometimes re-adds its own)
      const observer = new MutationObserver((mutations) => {{
        const hasPanelFavicon = Array.from(document.querySelectorAll('link[rel="icon"]'))
          .some(l => l.href.includes('panel'));
        if (hasPanelFavicon) {{
          setFavicon();
        }}
      }});
      observer.observe(document.head, {{ childList: true, subtree: true }});

      // Also run once after full DOM load
      window.addEventListener('load', setFavicon);
    </script>
    """
    return pn.pane.HTML(html, width=0, height=0, margin=0, sizing_mode="fixed")

# --- Example dashboard ---
dashboard = pn.Column(
    enforce_favicon(),
    pn.pane.Markdown("## 🦊 Your favicon is locked — no flash, no revert."),
    pn.Spacer(height=400),
)

dashboard.servable()