Data App Tutorial
In this tutorial, you build a Streamlit app that explores a world cities dataset, then deploy it to Streamlit Cloud so anyone can use it.
Before the Lesson
- Create a GitHub account at https://github.com/signup if you don't have one (done in the previous lab), and install GitHub Desktop.
- Create a Streamlit account at https://share.streamlit.io/signup — sign up with your GitHub account.
- Download worldcities.csv.zip. The dataset is revised based on this Kaggle Dataset.
Set Up the Project
Create a new uv project for the app and install the packages:
uv init --python 3.14 my-streamlit
cd my-streamlit
uv add streamlit pandas matplotlibUnzip worldcities.csv.zip and move worldcities.csv into the my-streamlit folder.
The Dataset
Each row of worldcities.csv is a city with a population over one million. The app uses these columns:
cityandcountry— the city name and its countrylatandlon— the location, used byst.map()population— the population in millions, from about 1.0 (the smallest city) to 38.0 (Tokyo), with a mean of 3.6. The app's population slider goes from 0 to 40 with a default of 3.6.capital— whether the city is a capital, used by the app's multi-select:primary- country's capital (e.g. Washington D.C.)admin- first-level admin capital (e.g. Little Rock, AR)minor- lower-level admin capital (e.g. Fayetteville, AR)nanif not a capital (nanis not a string - it's a keyword in Pandas for Null)
Build the App
Create a new app-cities.py file in the my-streamlit folder with the following content, which is explained next:
import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('seaborn-v0_8')
st.title('World Cities')
df = pd.read_csv('worldcities.csv')
# note that you have to use 0.0 and 40.0 given that the data type of population is float
population_filter = st.slider('Minimal Population (Millions):', 0.0, 40.0, 3.6) # min, max, default
# create a multi select
capital_filter = st.sidebar.multiselect(
'Capital Selector',
df.capital.unique(), # options
df.capital.unique()) # defaults
# create a input form
form = st.sidebar.form("country_form")
country_filter = form.text_input('Country Name (enter ALL to reset)', 'ALL')
form.form_submit_button("Apply")
# filter by population
df = df[df.population >= population_filter]
# filter by capital
df = df[df.capital.isin(capital_filter)]
if country_filter!='ALL':
df = df[df.country == country_filter]
# show on map
st.map(df)
# show dataframe
st.subheader('City Details:')
st.write(df[['city', 'country', 'population']])
# show the plot
st.subheader('Total Population By Country')
fig, ax = plt.subplots(figsize=(20, 5))
pop_sum = df.groupby('country')['population'].sum()
pop_sum.plot.bar(ax=ax)
st.pyplot(fig)NOTE: whenever you interact with the app using any widget, such as changing the slider's value, the ENTIRE file is executed again from top to bottom.
- title, subtitle using
st.title()andst.subheader() - show the map using
st.map()the dataframe must have columns namedlatitudeorlatandlongitudeorlon - create a slider using
st.slider() - create a multi-select using
st.multiselect() - put widgets in sidebar using
st.sidebarsuch asst.sidebar.multiselect() - use
st.form()to group multiple widgets and only refresh the app when the form button is clicked, see the country filter as an example
Run the app from the my-streamlit folder:
uv run streamlit run app-cities.pyDeploy the App
To deploy the app to Streamlit Cloud, you publish the my-streamlit project to a public GitHub repository and then point Streamlit Cloud at that repository. You don't need a requirements.txt: Streamlit Cloud reads uv.lock and installs exactly the packages the project uses.
uv init already made my-streamlit a git repository, and its .gitignore keeps the .venv folder out of it. Open GitHub Desktop, choose File > Add Local Repository (or Add an Existing Repository from your Hard Drive), and select the my-streamlit folder. If GitHub Desktop says the folder is not a git repository (uv only creates one when command-line Git is installed), click create a repository and choose Python under Git Ignore, so the .venv folder stays out of the repository.
The Changes tab lists every file in the project, including app-cities.py, worldcities.csv, pyproject.toml, and uv.lock. Enter a summary such as world cities app and click Commit to main.
Then click Publish repository:

The repository must be PUBLIC — uncheck "Keep this code private". You can change the name, such as world-cities:

Go to GitHub and you should see all the project files in your repo.
Log in to https://share.streamlit.io/ and create a new app:

Choose the repo you just published, set the main file path to app-cities.py, and open Advanced settings to set the Python version to 3.14 — Streamlit Cloud defaults to 3.12, and the install fails because the project requires 3.14. Then click Deploy. You can also use the Paste GitHub URL option and enter the URL of the app file, such as https://github.com/<your-username>/world-cities/blob/main/app-cities.py:

Or fill in the repository, branch, and main file path directly:

Wait for the process to finish and you should see your app deployed:

You can share the app with anyone in the world:


To update the app later, edit the files in my-streamlit, then commit and click Push origin in GitHub Desktop — Streamlit Cloud redeploys the app automatically.
Data App
A data app lets anyone explore your data or use your model in a web browser — no Python required. We build interactive apps with Streamlit in pure Python…
Data App Lab
This is an in-class lab — there is nothing to submit. You build a Streamlit app for the California housing dataset, then deploy it to Streamlit Cloud…