Recap and final exam
Ten modules to move from an empty file to a churn dashboard the sales team opens every morning. Here is the course condensed, then the threads that run through it, and finally the exam.
The course at a glance
| Module | The essential point |
|---|---|
| 1. Execution model | The whole script re-runs on every interaction; st.set_page_config first, session_state for persistence, @st.cache_* for expensive work |
| 2. Components | Widgets are functions that return the current value; st.metric for KPIs, delta_color="inverse" when up is bad |
| 3. Layout | Columns, tabs, sidebar and expanders are containers; hidden tabs still execute their code on rerun |
| 4. Charts and tables | Native for quick, Plotly for interactive, Altair for the grammar; always use_container_width=True |
| 5. Caching | cache_data copies (values), cache_resource shares (objects); underscore prefix skips hashing |
| 6. State and forms | session_state is the tab-scoped dict; st.form batches inputs and silences on_change |
| 7. Upload and download | sep=None, engine="python" handles the CSV quirks; validate before scoring; cache the serialization |
| 8. Calling a model | Local behind cache_resource, remote behind requests with a mandatory timeout= |
| 9. Theme and pages | .streamlit/config.toml and st.logo for the brand; st.navigation for a multipage app |
| 10. Deployment | Community Cloud or Docker with --server.address=0.0.0.0; secrets in st.secrets, never in git |
The threads running through the course
Everything comes back to the rerun model. A stateless top-to-bottom re-execution on every gesture is what makes Streamlit small enough to learn in a day. Every mechanism the framework adds — caches, session state, forms, callbacks — exists to give you controlled escapes from that model when the top-to-bottom default is not what you need. Knowing that one fact makes every module deducible rather than memorizable.
Widgets and state share a namespace. A widget with key="x" writes
to st.session_state["x"] and reads back from it. That single sentence
explains why you pre-fill a widget by writing to session state, why
renaming a label resets a widget, and why two widgets cannot share a
key. Most of the confusion around forms, callbacks and multipage apps
disappears once that connection is internalized.
Local versus remote is not a coding decision, it is an operational
one. Loading a model with joblib is fifteen lines; hitting an
inference API is fifteen lines; the difference is who owns the release
cycle and who pays for the hardware. Course 40 covers the API side of
that decision; here, the client side is what the app must handle —
timeouts, error messages, a spinner and a cache with a short TTL.
Deployment is when access control becomes real. A shared password gate takes five lines and is good enough for a low-value internal tool; anything more requires an identity provider, and the OIDC or reverse-proxy path is the industry answer. Whichever path you take, authorization belongs inside the app, not only at the door — an authenticated user is not necessarily a whitelisted one.
Before you share the dashboard
A quick checklist to run through before pushing the URL to the sales team channel:
- Rerun: no top-level counter,
session_stateinitialized once with a guard,@st.cache_resourceon the model,@st.cache_dataon the DataFrames. - Layout:
layout="wide"if you have KPI cards, one primary button per screen, a sidebar that stays readable when collapsed, no widget the app strictly needs hidden behind an expander. - State and forms: every widget in a long form has a stable
key=; every callback is a state change, not slow work. - Upload and download: file size cap set explicitly, columns validated before scoring, results downloadable as UTF-8 CSV.
- Model call: every
requests.posthas atimeout=, every failure writes a user-friendlyst.error, no traceback in the browser. - Theme:
primaryColormatches the brand, a favicon and a logo, toasts for background events, tooltips (help=) on every input the user might misread. - Deployment:
.streamlit/secrets.tomlin.gitignore, model not in the repo,--server.address=0.0.0.0in the Dockerfile, an identity provider in front of anything that touches customer data.
The final exam
The exam has 40 questions covering the ten modules: the execution
model and its consequences, choosing the right widget for the right
input, laying out a page with columns and tabs, choosing between the
three chart tiers, cache_data versus cache_resource, session_state
and forms, uploading and validating a CSV, calling a local or remote
model, theming and multipage navigation, and finally deployment with
secrets and access control.
Several questions present situations to diagnose: a page that lags
because the model loads on every rerun, a "wrong password" branch that
leaks the password by timing, a session_state reset because the widget
key changed, a Plotly chart that overflows its column. It is judgment
that is assessed, not the recitation of API signatures.
On success, your certificate of completion is issued immediately; its number is verifiable by any third party on the platform.
Take the table above and, for each row, ask yourself "how would I see
that I am wrong here?". If you can say why a model reloads on every
keystroke, why a shared password compared with == leaks over the
network, why a widget resets when you rename its label, and why
--server.address=0.0.0.0 matters in a container, you are ready. Good
luck!
Final exam
Ready to validate this course?
40 questions drawn at random from the course bank · passing score 70% · verifiable PDF certificate issued immediately on success.
Start the examYou need to be signed in to your InSkillML account with an active subscription. You can also start the exam from My courses.