Unable to run dash application in jupyter notebook

I’m creating a Dash application where. I’ve followed the official documentation following some examples and was able to build this multi-page dash app. This does run on the local host but when I click on the page links the pages do not open and are not responsive. I am new to Dash app building so some help would be highly appreciated. Here’s the code:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

new_df=Gold_coin_prediction.join([Universal_prediction, NewHope_prediction,CPI_prediction,Japfa_prediction,QLFeed_prediction,QLAgrofood_prediction,WidodoMakmur_prediction,Farmsco_prediction,SabasDian_prediction,KertamulyaSari_prediction,Agrico_prediction,Wonokoyo_prediction,CibadakIndah_prediction,Gorontalo_prediction,NTB_prediction])
df_weekly_average = new_df_average.groupby(pd.Grouper(key='index', freq='W-SUN')).mean()[['PT. Gold Coin', 'yhat_PT. Gold Coin','PT. Universal','yhat_PT. Universal','PT. NEW HOPE INDONESIA','yhat_PT. NEW HOPE INDONESIA','CPI','yhat_CPI','Japfa','yhat_Japfa','QLFeed','yhat_QLFeed','QLAgrofood','yhat_QLAgrofood','WidodoMakmur','yhat_WidodoMakmur','Farmsco','yhat_Farmsco','SabasDian','yhat_SabasDian','KertamulyaSari','yhat_KertamulyaSari','Agrico','yhat_Agrico','Wonokoyo','yhat_Wonokoyo','CibadakIndah','yhat_CibadakIndah','Gorontalo','yhat_Gorontalo','NTB','yhat_NTB']]
df_weekly_average ['week_start'] = df_weekly_average.index

app = dash.Dash(__name__,suppress_callback_exceptions=True,external_stylesheets=external_stylesheets)

index_page = html.Div([
    html.H1('Welcome to the Home Page!'),
    dcc.Link('Feedmill Price Forecasts(daily)', href='/page-1'),
    html.Br(),
    dcc.Link('Feedmill Price Forecasts(weekly)', href='/page-2'),
    html.Div(id='page-content')
])

page_1_layout = html.Div([
    html.H1('Welcome to Page 1!'),
    html.H2('Feedmill price forecasting'),
    dcc.Graph(id="time-series-chart"),
    dcc.Graph(id="page-1-graph"),
    html.P("Select Feedmill:"),
    dcc.Dropdown(
        id="ticker",
        options=["PT. Gold Coin","PT. Universal", "PT. NEW HOPE INDONESIA","CPI","Japfa","QLFeed","QLAgrofood","WidodoMakmur","Farmsco","SabasDian","KertamulyaSari","Agrico","Wonokoyo","CibadakIndah","Gorontalo","NTB"],
        value="PT. Gold Coin",
        clearable=False,
    ),
    dcc.Interval(id='interval-component', interval=24*60*60*1000, n_intervals=0),
])
page_2_layout = html.Div([
    html.H1('Welcome to Page 2!'),
    html.H2('Feedmill price forecasting'),
    dcc.Graph(id="time-series-chart"),
    dcc.Graph(id="page-2-graph"),
    html.P("Select Feedmill:"),
    dcc.Dropdown(
        id="ticker-2",
        options=["PT. Gold Coin","PT. Universal", "PT. NEW HOPE INDONESIA","CPI","Japfa","QLFeed","QLAgrofood","WidodoMakmur","Farmsco","SabasDian","KertamulyaSari","Agrico","Wonokoyo","CibadakIndah","Gorontalo","NTB"],
        value="PT. Gold Coin",
        clearable=False,
    ),
])

app.layout = index_page

