Example runs as a jupyterlab notebook but fails as a standalone server app?

I have the following example, which successfully runs as a jupyterlab notebook, but will not run as a standalone server app.

Here is the code that runs inside JupyterLab (v3.3.2), Bokeh (v3.2.0)

from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CheckboxButtonGroup, CustomJS
from bokeh.plotting import show, figure, output_notebook
import pandas as pd
output_notebook()

def create_plot(doc):
    
    # create fake data
    x = [2, 4, 8, 5, 9, 3]
    y = [4, 8, 2, 7, 4, 6]
    id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
    color = ['red'] + ['green']*5
    df = pd.DataFrame({'x': x, 'y': y, 'ids': id_, 'color': color})

    # create column data source
    cds = ColumnDataSource(data=df)

    # create figure
    p = figure(width=300, height=200)
    p.circle(x='x', y='y', size=5, source=cds, color='color')

    # Create widget (checkbox button)
    checkbox_button_group = CheckboxButtonGroup(labels=id_, active=[0])

    # Update the colors after a click on an id
    checkbox_button_group.js_on_change("active", CustomJS(code="""
        console.log('checkbox_button_group: active=' + this.active, this.toString())
        """))

    def set_col(row, red_ids):
        color = 'red' if row in red_ids else 'green'
        return color

    def update_data(df, red_ids=None):
        if red_ids is None:
            red_ids = []
        
        df['color'] = df['ids'].apply(lambda x: set_col(x, red_ids))
        cds.data = df

    def update(attr, old, new):
        red_ids = [checkbox_button_group.labels[i] for i in checkbox_button_group.active]
        update_data(df, red_ids)

    checkbox_button_group.on_change('active', update)

    # display button & plot in a column
    doc.add_root(column(checkbox_button_group, p))

show(create_plot, notebook_url="localhost:8891")

Here is the modified code, to be run as a bokeh-server app:

# test-app.py

from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CheckboxButtonGroup, CustomJS
from bokeh.plotting import show, figure, curdoc
import pandas as pd

def create_plot(doc):

    # create fake data
    x = [2, 4, 8, 5, 9, 3]
    y = [4, 8, 2, 7, 4, 6]
    id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
    color = ['red'] + ['green']*5
    df = pd.DataFrame({'x': x, 'y': y, 'ids': id_, 'color': color})

    # create column data source
    cds = ColumnDataSource(data=df)

    # create figure
    p = figure(width=300, height=200)
    p.circle(x='x', y='y', size=5, source=cds, color='color')

    # Create widget (checkbox button)
    checkbox_button_group = CheckboxButtonGroup(labels=id_, active=[0])

    # Update the colors after a click on an id
    checkbox_button_group.js_on_change("active", CustomJS(code="""
        console.log('checkbox_button_group: active=' + this.active, this.toString())
        """))

    def set_col(row, red_ids):
        color = 'red' if row in red_ids else 'green'
        return color

    def update_data(df, red_ids=None):
        if red_ids is None:
            red_ids = []

        df['color'] = df['ids'].apply(lambda x: set_col(x, red_ids))
        cds.data = df

    def update(attr, old, new):
        red_ids = [checkbox_button_group.labels[i] for i in checkbox_button_group.active]
        update_data(df, red_ids)

    checkbox_button_group.on_change('active', update)

    # display button & plot in a column
    doc.add_root(column(checkbox_button_group, p))

if __name__ == "__main__":
    create_plot(curdoc)

When I run this with the following command:
bokeh serve --show test-app.py

I get a blank page inside the browser.

curdoc is function that needs to be called

create_plot(curdoc())

Also you need to remove the __main__ check. The module is not main, it is not being run itself, it is being executed inside another python app (the bokeh server)

@mbilyanov there are a lot of examples you can refer to in the repo:

https://github.com/bokeh/bokeh/tree/branch-3.3/examples/server/app

We created all these specifically for users to emulate and get started with.

Your solution has worked, thank you.