Host dash apps in the browser using PyCafe

Hi all,

A while back, we launched a platform for hosting, editing and sharing Python web apps with a single click: https://py.cafe

Dash is one of the frameworks supported. You can click the Dash tile from the homepage
or start from an existing project and fork it:

Or start from our default template:

As you can see, every project can also have a preview screenshot, which makes it ideal for sharing on social media.

Custom packages can be installed, which means you can also use component libraries such as
dash-mantine-components:

PyCafe is built on top of Pyodide, but makes it easier to install, edit and share apps.

I hope you all like it. Feel free to share what you’ve made in the replies.

Regards,

Maarten Breddels

7 Likes

I’ve just used it for Plotly’s latest data viz challenge #FigureFriday.
It’s great to have an app up and running quickly and to be able to share a link and live edit it :rocket:

Will use it more often for demos now - thanks for your work on this!

3 Likes

Thanks for sharing, @maartenbreddels :pray: And welcome the the community :wave:

Impressive to see @li.nguyen !

Thank you, @adamschroeder, for the warm welcome.

2 Likes

Hi @maartenbreddels , I try to put a new mini-project on py.cafe but get an error on the json package. I saw some examples of adding stuff in the documentation, but I have no idea, not enough experience. The terminal window looks read-only. Do I ask too much (for the free version), missing something easy, missing something not that easy or is it not possible at the moment? I do like py.cafe very much and if not possible, I can maybe adjust my code for portfolio purposes a bit.

Marie-Anne

Hi @marieanne , I recently asked about pycafe here on another channel and got this link, maybe it will be of some help to you. PyCafe Guide — Panel v1.5.5

Thank you @Ester for your link. I looked at it, tried to add json this way, but it is another framework., Panel and not Dash. Ccould not get it to work.

Hi @marieanne

Could you please show an example of the app you are trying to host? Does it run correctly locally but just not on pycafe?

Hi @AnnMarieW ,

the errormessage:
Ă— No solution found when resolving dependencies:
╰─▶ Because json was not found in the package registry and you require json,
we can conclude that your requirements are unsatisfiable.

The requirements.txt has a line with the word “json”.

I’ve put the code on github, figurefriday/Week50 at main · tigi/figurefriday · GitHub, the content in the assets file is needed and it works locally.

In the meantime I have changed usage of dangerousinnerhtml to dbc.listgroup for week51 and now it works on py.cafe. One of the two how-to problems solved.

Thank you if you have a hint, Marie-Anne

hi @marieanne
Try removing json from requirements.txt
The json is already included with Python so it doesn’t need to be installed.

1 Like

@AnnMarieW , how cool, look (have some patience :-)):

Is there a place where I can check a problem like this? Marie-Anne

2 Likes

What’s the problem? It worked for me. Looks great! :slightly_smiling_face:

No, I’m very happy :slight_smile: What I mean, if I run into a problem like this in the future, came your answer from experience or is there a place with a list of things not to add to requirements which I could check myself.

You only need to include third party libraries where you had to do pip install

To see what’s included in Python you can check the docs for your version The Python Standard Library — Python 3.13.1 documentation

You can also use pip list and if it’s not on the list, it’s likely a built-in module.

2 Likes

Hi all, I am a bit clueless again about an error. The uploaded code to pycafe works.
But when I push the files I get this errormessage.

What I tried myself:

  • find this error in the documentation. No idea if there is some errorlog. The app works without problems on my desktop.
  • cleanup one project with large .csv files, load .csv from github, remove them from py.cafe. Could still be the diskspace but that errormessage was gone.
  • push the project you start with, gives the same error.
  • changed some things to the code, didn’t help.

Any hints or help are very appreciated, Marie-Anne

Edit 07 jan 2025, put this question on discord. @Ester somebody will look into the problem in the near future

Code - ff 2025 - w1
# -*- coding: utf-8 -*-
"""
Created on Sat Jan  4 11:51:17 2025

@author: win11
"""

import plotly.express as px
import pandas as pd
from dash import Dash, html, dcc, Input, Output, callback
import dash_bootstrap_components as dbc
import dash_daq as daq


###############################################################

# DATAPROCESSING #

###############################################################

df_raw = pd.read_csv('https://raw.githubusercontent.com/tigi/figurefriday/refs/heads/main/2025-figurefriday-week1/NYC%20Marathon%20Results%2C%202024%20-%20Marathon%20Runner%20Results.csv')


df = df_raw[['runnerId', 'age', 'gender','countryCode','racesCount']].copy()
#drop age = 0, with all the nans
df = df.dropna()
#add true/false column for usa citizen
df['Usa citizen'] = df['countryCode'].apply(lambda x: 1 if x=='USA' else 0)



df_grouped_age =df.groupby(['age', 'gender','Usa citizen'])['age'].count().rename('Count').to_frame().reset_index()

#drop gender=x because I want to end with 4 groups, total of 119 runners dropped out of 55000+
df_grouped_age = df_grouped_age[(df_grouped_age['gender'] != 'X')].sort_values(by=['age'])



###############################################################

# BUCKET LIST THING FOR PEOPLE ABROAD?#

###############################################################