def display_time_series(ticker, pathname):
    if pathname == '/page-1':
        filtered_df = new_df.loc[:, [ticker, f"yhat_{ticker}", f"y_lower_{ticker}", f"y_upper_{ticker}"]]
        filtered_df[f"yhat_{ticker}"] = filtered_df[f"yhat_{ticker}"].iloc[-8:]
        filtered_df[f"y_lower_{ticker}"] = filtered_df[f"y_lower_{ticker}"].iloc[-8:]
        filtered_df[f"y_upper_{ticker}"] = filtered_df[f"y_upper_{ticker}"].iloc[-8:]

        # Add rolling mean line
        rolling_mean = filtered_df[ticker].rolling(window=7, min_periods=1).mean().shift(7)
        fig = go.Figure()
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[ticker],
                        mode='lines',
                        name='Actual'))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=rolling_mean,
                        mode='lines',
                        name='Rolling Mean'))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"yhat_{ticker}"],
                        mode='lines',
                        name="Predicted"))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_lower_{ticker}"],
                        fill=None,
                        mode='lines',
                        name="lower bound"))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_upper_{ticker}"],
                        fill='tonexty',
                        mode='lines',
                        name="upper bound"))
        fig.update_xaxes(title_text='Date',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
        fig.update_yaxes(
        title_text='Feedmill Price',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
        fig.update_layout(legend=dict(title="Legend", orientation="v", y=1.1, x=1.05, xanchor="center", bgcolor='rgba(0,0,0,0)'),
                         margin=dict(l=20, r=20, t=80, b=30)
                         )
        fig.update_traces(marker=dict(size=1.5))
        
        
    elif pathname == '/page-2':
        filtered_df = df_weekly_average.loc[:, [ticker, f"yhat_{ticker}"]]
        filtered_df[f"yhat_{ticker}"] = filtered_df[f"yhat_{ticker}"].iloc[-2:]
        fig = px.line(filtered_df)
        fig.update_xaxes(title_text='Week_start')
        fig.update_yaxes(title_text='Feedmill Price')
    else:
        fig = {}
    return fig

@app.callback(Output('page-1-graph', 'figure'),
              Input('interval-component', 'n_intervals'),
              Input('ticker', 'value'),
              prevent_initial_call=True)
def update_graph(n, ticker):
    fig = display_time_series(ticker, '/page-1')
    return fig

@app.callback(
    Output('page-2-graph', 'figure'),
    [Input('url', 'pathname'),
     Input('ticker-2', 'value')])
def update_page_2(pathname, ticker):
    fig = display_time_series(ticker, '/page-2')
    return fig

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/':
        return index_page
    elif pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    else:
        return html.Div([
            html.H1('404 Error: Page not found'),
            dcc.Link('Go back to home', href='/')
        ])
# Run the app
if __name__ == '__main__':
    app.run_server(debug=True, use_reloader=False, port=8000, host='127.0.0.1')

As I know, you should use debug=False when running Dash with Jupyter Notebook. Could you try that?

@hoatran I tried that but still, it does not work. The page does show up but the links do not open

Can you add some data so we can try it out?

@hoatran how do I add an excel file here?

Maybe upload to github then add link to your post.

@hoatran does this work?

Data is for the daily forecasts
new_df

PT. Gold Coin yhat_PT. Gold Coin y_lower_PT. Gold Coin y_upper_PT. Gold Coin PT. Universal yhat_PT. Universal y_lower_PT. Universal y_upper_PT. Universal
2023-03-14 00:00:00 4700 4716.309123 4700 4703.450009
2023-03-15 00:00:00 4700 4692.353781 4700 4702.445763
2023-03-16 00:00:00 4700 4700.92097 4700 4703.455424
2023-03-17 00:00:00 4700 4709.029936 4700 4700.043833
2023-03-18 00:00:00 4700 4701.141868 4700 4700.531019
2023-03-19 00:00:00 4699.535025 4616.053041 4783.017009 4679.525719 4605.878919 4753.172519
2023-03-20 00:00:00 4683.644197 4565.582843 4801.705551 4691.968314 4587.81601 4796.120618
2023-03-21 00:00:00 4693.40207 4548.807032 4837.997107 4694.818921 4567.258921 4822.378921
2023-03-22 00:00:00 4694.563797 4527.599829 4861.527765 4693.732885 4546.439284 4841.026486
2023-03-23 00:00:00 4691.975151 4505.303759 4878.646542 4695.272674 4530.593422 4859.951926
2023-03-24 00:00:00 4700.746551 4496.258288 4905.234815 4692.987544 4512.590462 4873.384626
2023-03-25 00:00:00 4704.816399 4483.94383 4925.688968 4688.050904 4493.199785 4882.902022

Data is for the weekly forecasts
in my code new_df_average

index PT. Gold Coin yhat_PT. Gold Coin PT. Universal yhat_PT. Universal
2023-02-12 00:00:00 4700 4708.990944 4700 4707.098693
2023-02-19 00:00:00 4700 4700.008641 4700 4699.618728
2023-02-26 00:00:00 4700 4699.647406 4700 4700.461479
2023-03-05 00:00:00 4700 4699.604365 4700 4700.489673
2023-03-12 00:00:00 4700 4698.615092 4700 4702.238096
2023-03-19 00:00:00 4700 4699.981183 4700 4700.735715
2023-03-26 00:00:00 4694.858027 4692.805207

After checking your code, I saw that you did not define url in your code but you used url as Input for page-content. So I think you should change as below:

app.layout = html.Div([
    dcc.Location(id='url'),
    index_page])

And with the callback:

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    else:
        return html.Div([
            html.H1('404 Error: Page not found'),
            dcc.Link('Go back to home', href='/'

)


@hoatran these are the two plots I am trying to have in these two pages.

Daily forecast

Weekly forecast

this does work but why is there a blank chart appearing and 404 error also appearing in the index page?

Hi, if you are using notebooks isn’t it better to use jupyterdash?

I can not use your data so I please add your data for us to check why did graph blank. For the 404, please update your page-content callback as below:

@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/':
        return html.Div()
    elif pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    else:
        return html.Div([
            html.H1('404 Error: Page not found'),
            dcc.Link('Go back to home', href='/')
        ])

@hoatran Thanks for sharing the callback code. The error is fixed now but the graphs do not appear yet. I have added the github link with the code for individual pages and the single page app named as forecast_dash_app.py

@hoatran now the graphs are appearing the issue was I had to change the callback for page-1-graph
@app.callback(
Output(‘page-1-graph’, ‘figure’),
[Input(‘url’, ‘pathname’),
Input(‘ticker’, ‘value’)])
def update_graph(n, ticker):
fig = display_time_series(ticker, ‘/page-1’)
return fig

But, the issue of the blank graph persists.

1 Like

I did not see callback of time-series-chart in your code. Please check it.

I added this code for callback for the time-series-chart. Please could you check it the graphs are still not appearing.

@app.callback(
Output(“page-1-graph”, “figure”),
Output(“page-2-graph”, “figure”),
Input(“ticker”, “value”),
Input(“ticker-2”, “value”)
)
def update_time_series_chart(ticker, ticker_2):
if ticker:
filtered_df = new_df.loc[:, [ticker, f"yhat_{ticker}“, f"y_lower_{ticker}”, f"y_upper_{ticker}“]]
filtered_df[f"yhat_{ticker}”] = filtered_df[f"yhat_{ticker}“].iloc[-8:]
filtered_df[f"y_lower_{ticker}”] = filtered_df[f"y_lower_{ticker}“].iloc[-8:]
filtered_df[f"y_upper_{ticker}”] = filtered_df[f"y_upper_{ticker}"].iloc[-8:]

    rolling_mean = filtered_df[ticker].rolling(window=7, min_periods=1).mean().shift(7)
    fig1 = go.Figure()
    fig1.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[ticker],
                    mode='lines',
                    name='Actual'))
    fig1.add_trace(go.Scattergl(x=filtered_df.index, y=rolling_mean,
                    mode='lines',
                    name='Rolling Mean'))
    fig1.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"yhat_{ticker}"],
                    mode='lines',
                    name="Predicted"))
    fig1.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_lower_{ticker}"],
                    fill=None,
                    mode='lines',
                    name="lower bound"))
    fig1.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_upper_{ticker}"],
                    fill='tonexty',
                    mode='lines',
                    name="upper bound"))
