Skip to content

Commit dae1d83

Browse files
committed
Add shinylive standalone example
1 parent 79c161a commit dae1d83

File tree

11 files changed

+1422
-6
lines changed

11 files changed

+1422
-6
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ dependencies = [
1111
]
1212

1313
[tool.uv.workspace]
14-
members = ["routes_example_app", "shinylive_quarto"]
14+
members = ["routes_example_app", "shinylive_quarto", "shinylive_without_quarto"]
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
site/
2+

shinylive_without_quarto/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Shinylive without quarto
2+
3+
Run app:
4+
5+
```bash
6+
uv sync
7+
8+
uvicorn --reload app:app
9+
```
10+
11+
Create standalone Shinylive app in `site` folder:
12+
13+
```bash
14+
shinylive export . site
15+
```
16+
17+
Start local webserver to server the app:
18+
19+
```bash
20+
python3 -m http.server --directory site --bind localhost 8008
21+
```
22+
23+
Navigate to [http://localhost:8008](http://localhost:8008)

shinylive_without_quarto/app.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import seaborn as sns
2+
from faicons import icon_svg
3+
4+
# Import data from shared.py
5+
from shared import app_dir, df
6+
7+
from shiny import App, reactive, render, ui
8+
9+
app_ui = ui.page_sidebar(
10+
ui.sidebar(
11+
ui.input_slider("mass", "Mass", 2000, 6000, 6000),
12+
ui.input_checkbox_group(
13+
"species",
14+
"Species",
15+
["Adelie", "Gentoo", "Chinstrap"],
16+
selected=["Adelie", "Gentoo", "Chinstrap"],
17+
),
18+
title="Filter controls",
19+
),
20+
ui.layout_column_wrap(
21+
ui.value_box(
22+
"Number of penguins",
23+
ui.output_text("count"),
24+
showcase=icon_svg("earlybirds"),
25+
),
26+
ui.value_box(
27+
"Average bill length",
28+
ui.output_text("bill_length"),
29+
showcase=icon_svg("ruler-horizontal"),
30+
),
31+
ui.value_box(
32+
"Average bill depth",
33+
ui.output_text("bill_depth"),
34+
showcase=icon_svg("ruler-vertical"),
35+
),
36+
fill=False,
37+
),
38+
ui.layout_columns(
39+
ui.card(
40+
ui.card_header("Bill length and depth"),
41+
ui.output_plot("length_depth"),
42+
full_screen=True,
43+
),
44+
ui.card(
45+
ui.card_header("Penguin data"),
46+
ui.output_data_frame("summary_statistics"),
47+
full_screen=True,
48+
),
49+
),
50+
ui.include_css(app_dir / "styles.css"),
51+
title="Penguins dashboard",
52+
fillable=True,
53+
)
54+
55+
56+
def server(input, output, session):
57+
@reactive.calc
58+
def filtered_df():
59+
filt_df = df[df["species"].isin(input.species())]
60+
filt_df = filt_df.loc[filt_df["body_mass_g"] < input.mass()]
61+
return filt_df
62+
63+
@render.text
64+
def count():
65+
return filtered_df().shape[0]
66+
67+
@render.text
68+
def bill_length():
69+
return f"{filtered_df()['bill_length_mm'].mean():.1f} mm"
70+
71+
@render.text
72+
def bill_depth():
73+
return f"{filtered_df()['bill_depth_mm'].mean():.1f} mm"
74+
75+
@render.plot
76+
def length_depth():
77+
return sns.scatterplot(
78+
data=filtered_df(),
79+
x="bill_length_mm",
80+
y="bill_depth_mm",
81+
hue="species",
82+
)
83+
84+
@render.data_frame
85+
def summary_statistics():
86+
cols = [
87+
"species",
88+
"island",
89+
"bill_length_mm",
90+
"bill_depth_mm",
91+
"body_mass_g",
92+
]
93+
return render.DataGrid(filtered_df()[cols], filters=True)
94+
95+
96+
app = App(app_ui, server)

shinylive_without_quarto/hello.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def main():
2+
print("Hello from shinylive-without-quarto!")
3+
4+
5+
if __name__ == "__main__":
6+
main()

0 commit comments

Comments
 (0)