# Create plot
fig = px.area(df_grouped_age, x="age", y="Count", color= 'gender', color_discrete_map= {'M': '#1261a0',
                                      'W': '#0895d3'}, line_group='Usa citizen',
              pattern_shape_sequence=["|", ""],pattern_shape = 'Usa citizen', line_shape='spline')


#customize texts
fig.update_layout(
    title="You are never to old to run a marathon",
    xaxis_title="Runners age",
    yaxis_title="Total number of runners",
    legend_title="Profile",

)



#make legend for traces understandable
for tr in fig.select_traces():
    tr['name'] = tr['name'].replace('W,','Female')
    tr['name'] = tr['name'].replace('M,','Male')
    tr['name'] = tr['name'].replace('0','from abroad')
    tr['name'] = tr['name'].replace('1','from the USA')
    
    
    
def create_age_card(age):
    
    #imagesources
    
    age_image = age
    if age not in (40,50,60):
        age_image = "unknown"
    
    
    
    
    #calculate some values
    #%firsttimes
    
    total = len(df[(df['age'] == age)])
    total_first = len(df[(df['age'] == age) & (df['racesCount'] == 1)])
    if total > 0: 
        first_count=str(round(100*(total_first/total),1)) 
    else: 
        first_count='unknown'
    races_median = df[(df['age'] == age)]['racesCount'].median()
    races_max = df[(df['age'] == age)]['racesCount'].max()
    total_abroad = len(df[(df['age'] == age) & (df['Usa citizen'] == 0)])
    if total > 0: 
        foreigners  =str(round(100*(total_abroad/total),1))
    else: 
        foreigners = "unknown"
    
    
    card = dbc.Card(
    [
        dbc.Row(
            [
                dbc.Col(
                    dbc.CardImg(
                        src=f"assets/{age_image}.jpg",
                        className="img-fluid rounded-start",
                    ),
                    className="col-md-4",
                ),
                dbc.Col(
                    dbc.CardBody(
                        [
                            html.H4(f"Profile {age} years", className="card-title"),
                            html.Span(
                               "First USA official marathon?",
                                className="card-text",style={"fontSize": "14px"}
                            ),
                            html.Span(
                               f" {first_count} %",
                                className="card-text", style={"fontWeight":"bold","fontSize": "14px"}
                            ),
                            html.Br(),
                            html.Span('Runner with most registered races: ', style={"fontSize": "14px"}),
                            html.Span(
                               f" {races_max} races",
                                className="card-text", style={"fontWeight":"bold","fontSize": "14px"}
                            ),
                            html.Br(),
                            html.Span("Coming from abroad? ",style={"fontSize": "14px"}),
                            html.Span(
                               f"{foreigners}% of runners",
                                className="card-text", style={"fontWeight":"bold","fontSize": "14px"}
                            ),

                        ]
                    ),
                    className="col-md-8",
                ),
            ],
            className="g-0 d-flex align-items-center",
        )
    ],
    className="mb-4",
    style={"maxWidth": "540px"},
)
    
    
    
    
    return card

 


dbc_css = "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates/dbc.min.css"
app = Dash(__name__, external_stylesheets=[dbc.themes.SANDSTONE, dbc_css])



app.layout = dbc.Container(
    [   dbc.Row([
        html.H1("Is the New York City Marathon on your bucketlist?"),
        dbc.Col([

            dcc.Graph(id="scatter-plot", figure = fig),
      
            
            ], className = 'col-md-12'),
        

          
        ]),
        
        dbc.Row([
            dbc.Col([create_age_card(40)],className='col-md-4'),
            dbc.Col([create_age_card(50)],className='col-md-4'),
            dbc.Col([create_age_card(60)],className='col-md-4')
            
            
            ]),
        
        
        dbc.Row([
            
            dbc.Col( 
                [html.H4('Enter your age and see your potential based on 2024 runner information of the NYCM'),
                    daq.NumericInput(
        id='my-numeric-input-1', min=18, max=88, value=30),
                    
#                     dcc.Input(
#     id="my-numeric-input-1", type="number", placeholder="Enter your age",
#     min=18, max=88, step=1,value=30
# ),
                    
                    
                    html.Br(),
    ], style={"backgroundColor": "#0895d3", "borderRadius": "4px", "color": "white", "padding": "1rem","textAlign":"center"}),
            dbc.Col([html.Div(id='numeric-input-output-1', children=create_age_card(30))]),
            dbc.Col([html.H2('Go for it!')], style={"textAlign": "Center"})
            
            ])
        
        
        
        
        
        
], style={"marginTop": "2rem"})


@callback(
    Output('numeric-input-output-1', 'children'),
    Input('my-numeric-input-1', 'value')
)
def update_output(value):
    return create_age_card(value)


app.run_server(debug=True)

Hi @marieanne,

Interesting. I have similar error code today in pycafe. I loaded the data from github and similar error.

Hi, @marieanne, imagine I managed to do it, after several attempts, I fixed it in the code on py and saved it, after that it worked right away.
I think pythonanywhere sometimes doesn’t work.

Logic said that if would copy your project it should work. Well, the copy worked, I pushed I was done, same server engine error. :rofl: Lucky you!

1 Like

We had an issue on our backend, which should be fixed now. Sorry for the inconvenience!

4 Likes

Yes, it was and with the speed of light, thank you.

2 Likes