elif ticker_2:
    filtered_df = df_weekly_average.loc[:, [ticker_2, f"yhat_{ticker_2}"]]
    filtered_df[f"yhat_{ticker_2}"] = filtered_df[f"yhat_{ticker_2}"].iloc[-2:]
    rolling_mean = filtered_df[ticker_2].rolling(window=7, min_periods=1).mean().shift(1)
    fig2 = go.Figure()
    fig2.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[ticker_2],
                    mode='lines',
                    name='Actual'))
    fig2.add_trace(go.Scattergl(x=filtered_df.index, y=rolling_mean,
                    mode='lines',
                    name='Rolling Mean'))
    fig2.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"yhat_{ticker_2}"],
                    mode='lines',
                    name="Predicted"))

    fig2.update_xaxes(title_text='Date',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
    fig2.update_yaxes(
        title_text='Feedmill Price',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
    fig2.update_layout(
        legend=dict(title="Legend", orientation="v", y=1.1, x=1.05, xanchor="center", bgcolor='rgba(0,0,0,0)'),
        margin=dict(l=20, r=20, t=80, b=30))
    fig2.update_traces(marker=dict(size=1.5))
else:
    fig1 = {}
    fig2= {}
return fig1,fig2
1 Like

If it was me, I will do something like below:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import pandas as pd
from dash.exceptions import PreventUpdate
import io
from datetime import datetime

new_df=pd.read_excel('feedmill_prices.xlsx')
new_df_average=pd.read_excel('feedmill_average_prices.xlsx')
df_weekly_average = new_df_average.groupby(pd.Grouper(key='index', freq='W-SUN')).mean()[['PT. Gold Coin', 'yhat_PT. Gold Coin','PT. Universal','yhat_PT. Universal','PT. NEW HOPE INDONESIA','yhat_PT. NEW HOPE INDONESIA','CPI','yhat_CPI','Japfa','yhat_Japfa','QLFeed','yhat_QLFeed','QLAgrofood','yhat_QLAgrofood','WidodoMakmur','yhat_WidodoMakmur','Farmsco','yhat_Farmsco','SabasDian','yhat_SabasDian','KertamulyaSari','yhat_KertamulyaSari','Agrico','yhat_Agrico','Wonokoyo','yhat_Wonokoyo','CibadakIndah','yhat_CibadakIndah','Gorontalo','yhat_Gorontalo','NTB','yhat_NTB']]
df_weekly_average ['week_start'] = df_weekly_average.index

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__,suppress_callback_exceptions=True,external_stylesheets=external_stylesheets)

index_page = html.Div([
    html.H1('Welcome to the Home Page!'),
    dcc.Link('Feedmill Price Forecasts(daily)', href='/page-1'),
    html.Br(),
    dcc.Link('Feedmill Price Forecasts(weekly)', href='/page-2'),
    html.Div(id='page-content')
])

page_1_layout = html.Div([
    html.H1('Welcome to Page 1!'),
    html.H2('Feedmill price forecasting'),
    dcc.Graph(id="time-series-chart"),
    html.Br(),
    html.Button('Download CSV', id='export-csv-button', n_clicks=0),
    dcc.Download(id="download-dataframe-csv"),
    dcc.Graph(id="page-1-graph"),
    html.P("Select Feedmill:"),
    dcc.Dropdown(
        id="ticker",
        options=["PT. Gold Coin","PT. Universal", "PT. NEW HOPE INDONESIA","CPI","Japfa","QLFeed","QLAgrofood","WidodoMakmur","Farmsco","SabasDian","KertamulyaSari","Agrico","Wonokoyo","CibadakIndah","Gorontalo","NTB"],
        value="PT. Gold Coin",
        clearable=False,
    ),
    dcc.Interval(id='interval-component', interval=24*60*60*1000, n_intervals=0),
])

page_2_layout = html.Div([
    html.H1('Welcome to Page 2!'),
    html.H2('Feedmill price forecasting'),
    dcc.Graph(id="time-series-chart"),
    dcc.Graph(id="page-2-graph"),
    html.P("Select Feedmill:"),
    dcc.Dropdown(
        id="ticker-2",
        options=["PT. Gold Coin","PT. Universal", "PT. NEW HOPE INDONESIA","CPI","Japfa","QLFeed","QLAgrofood","WidodoMakmur","Farmsco","SabasDian","KertamulyaSari","Agrico","Wonokoyo","CibadakIndah","Gorontalo","NTB"],
        value="PT. Gold Coin",
        clearable=False,
    ),
])

app.layout = html.Div([
    dcc.Location(id='url'),
    index_page])

def display_time_series_2(ticker, pathname):
    if pathname == '/page-1':
        filtered_df = new_df.loc[:, [ticker, f"yhat_{ticker}", f"y_lower_{ticker}", f"y_upper_{ticker}"]]
        filtered_df[f"yhat_{ticker}"] = filtered_df[f"yhat_{ticker}"].iloc[-8:]
        filtered_df[f"y_lower_{ticker}"] = filtered_df[f"y_lower_{ticker}"].iloc[-8:]
        filtered_df[f"y_upper_{ticker}"] = filtered_df[f"y_upper_{ticker}"].iloc[-8:]

        # Add rolling mean line
        rolling_mean = filtered_df[ticker].rolling(window=7, min_periods=1).mean().shift(7)
        fig = go.Figure()
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[ticker],
                        mode='lines',
                        name='Actual'))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=rolling_mean,
                        mode='lines',
                        name='Rolling Mean'))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"yhat_{ticker}"],
                        mode='lines',
                        name="Predicted"))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_lower_{ticker}"],
                        fill=None,
                        mode='lines',
                        name="lower bound"))
        fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"y_upper_{ticker}"],
                        fill='tonexty',
                        mode='lines',
                        name="upper bound"))
        fig.update_xaxes(title_text='Date',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
        fig.update_yaxes(
        title_text='Feedmill Price',
        title_font=dict(
            family="Arial, sans-serif",
            size=18,
            color="black"))
        fig.update_layout(legend=dict(title="Legend", orientation="v", y=1.1, x=1.05, xanchor="center", bgcolor='rgba(0,0,0,0)'),
                         margin=dict(l=20, r=20, t=80, b=30)
                         )
        fig.update_traces(marker=dict(size=1.5))
        
        
    elif pathname == '/page-2':
        filtered_df = df_weekly_average.loc[:, [ticker, f"yhat_{ticker}"]]
        filtered_df[f"yhat_{ticker}"] = filtered_df[f"yhat_{ticker}"].iloc[-2:]
        fig = px.line(filtered_df)
        fig.update_xaxes(title_text='Week_start')
        fig.update_yaxes(title_text='Feedmill Price')
    else:
        fig = {}
    return fig

@app.callback(Output('page-1-graph', 'figure'),
              Input('url', 'pathname'),
              Input('ticker', 'value'))
def update_graph(pathname, ticker):
    fig = display_time_series_2(ticker, '/page-1')
    return fig        

@app.callback(
    Output('page-2-graph', 'figure'),
    [Input('url', 'pathname'),
     Input('ticker-2', 'value')])
def update_page_2(pathname, ticker):
    fig = display_time_series_2(ticker, '/page-2')
    return fig

@app.callback(
    Output("time-series-chart", "figure"), 
    Input("ticker", "value"))

def display_time_series(ticker):
    filtered_df = df_weekly_average.loc[:, [ticker, f"yhat_{ticker}"]]
    filtered_df[f"yhat_{ticker}"] = filtered_df[f"yhat_{ticker}"].iloc[-2:]
    
    rolling_mean = filtered_df[ticker].rolling(window=7, min_periods=1).mean().shift(1)
    fig = go.Figure()
    fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[ticker],
                    mode='lines',
                    name='Actual'))
    fig.add_trace(go.Scattergl(x=filtered_df.index, y=rolling_mean,
                    mode='lines',
                    name='Rolling Mean'))
    fig.add_trace(go.Scattergl(x=filtered_df.index, y=filtered_df[f"yhat_{ticker}"],
                    mode='lines',
                    name="Predicted"))
    
    fig.update_xaxes(title_text='Date',
    title_font=dict(
        family="Arial, sans-serif",
        size=18,
        color="black"))
    fig.update_yaxes(
    title_text='Feedmill Price',
    title_font=dict(
        family="Arial, sans-serif",
        size=18,
        color="black"))
    fig.update_layout(legend=dict(title="Legend", orientation="v", y=1.1, x=1.05, xanchor="center", bgcolor='rgba(0,0,0,0)'),
                     margin=dict(l=20, r=20, t=80, b=30)
                     )
    fig.update_traces(marker=dict(size=1.5))
    return fig

