Serve Panel Apps With A Trailing Slash

Dear all,
Any idea how can I make Panel serve my app correctly with a trailing slash in the URL? for example, I have this dashboard that is working fine, but not when adding the slash
I am trying to add it to google search, but google bots keep sending the request with a trailing slash, and I am worried that the user may land on a non-working dashboard.

Any feedback or idea is highly appreciated.


great work ! it looks really clean and well organized ! I expect something can help you with your question !

1 Like

An idea is to look into how to add extra request handlers to Tornado and/ or Bokeh to redirect to the address without the slash. There is probably some code in the Bokeh discourse or in the Bokeh repository?

Alternatively you could look into using pn.serve instead of Panel serve. Bokeh should now with version 2.4 provide the ability to serve at any url.

But I hope someone here can provide a specific answer?

and congrats on the app. Seems to work very efficiently :+1:

Thanks @nghenzi2019 and @Marc for the kind response and feedback. I ended up setting an Nginx reverse proxy to redirect requests. The configuration wasn’t obvious too, but with a lot of trial and error, it seems to be working now.

1 Like

Great to hear you found a solution @mashaal .

If you think you’ve learned something that could be useful for other Panel users feel free to share :+1:

I have never tried nginx but often thought it would like to try it out in combination with Panel and FastAPI.

Yes definitely will share.
I figured that there are three parts served by Panel, which are affected by the trailing slash:
1- Static file (e.g. css and javascript), served from http : // server / static /… when the slash is added, the request will become http : // server / [app name] / static /… which results in 404.
2- The application itself, served from http : // server / [app name]
3- The WebSocket, served from ws : // server / [app name] / ws

So my Nginx needs to account for these three parts and reroute them correctly. Below is my config file for Nginx with the three rules, each to handle one of the parts. Note that “Rased” is the name of my app, so change it according to your needs.

events {

http {
    server {
        listen 80;

        location ~ ^(?:.*/)static/(.*) {
            proxy_pass localhost:8000/static/$1;

        # repeat for every panel service
        # begin repeat
        location /rased/ws {
            proxy_pass localhost:8000/rased/ws;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
        location ~ /rased/?$ {
            proxy_pass $scheme://localhost:8000/rased;
        # end repeat