@app.callback(Output('download-dataframe-csv', 'data'),
              Input('export-csv-button', 'n_clicks'),
              Input('ticker', 'value'),
              prevent_initial_call=True)
def download_csv(n_clicks, ticker):
    if n_clicks == 0:
        raise PreventUpdate
    filtered_df_weekly = df_weekly_average.loc[:, [ticker, f"yhat_{ticker}"]]
    filtered_df_weekly[f"{ticker}_rolling_mean"] = filtered_df_weekly[ticker].rolling(window=7, min_periods=1).mean().shift(1)
    filtered_df_weekly.reset_index(inplace=True)
    csv_string = io.StringIO()
    filtered_df_weekly.to_csv(csv_string, index=False, encoding='utf8')
    csv_string.seek(0)
    timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    filename = f"{ticker}_weekly_price_forecasts_{timestamp}.csv"
    return dict(filename=filename, content=csv_string.getvalue())


@app.callback(Output('page-content', 'children'),
              [Input('url', 'pathname')])
def display_page(pathname):
    if pathname == '/':
        return html.Div()
    elif pathname == '/page-1':
        return page_1_layout
    elif pathname == '/page-2':
        return page_2_layout
    else:
        return html.Div([
            html.H1('404 Error: Page not found'),
            dcc.Link('Go back to home', href='/')
        ])
# Run the app
if __name__ == '__main__':
    app.run_server(debug=False, port=8000)

Note: I’m just returning Page1. If you want to make multiple pages with multiple py file. I think you need to revise your code that we need one main py, and then pages py.

1 Like

This seems great. Let me check this out I will revert to you in sometime. Many thanks @hoatran

@hoatran this works great. I have created the single-page app. I had one question, in particular, how could I host a .ipynb file with the Data ingestion from google sheets via API and data processing, the ML model predictions and then the dash app in the last? I was trying using CircleCI by first pushing the ipynb file into github and then adding the config for circleci. Let me know if that is the process I should follow.

Did you try google colab?