diff --git a/docs/projects/agentic-code-reviewer/index.md b/docs/projects/agentic-code-reviewer/index.md
index 9fe7c71..f0bd51a 100644
--- a/docs/projects/agentic-code-reviewer/index.md
+++ b/docs/projects/agentic-code-reviewer/index.md
@@ -23,11 +23,11 @@ This assumes Python 101 and enough comfort with git to know what `git diff` show
## 🎯 What you'll do
-1. Install `uv`, get a free-tier LLM API key, and set up a small project — all in one place, before any building starts.
-2. Use Python's `subprocess` module to run `git diff` for real and capture its output as text.
-3. Design a system prompt that turns a general-purpose LLM into a focused, structured code reviewer.
-4. Send a diff to the model and print its feedback in a clear, readable format.
-5. Run the whole tool against a real diff — your own uncommitted changes, and a specific past commit from this course's own repo history.
+1. **Set up** `uv`, a free-tier LLM API key, and a small project — all in one place, before any building starts.
+2. **Capture** a real `git diff` with Python's `subprocess` module and read its output as text.
+3. **Design** a system prompt that turns a general-purpose LLM into a focused, structured code reviewer.
+4. **Evaluate** a diff with the model and **present** its feedback in a clear, readable format.
+5. **Apply** the whole tool to real diffs — your own uncommitted changes, and a specific past commit from this course's own repo history.
## Where to run this
@@ -41,6 +41,7 @@ This assumes Python 101 and enough comfort with git to know what `git diff` show
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/agentic-code-reviewer/notebook.ipynb)
[](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fagentic-code-reviewer%2Fnotebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything you need before you write a line of the reviewer itself: a real Python, a free API key, and a small project to hold both.
@@ -417,3 +418,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/ai-agent/index.md b/docs/projects/ai-agent/index.md
index 59ffa92..fded38f 100644
--- a/docs/projects/ai-agent/index.md
+++ b/docs/projects/ai-agent/index.md
@@ -22,10 +22,10 @@ This is optional and ungraded — a good fit once you've finished Python 101 (da
## 🎯 What you'll do
-1. Install `uv`, a fast, modern tool for managing Python itself and your project's dependencies — no separate Python installer needed.
-2. Get a free-tier AI API key. **You're free to use whichever provider you like** — GitHub Models is the suggested default below since it needs no separate signup (you already have a GitHub account), but Gemini, Groq, Mistral, Cerebras, and OpenRouter all have workable free tiers too.
-3. Set up a small project and install LangChain's `deepagents`.
-4. Write and run one small agent, locally, from your own terminal.
+1. **Set up** `uv`, a fast, modern tool for managing Python itself and your project's dependencies — no separate Python installer needed.
+2. **Obtain** a free-tier AI API key. **You're free to use whichever provider you like** — GitHub Models is the suggested default below since it needs no separate signup (you already have a GitHub account), but Gemini, Groq, Mistral, Cerebras, and OpenRouter all have workable free tiers too.
+3. **Configure** a small project with LangChain's `deepagents` installed.
+4. **Write and run** one small agent, locally, from your own terminal.
## Where to run this
@@ -41,6 +41,7 @@ This is optional and ungraded — a good fit once you've finished Python 101 (da
Be honest with yourself about the tradeoff, though: this is a lower-fidelity way to experience the project than a real local `uv` project — no separate files, no real project structure, just cells in a notebook. Treat it as a quick way to experiment, not the primary path.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -286,3 +287,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/browser-automation-agent/index.md b/docs/projects/browser-automation-agent/index.md
index ccef980..f245570 100644
--- a/docs/projects/browser-automation-agent/index.md
+++ b/docs/projects/browser-automation-agent/index.md
@@ -28,12 +28,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install Python [Playwright](https://playwright.dev/python/) and a real Chromium browser binary.
-2. Write a hardcoded script that fills out a real practice form by hand — and see exactly how brittle
- that is.
-3. Wrap page-reading and field-filling as **tools** an LLM agent can call.
-4. Give the agent a plain-English goal ("fill this form with these details") and let it decide which
- fields map to which tool calls, then run it end-to-end and verify the real submission.
+1. **Install** Python [Playwright](https://playwright.dev/python/) and a real Chromium browser binary.
+2. **Author** a hardcoded script that fills out a real practice form by hand — and **analyze** exactly how brittle that approach is.
+3. **Design** page-reading and field-filling as **tools** an LLM agent can call.
+4. **Direct** the agent with a plain-English goal ("fill this form with these details"), let it decide which fields map to which tool calls, then run it end-to-end and **verify** the real submission.
## Where to run this
@@ -59,6 +57,7 @@ demo only the agent's *decision-making* — which field it thinks matches which
with no actual browser opened anywhere. That's a legitimate way to explore Step 3's reasoning in
isolation, but it is not this project; treat it as a toy, not a substitute for Setup below.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -406,3 +405,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/chat-with-pdfs/index.md b/docs/projects/chat-with-pdfs/index.md
index 82944ab..9189a32 100644
--- a/docs/projects/chat-with-pdfs/index.md
+++ b/docs/projects/chat-with-pdfs/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Extract text from a folder of PDFs, page by page, and split it into small chunks — keeping each chunk's source filename and page number attached.
-2. Turn each chunk into a vector, entirely locally, with no API key and no cost, using `sentence-transformers`.
-3. Retrieve the chunks most relevant to a question across *all* the PDFs at once, then ask a free-tier LLM to answer using only that context — with a `(source, page N)` citation required for every fact.
-4. Wrap it all in a small interactive loop so you can keep asking questions without re-running a script each time.
+1. **Extract** text from a folder of PDFs, page by page, and **split** it into small chunks — keeping each chunk's source filename and page number attached.
+2. **Embed** each chunk as a vector, entirely locally, with no API key and no cost, using `sentence-transformers`.
+3. **Retrieve** the chunks most relevant to a question across *all* the PDFs at once, then **ask** a free-tier LLM to answer using only that context — with a `(source, page N)` citation required for every fact.
+4. **Build** a small interactive loop so you can keep asking questions without re-running a script each time.
## Where to run this
@@ -42,6 +42,7 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
Be honest with yourself about the tradeoff, though: this is a lower-fidelity way to experience the project than a real local `uv` project — no separate files, no real project structure, just cells in a notebook. Treat it as a quick way to experiment, not the primary path.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -512,3 +513,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/codebase-knowledge-graph/index.md b/docs/projects/codebase-knowledge-graph/index.md
index d21715b..211ca60 100644
--- a/docs/projects/codebase-knowledge-graph/index.md
+++ b/docs/projects/codebase-knowledge-graph/index.md
@@ -23,12 +23,12 @@ This assumes Python 101 and comfort with functions and imports — nothing from
## 🎯 What you'll do
-1. Install `uv` and set up a small project with `networkx` and `pyvis` — no API key, no signup, nothing to configure.
-2. Parse a single Python file's AST to find its function definitions, class definitions, and imports.
-3. Walk an entire repository and build a graph out of everything you find, using `networkx`.
-4. Add edges for **import** and **call** relationships, so the graph captures how the pieces actually connect, not just what exists.
-5. Visualize the graph as an interactive HTML page with `pyvis` (and, optionally, a static image with `matplotlib`).
-6. Write a small query function — "what does this function call?", "what imports this module?" — and run the whole thing against a real repository.
+1. **Set up** a small project with `uv`, `networkx`, and `pyvis` — no API key, no signup, nothing to configure.
+2. **Parse** a single Python file's AST to **identify** its function definitions, class definitions, and imports.
+3. **Build** a graph of an entire repository with `networkx`, walking everything you find.
+4. **Model** **import** and **call** relationships as graph edges, so the graph captures how the pieces actually connect, not just what exists.
+5. **Visualize** the graph as an interactive HTML page with `pyvis` (and, optionally, a static image with `matplotlib`).
+6. **Query** the graph with a small function — "what does this function call?", "what imports this module?" — and **evaluate** it against a real repository.
## Where to run this
@@ -448,3 +448,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/commit-message-agent/index.md b/docs/projects/commit-message-agent/index.md
index a815207..120fc54 100644
--- a/docs/projects/commit-message-agent/index.md
+++ b/docs/projects/commit-message-agent/index.md
@@ -23,11 +23,11 @@ This assumes Python 101 and enough comfort with git to know what `git add` and `
## 🎯 What you'll do
-1. Install `uv`, get a free-tier LLM API key, and set up a small project — all in one place, before any building starts.
-2. Use Python's `subprocess` module to run `git diff --staged` for real and capture its output as text.
-3. Design a system prompt that turns a general-purpose LLM into a focused Conventional-Commits-style message drafter.
-4. Build an interactive CLI loop: show the draft, let the user accept, edit, or regenerate it.
-5. Wire the loop up to actually run `git commit -m "..."` — but only after the user explicitly confirms.
+1. **Set up** `uv`, a free-tier LLM API key, and a small project — all in one place, before any building starts.
+2. **Capture** a staged `git diff --staged` with Python's `subprocess` module and read its output as text.
+3. **Design** a system prompt that turns a general-purpose LLM into a focused Conventional-Commits-style message drafter.
+4. **Build** an interactive CLI loop: show the draft, let the user accept, edit, or regenerate it.
+5. **Execute** the loop's `git commit -m "..."` step — but only after the user explicitly confirms.
## Where to run this
@@ -40,6 +40,7 @@ This assumes Python 101 and enough comfort with git to know what `git add` and `
[](https://colab.research.google.com/github/abderrahim-lectures/python-data-analysis-course/blob/main/examples/commit-message-agent/notebook.ipynb)
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/commit-message-agent/notebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything you need before you write a line of the drafter itself: a real Python, a free API key, and a small project to hold both.
@@ -454,3 +455,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/dependency-freshness-checker/index.md b/docs/projects/dependency-freshness-checker/index.md
index 9d722fe..57101d6 100644
--- a/docs/projects/dependency-freshness-checker/index.md
+++ b/docs/projects/dependency-freshness-checker/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded — a good fit once you've finished Python 101 (no
## 🎯 What you'll do
-1. Parse a real `pyproject.toml` file and extract its dependency list.
-2. Query PyPI's public JSON API to find each dependency's current published version.
-3. Compare your pinned/installed version against the latest, using real semantic-version parsing — not naive string comparison.
-4. Print a clean, categorized freshness report (up to date / outdated / unable to check).
+1. **Parse** a real `pyproject.toml` file and **extract** its dependency list.
+2. **Query** PyPI's public JSON API to find each dependency's current published version.
+3. **Compare** your pinned/installed version against the latest, using real semantic-version parsing — not naive string comparison.
+4. **Produce** a clean, categorized freshness report (up to date / outdated / unable to check).
## Where to run this
@@ -290,3 +290,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/docs-qa-bot/index.md b/docs/projects/docs-qa-bot/index.md
index a74a683..332e54c 100644
--- a/docs/projects/docs-qa-bot/index.md
+++ b/docs/projects/docs-qa-bot/index.md
@@ -25,11 +25,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Create a Discord bot application and grab its token from Discord's free developer portal.
-2. Install `uv`, set up a project, and add `discord.py` alongside the same embedding/retrieval libraries from the RAG App project.
-3. Reuse and adapt the RAG App's retrieval pipeline over a folder of documentation instead of personal notes.
-4. Wire a `discord.py` message handler so the bot retrieves relevant docs and generates an answer whenever it's mentioned.
-5. Invite the bot to a test server and ask it real questions, end to end.
+1. **Create** a Discord bot application and **retrieve** its token from Discord's free developer portal.
+2. **Set up** a project with `uv`, adding `discord.py` alongside the same embedding/retrieval libraries from the RAG App project.
+3. **Adapt** the RAG App's retrieval pipeline to a folder of documentation instead of personal notes.
+4. **Implement** a `discord.py` message handler so the bot retrieves relevant docs and generates an answer whenever it's mentioned.
+5. **Evaluate** the bot on a test server by asking it real questions, end to end.
## Where to run this
@@ -45,6 +45,7 @@ That said, the RAG pipeline *underneath* the bot — chunking, embedding, retrie
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/docs-qa-bot/notebook.ipynb)
[](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fdocs-qa-bot%2Fnotebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything in this section only needs to happen once, before you write a line of the bot itself: installing `uv`, creating the Discord bot application and grabbing its token, getting a free LLM key, and setting up the project. Every step after this one assumes all of it is already done.
@@ -486,3 +487,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/email-triage-agent/index.md b/docs/projects/email-triage-agent/index.md
index ac268f1..15be798 100644
--- a/docs/projects/email-triage-agent/index.md
+++ b/docs/projects/email-triage-agent/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Load a bundled folder of sample emails — no real inbox, password, or IMAP setup required to complete this project.
-2. Get a free-tier AI API key and write a prompt that categorizes each email (urgent / needs-reply / newsletter / fyi / spam-ish) and assigns it a priority.
-3. Write a second prompt that drafts a suggested reply for anything that needs one — and build in a hard rule this agent never breaks: **it never sends anything, ever**. Every draft is only printed and saved locally for you to read and send yourself.
-4. Run the whole pipeline end to end and read what it produced.
-5. *(Optional, "go further")* Point the same script at your own real inbox over IMAP instead of the sample emails, using a Gmail "app password" — not your real password.
+1. **Load** a bundled folder of sample emails — no real inbox, password, or IMAP setup required to complete this project.
+2. **Obtain** a free-tier AI API key and **write** a prompt that categorizes each email (urgent / needs-reply / newsletter / fyi / spam-ish) and assigns it a priority.
+3. **Design** a second prompt that drafts a suggested reply for anything that needs one — with a hard rule this agent never breaks: **it never sends anything, ever**. Every draft is only printed and saved locally for you to read and send yourself.
+4. **Run** the whole pipeline end to end and **review** what it produced.
+5. *(Optional, "go further")* **Apply** the same script to your own real inbox over IMAP, using a Gmail "app password" — not your real password.
## Where to run this
@@ -45,6 +45,7 @@ Click a badge, run the cells top to bottom, and paste in a free-tier API key whe
**A note on the optional IMAP extension**: none of the three options above are a good place to type in a real email password, app password or not. If you try the optional "go further" step, do it locally, in a `.env` file that never leaves your machine — not in a notebook cell or a cloud IDE you don't fully control.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -473,3 +474,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/finance-agent/index.md b/docs/projects/finance-agent/index.md
index 3f4478b..7e1febc 100644
--- a/docs/projects/finance-agent/index.md
+++ b/docs/projects/finance-agent/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded — a good fit once you've finished Python 101. Se
## 🎯 What you'll do
-1. Load and clean a sample bank CSV export with pandas.
-2. Build a fast, rule-based baseline categorizer — and see exactly where keyword rules run out of road.
-3. Build an LLM agent tool that categorizes the transactions the rules couldn't confidently label, and explains its reasoning.
-4. Flag statistically unusual transactions (an unusually large purchase compared to that category's typical spend) and have the agent summarize what it found in plain English.
+1. **Load** and **clean** a sample bank CSV export with pandas.
+2. **Build** a fast, rule-based baseline categorizer — and **analyze** exactly where keyword rules run out of road.
+3. **Design** an LLM agent tool that categorizes the transactions the rules couldn't confidently label, and **explains** its reasoning.
+4. **Detect** statistically unusual transactions (an unusually large purchase compared to that category's typical spend) and have the agent **summarize** what it found in plain English.
## Where to run this
@@ -42,6 +42,7 @@ This is optional and ungraded — a good fit once you've finished Python 101. Se
Be honest with yourself about the tradeoff, though: this is a lower-fidelity way to experience the project than a real local `uv` project — no separate files, no real project structure, just cells in a notebook. Treat it as a quick way to experiment, not the primary path.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -354,3 +355,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/finetune-llm-unsloth/index.md b/docs/projects/finetune-llm-unsloth/index.md
index 78a84d9..6327e6b 100644
--- a/docs/projects/finetune-llm-unsloth/index.md
+++ b/docs/projects/finetune-llm-unsloth/index.md
@@ -26,10 +26,10 @@ The AI Agent project runs entirely on your own machine. This one can't, fully
## 🎯 What you'll do
-1. Install `uv` and set up a local project — same first step as every project.
-2. Prepare a small dataset of examples that show the model the behavior you want it to learn.
-3. Get free GPU access via Google Colab or Kaggle, and use Unsloth to LoRA-fine-tune a small open model (around 1 billion parameters) on your dataset.
-4. Download the result — a small "adapter" file, not a whole new model — and run it locally to see your fine-tuned model in action.
+1. **Set up** a local project with `uv` — same first step as every project.
+2. **Prepare** a small dataset of examples that show the model the behavior you want it to learn.
+3. **Fine-tune** a small open model (around 1 billion parameters) with Unsloth on a free GPU via Google Colab or Kaggle, using LoRA.
+4. **Download** the result — a small "adapter" file, not a whole new model — and run it locally to **evaluate** your fine-tuned model in action.
## Where to run this
@@ -180,3 +180,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/github-issue-triage-agent/index.md b/docs/projects/github-issue-triage-agent/index.md
index de6b0c6..9649214 100644
--- a/docs/projects/github-issue-triage-agent/index.md
+++ b/docs/projects/github-issue-triage-agent/index.md
@@ -23,11 +23,11 @@ This assumes Python 101 — nothing from Data Analysis is required. It's optiona
## 🎯 What you'll do
-1. Install `uv`, get a free-tier LLM API key, and set up a small project.
-2. Fetch OPEN issues from a real public GitHub repo using GitHub's free REST API — no authentication required for public reads.
-3. Write a prompt that turns one issue's title and body into a request for a suggested triage label and a one-sentence rationale.
-4. Call the LLM for each issue and parse its reply.
-5. Print a readable triage report, and run the whole thing end to end against a real repo.
+1. **Set up** `uv`, a free-tier LLM API key, and a small project.
+2. **Fetch** OPEN issues from a real public GitHub repo using GitHub's free REST API — no authentication required for public reads.
+3. **Design** a prompt that turns one issue's title and body into a request for a suggested triage label and a one-sentence rationale.
+4. **Call** the LLM for each issue and **parse** its reply.
+5. **Produce** a readable triage report, and **evaluate** the whole pipeline end to end against a real repo.
## Where to run this
@@ -41,6 +41,7 @@ This assumes Python 101 — nothing from Data Analysis is required. It's optiona
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/github-issue-triage-agent/notebook.ipynb)
[](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fgithub-issue-triage-agent%2Fnotebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### 1. Install `uv`
@@ -343,3 +344,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/habit-streak-visualizer/index.md b/docs/projects/habit-streak-visualizer/index.md
index c674ca5..ba96840 100644
--- a/docs/projects/habit-streak-visualizer/index.md
+++ b/docs/projects/habit-streak-visualizer/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Design a simple check-in log format (a CSV: date, habit, done) and write a CLI to append to it.
-2. Compute a habit's current streak and longest streak from that log.
-3. Lay a range of days out into a GitHub-contributions-graph-style grid: seven weekday rows by however many week columns the range needs.
-4. Render that grid as a matplotlib heatmap, colored by how long a streak was building on each day, using several months of real-looking sample data so the picture actually looks interesting.
+1. **Design** a simple check-in log format (a CSV: date, habit, done) and **build** a CLI to append to it.
+2. **Compute** a habit's current streak and longest streak from that log.
+3. **Arrange** a range of days into a GitHub-contributions-graph-style grid: seven weekday rows by however many week columns the range needs.
+4. **Render** that grid as a matplotlib heatmap, colored by how long a streak was building on each day, using several months of real-looking sample data so the picture actually looks interesting.
## Where to run this
@@ -315,3 +315,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/job-aggregator/index.md b/docs/projects/job-aggregator/index.md
index 852563f..586d9d3 100644
--- a/docs/projects/job-aggregator/index.md
+++ b/docs/projects/job-aggregator/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Parse a single job-listing page's HTML into structured fields with BeautifulSoup.
-2. Write one small parser per source and combine several differently-structured sources into one table.
-3. Dedupe listings that were posted to more than one board, using pandas.
-4. Filter by keyword and print/save only the matches that are new since the last run.
+1. **Parse** a single job-listing page's HTML into structured fields with BeautifulSoup.
+2. **Build** one small parser per source and **combine** several differently-structured sources into one table.
+3. **Deduplicate** listings that were posted to more than one board, using pandas.
+4. **Filter** by keyword and **save** only the matches that are new since the last run.
## Where to run this
@@ -360,3 +360,4 @@ A complete parse → combine → dedupe → filter → alert pipeline: real HTML
Built something you're proud of? [`examples/student-projects/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/student-projects) is a gallery of projects other students have submitted — and its README has a full, beginner-friendly walkthrough for adding yours via a **pull request**, even if you've never used git before: forking the repo, making a branch, committing your files, and opening the PR, one step at a time. No prior git experience assumed.
+
diff --git a/docs/projects/mcp-notes-server/index.md b/docs/projects/mcp-notes-server/index.md
index 41d6c3b..ad1398d 100644
--- a/docs/projects/mcp-notes-server/index.md
+++ b/docs/projects/mcp-notes-server/index.md
@@ -23,10 +23,10 @@ If you keep notes in Obsidian, Notion, or just a plain folder of Markdown files,
## 🎯 What you'll do
-1. Install `uv` and set up a small project with the official MCP Python SDK.
-2. Index a real folder of sample Markdown notes -- load them off disk, pull out titles and modification times.
-3. Write search and lookup functions as plain Python, and test them before any MCP code is involved.
-4. Wire those functions up as MCP tools with `FastMCP`, and connect the server to Claude Desktop.
+1. **Set up** a small project with `uv` and the official MCP Python SDK.
+2. **Index** a real folder of sample Markdown notes — loading them off disk and **extracting** titles and modification times.
+3. **Write** search and lookup functions as plain Python, and **test** them before any MCP code is involved.
+4. **Expose** those functions as MCP tools with `FastMCP`, and **connect** the server to Claude Desktop.
## Where to run this
@@ -373,3 +373,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/mcp-server/index.md b/docs/projects/mcp-server/index.md
index ca644b4..b346e30 100644
--- a/docs/projects/mcp-server/index.md
+++ b/docs/projects/mcp-server/index.md
@@ -25,10 +25,10 @@ MCP is one of the more actively adopted patterns for extending AI assistants rig
## 🎯 What you'll do
-1. Install `uv` and set up a small project with the official MCP Python SDK.
-2. Write an MCP server exposing two of your own tools, using the SDK's `FastMCP` API.
-3. Run your server locally and test its tools by hand with the MCP Inspector, before connecting any real AI client.
-4. Register your server with Claude Desktop's free tier and watch it actually call your code.
+1. **Set up** a small project with `uv` and the official MCP Python SDK.
+2. **Design** an MCP server exposing two of your own tools, using the SDK's `FastMCP` API.
+3. **Run** your server locally and **test** its tools by hand with the MCP Inspector, before connecting any real AI client.
+4. **Register** your server with Claude Desktop's free tier and **observe** it actually calling your code.
## Where to run this
@@ -247,3 +247,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/mcp-sqlite-server/index.md b/docs/projects/mcp-sqlite-server/index.md
index 6166845..f56ee1e 100644
--- a/docs/projects/mcp-sqlite-server/index.md
+++ b/docs/projects/mcp-sqlite-server/index.md
@@ -23,10 +23,10 @@ This assumes Python 101, ideally Data Analysis too (comfort with tables, columns
## 🎯 What you'll do
-1. Build a small, realistic SQLite database with a few related tables, using nothing but the standard library's `sqlite3` module.
-2. Write plain Python functions to list tables, describe a table's schema, and run a query — with a real, non-hand-wavy safety check that rejects anything that isn't a read-only `SELECT`.
-3. Wire those functions up as MCP tools with `FastMCP`, the same decorator-based API from the Build an MCP Server project.
-4. Connect your server to Claude Desktop and ask it a genuine plain-English question, watching it write and run its own SQL through your tools.
+1. **Build** a small, realistic SQLite database with a few related tables, using nothing but the standard library's `sqlite3` module.
+2. **Write** plain Python functions to list tables, describe a table's schema, and run a query — with a real, non-hand-wavy safety check that rejects anything that isn't a read-only `SELECT`.
+3. **Expose** those functions as MCP tools with `FastMCP`, the same decorator-based API from the Build an MCP Server project.
+4. **Connect** your server to Claude Desktop and **evaluate** it with a genuine plain-English question, watching it write and run its own SQL through your tools.
## Where to run this
@@ -362,3 +362,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to letting an AI write its own SQL — carefully. 🎓
+
diff --git a/docs/projects/meeting-notes-summarizer/index.md b/docs/projects/meeting-notes-summarizer/index.md
index de64ca9..9f8815f 100644
--- a/docs/projects/meeting-notes-summarizer/index.md
+++ b/docs/projects/meeting-notes-summarizer/index.md
@@ -23,12 +23,12 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv`, a fast, modern tool for managing Python itself and your project's dependencies.
-2. Get a free-tier LLM API key — any of six providers work.
-3. Load a real meeting transcript (three realistic samples ship with this project, so it runs with zero setup).
-4. Design a prompt that asks the model to return **structured JSON**, not free-flowing prose — the core, transferable skill of this project.
-5. Call the model, then parse and validate its JSON response — handling the case where it comes back slightly malformed, which happens more often than you'd like.
-6. Format the structured result as both readable Markdown and a `.json` file, and run the whole thing end to end on a real transcript.
+1. **Set up** `uv`, a fast, modern tool for managing Python itself and your project's dependencies.
+2. **Obtain** a free-tier LLM API key — any of six providers work.
+3. **Load** a real meeting transcript (three realistic samples ship with this project, so it runs with zero setup).
+4. **Design** a prompt that asks the model to return **structured JSON**, not free-flowing prose — the core, transferable skill of this project.
+5. **Call** the model, then **parse** and **validate** its JSON response — handling the case where it comes back slightly malformed, which happens more often than you'd like.
+6. **Format** the structured result as both readable Markdown and a `.json` file, and **run** the whole thing end to end on a real transcript.
## Where to run this
@@ -42,6 +42,7 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/meeting-notes-summarizer/notebook.ipynb)
[](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fmeeting-notes-summarizer%2Fnotebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything you need before writing any summarization code — installing `uv`, creating the project, getting a free API key, and setting it up as an environment variable — lives in this one section, so you only have to do it once.
@@ -492,3 +493,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/ml-classifier/index.md b/docs/projects/ml-classifier/index.md
index 70ba2a6..34b89de 100644
--- a/docs/projects/ml-classifier/index.md
+++ b/docs/projects/ml-classifier/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv` and set up a local project with `scikit-learn` and `pandas`.
-2. Load the same Titanic dataset from Week 10, and encode its categorical columns as numbers.
-3. Split the data into a training set and a test set, and understand why that split matters.
-4. Train a `LogisticRegression` classifier and use it to predict survival.
-5. Evaluate it properly, then train a second model (`RandomForestClassifier`) and compare.
+1. **Set up** a local project with `uv`, `scikit-learn`, and `pandas`.
+2. **Load** the same Titanic dataset from Week 10, and **encode** its categorical columns as numbers.
+3. **Split** the data into a training set and a test set, and **explain** why that split matters.
+4. **Train** a `LogisticRegression` classifier and **apply** it to predict survival.
+5. **Evaluate** it properly, then train a second model (`RandomForestClassifier`) and **compare** the two.
## Where to run this
@@ -257,3 +257,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/multi-agent-research/index.md b/docs/projects/multi-agent-research/index.md
index c947ccb..27ab4a8 100644
--- a/docs/projects/multi-agent-research/index.md
+++ b/docs/projects/multi-agent-research/index.md
@@ -25,11 +25,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv`, a fast, modern tool for managing Python itself and your project's dependencies.
-2. Get a free-tier AI API key — the same six-provider choice as the AI Agent project.
-3. Set up a small project and install `deepagents`.
-4. Define three sub-agents — planner, researcher, writer — each with its own narrow system prompt.
-5. Wire them together into one top-level agent and run it on a real research question, end to end.
+1. **Set up** `uv`, a fast, modern tool for managing Python itself and your project's dependencies.
+2. **Obtain** a free-tier AI API key — the same six-provider choice as the AI Agent project.
+3. **Configure** a small project with `deepagents` installed.
+4. **Define** three sub-agents — planner, researcher, writer — each with its own narrow system prompt.
+5. **Integrate** them into one top-level agent and **evaluate** it on a real research question, end to end.
## Where to run this
@@ -46,6 +46,7 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
It's a lower-fidelity way to experience the project than a real local `uv` project, but perfectly workable for trying the idea out quickly.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything below gets your environment fully ready before any building starts: installing `uv`, getting a free API key, setting up the project, and configuring your `.env` file.
@@ -276,3 +277,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/rag-notes/index.md b/docs/projects/rag-notes/index.md
index ada6cbd..d4692d0 100644
--- a/docs/projects/rag-notes/index.md
+++ b/docs/projects/rag-notes/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Take a folder of your own `.md`/`.txt` notes and split them into small, searchable chunks.
-2. Turn each chunk into a vector — a list of numbers capturing its meaning — entirely locally, with no API key and no cost, using `sentence-transformers`.
-3. Write a small local search function that finds the chunks most relevant to a question, using nothing but `numpy`.
-4. Write a script that retrieves relevant chunks, then asks a free-tier LLM to answer *using only that context*.
+1. **Split** a folder of your own `.md`/`.txt` notes into small, searchable chunks.
+2. **Embed** each chunk as a vector — a list of numbers capturing its meaning — entirely locally, with no API key and no cost, using `sentence-transformers`.
+3. **Write** a small local search function that finds the chunks most relevant to a question, using nothing but `numpy`.
+4. **Assemble** a script that retrieves relevant chunks, then asks a free-tier LLM to answer *using only that context*.
## Where to run this
@@ -42,6 +42,7 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
Click a badge, run the cells top to bottom, and paste in a free-tier LLM API key when prompted. Be honest with yourself about the tradeoff, though: this is a lower-fidelity way to experience the project than a real local `uv` project — no separate files, no real project structure, just cells in a notebook. Treat it as a quick way to experiment, not the primary path.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
### Install `uv`
@@ -459,3 +460,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/rate-limited-api/index.md b/docs/projects/rate-limited-api/index.md
index c6d11b7..3ac16cb 100644
--- a/docs/projects/rate-limited-api/index.md
+++ b/docs/projects/rate-limited-api/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded; see [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv` and set up a local FastAPI project — no external API key needed, since this project ships its own dataset.
-2. Bundle a dataset and build paginated `list`/`get` endpoints over it.
-3. Add filtering by category and author with query parameters.
-4. Build real API-key issuance and a dependency that validates a key on protected endpoints.
-5. Implement a from-scratch sliding-window rate limiter and return real `429 Too Many Requests` responses with a `Retry-After` header once a key exceeds its budget.
+1. **Set up** a local FastAPI project with `uv` — no external API key needed, since this project ships its own dataset.
+2. **Build** paginated `list`/`get` endpoints over a bundled dataset.
+3. **Implement** filtering by category and author with query parameters.
+4. **Build** real API-key issuance and a dependency that validates a key on protected endpoints.
+5. **Implement** a from-scratch sliding-window rate limiter and **return** real `429 Too Many Requests` responses with a `Retry-After` header once a key exceeds its budget.
## Where to run this
@@ -400,3 +400,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/recipe-planner-agent/index.md b/docs/projects/recipe-planner-agent/index.md
index b461b8e..ece2c5e 100644
--- a/docs/projects/recipe-planner-agent/index.md
+++ b/docs/projects/recipe-planner-agent/index.md
@@ -23,11 +23,11 @@ This assumes Python 101. Having done the [AI Agent project](/docs/projects/ai-ag
## 🎯 What you'll do
-1. Install `uv`, get a free-tier AI API key, and set up a small project with `deepagents` — all up front, in Setup below.
-2. Define a small local "recipe database" — a plain Python list of dicts, 10-15 recipes, each with its own ingredient list.
-3. Write a tool function the agent can call to search that database by ingredients you have on hand.
-4. Wire that tool into a `deepagents` agent with a system prompt that keeps it grounded in real recipes only.
-5. Ask the agent for meal suggestions from a real ingredient list, then have it build a shopping list for the one you pick.
+1. **Set up** `uv`, a free-tier AI API key, and a small project with `deepagents` — all up front, in Setup below.
+2. **Define** a small local "recipe database" — a plain Python list of dicts, 10-15 recipes, each with its own ingredient list.
+3. **Write** a tool function the agent can call to search that database by ingredients you have on hand.
+4. **Integrate** that tool into a `deepagents` agent with a system prompt that keeps it grounded in real recipes only.
+5. **Evaluate** the agent's meal suggestions from a real ingredient list, then have it **build** a shopping list for the one you pick.
## Where to run this
@@ -43,6 +43,7 @@ This assumes Python 101. Having done the [AI Agent project](/docs/projects/ai-ag
It's a lower-fidelity way to experience the project than a real local `uv` project — no separate files, no real project structure — but perfectly workable for trying the idea out. Set your API key with `os.environ["GITHUB_TOKEN"] = "..."` in the getpass cell (or use Colab's Secrets panel).
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything needed before you write a single line of the agent itself lives here — installing `uv`, getting an API key, creating the project, and setting up your `.env` file. Steps 1 onward assume all of this is already done.
@@ -410,3 +411,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/scrape-analyze/index.md b/docs/projects/scrape-analyze/index.md
index bc2554e..85f011f 100644
--- a/docs/projects/scrape-analyze/index.md
+++ b/docs/projects/scrape-analyze/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv` and set up a local project.
-2. Fetch a real web page with `requests` and parse its HTML with `beautifulsoup4`.
-3. Follow pagination links to collect an entire site's worth of data into a CSV.
-4. Load that CSV into pandas and clean it — splitting a packed string column, checking whitespace and dtypes.
-5. Analyze the cleaned data and produce a couple of honest, properly labeled charts with `matplotlib`.
+1. **Set up** a local project with `uv`.
+2. **Fetch** a real web page with `requests` and **parse** its HTML with `beautifulsoup4`.
+3. **Collect** an entire site's worth of data into a CSV by following pagination links.
+4. **Load** that CSV into pandas and **clean** it — splitting a packed string column, checking whitespace and dtypes.
+5. **Analyze** the cleaned data and **produce** a couple of honest, properly labeled charts with `matplotlib`.
## Where to run this
@@ -334,3 +334,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/study-buddy-agent/index.md b/docs/projects/study-buddy-agent/index.md
index 292f0d9..67a6f6f 100644
--- a/docs/projects/study-buddy-agent/index.md
+++ b/docs/projects/study-buddy-agent/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded — a good fit once you've finished Python 101; no
## 🎯 What you'll do
-1. Install `uv` and get a free-tier LLM API key.
-2. Load one of your own notes files and decide how much of it to hand the model as context.
-3. Write a prompt that generates quiz questions grounded in that specific text, along with an expected answer the program keeps to itself.
-4. Build the interactive loop: ask a question, take your typed answer, have the model judge it and give feedback.
-5. Track a running score and report it at the end.
+1. **Set up** `uv` and a free-tier LLM API key.
+2. **Load** one of your own notes files and **choose** how much of it to hand the model as context.
+3. **Design** a prompt that generates quiz questions grounded in that specific text, along with an expected answer the program keeps to itself.
+4. **Build** the interactive loop: ask a question, take your typed answer, have the model judge it and give feedback.
+5. **Track** a running score and **report** it at the end.
## Where to run this
@@ -43,6 +43,7 @@ This is optional and ungraded — a good fit once you've finished Python 101; no
It's a lower-fidelity way to experience it than a real local project (no real file structure, no separate `.py` files), but it's a reasonable way to try the idea quickly.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything you need before Step 1 — installing `uv`, creating the project, and getting an API key — lives here, all up front, so the steps below can focus purely on the quiz logic.
@@ -334,3 +335,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/trivia-bot/index.md b/docs/projects/trivia-bot/index.md
index 39befaa..69645d0 100644
--- a/docs/projects/trivia-bot/index.md
+++ b/docs/projects/trivia-bot/index.md
@@ -25,13 +25,13 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Create a Discord bot application and grab its token from Discord's free developer portal.
-2. Install `uv`, set up a project, and add `discord.py` alongside a free-tier LLM client.
-3. Build a fixed trivia question bank and a basic Discord slash command that posts one.
-4. Add a persistent per-player leaderboard, stored across restarts.
-5. Add an LLM-generated question mode: give the bot a topic, get back a fresh question.
-6. Wire it all into a full round loop — post a question, collect answers within a time limit, reveal the answer, update the leaderboard.
-7. Invite the bot to a test server and run real rounds, end to end.
+1. **Create** a Discord bot application and **retrieve** its token from Discord's free developer portal.
+2. **Set up** a project with `uv`, adding `discord.py` alongside a free-tier LLM client.
+3. **Build** a fixed trivia question bank and a basic Discord slash command that posts one.
+4. **Add** a persistent per-player leaderboard, stored across restarts.
+5. **Add** an LLM-generated question mode: give the bot a topic, get back a fresh question.
+6. **Integrate** it all into a full round loop — post a question, collect answers within a time limit, reveal the answer, update the leaderboard.
+7. **Evaluate** the bot on a test server with real rounds, end to end.
## Where to run this
@@ -46,6 +46,7 @@ That said, question generation and scoring *underneath* the bot are just regular
[](https://colab.research.google.com/github/abderrahim-lectures/python-data-analysis-course/blob/main/examples/trivia-bot/notebook.ipynb)
[](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/trivia-bot/notebook.ipynb)
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything in this section only needs to happen once, before you write a line of the bot itself: installing `uv`, creating the Discord bot application and grabbing its token, getting a free LLM key, and setting up the project. Every step after this one assumes all of it is already done.
@@ -538,3 +539,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/voice-to-task-agent/index.md b/docs/projects/voice-to-task-agent/index.md
index c6fc94c..f4382c2 100644
--- a/docs/projects/voice-to-task-agent/index.md
+++ b/docs/projects/voice-to-task-agent/index.md
@@ -23,9 +23,9 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Transcribe a short voice memo to text, entirely locally and for free, using OpenAI's *open-source* Whisper model (`openai-whisper`, run on your own CPU) — not the paid Whisper API.
-2. Write a prompt that asks a free-tier LLM to read that transcript and pull out structured action items: a task, an optional due date, an optional priority.
-3. Run the whole pipeline end to end on a provided sample recording (or your own), and save the result as a simple task list.
+1. **Transcribe** a short voice memo to text, entirely locally and for free, using OpenAI's *open-source* Whisper model (`openai-whisper`, run on your own CPU) — not the paid Whisper API.
+2. **Design** a prompt that asks a free-tier LLM to read that transcript and **extract** structured action items: a task, an optional due date, an optional priority.
+3. **Run** the whole pipeline end to end on a provided sample recording (or your own), and **save** the result as a simple task list.
## Where to run this
@@ -39,6 +39,7 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
**Google Colab is a notably good fit for this one** — better than for most other projects in this series. Whisper's transcription speed scales a lot with hardware, and Colab gives you a free GPU that a local CPU-only laptop doesn't: `!pip install openai-whisper` in a cell, then a GPU runtime, and even the larger Whisper model sizes (more accurate, normally too slow to consider on a CPU) become practical. If you want to experiment with model size vs. accuracy (see the tip in Step 1), Colab is where to do it. The badges above open a ready-made [`notebook.ipynb`](https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/voice-to-task-agent/notebook.ipynb) that runs the whole pipeline with zero local setup — same two-step pipeline, same sample audio, just in a hosted notebook instead of a terminal.
+**opencode** *(optional)* — a free, open-source AI coding agent that runs in your terminal. If you'd rather have an agent write and run this project for you than type the code yourself, install it with `curl -fsSL https://opencode.ai/install | bash` (or `npm install -g opencode-ai`) and point it at this repo with the same API key from Setup below. It's optional — this project's whole point is building it yourself, so treat it as a bonus, not a shortcut.
## Setup
Everything needed before you write any pipeline code — installing `uv`, creating the project, and getting an LLM API key — lives here, once, up front. The actual build starts at Step 1, assuming all of this is already in place.
@@ -350,3 +351,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/webcam-object-counter/index.md b/docs/projects/webcam-object-counter/index.md
index dd52338..4642f62 100644
--- a/docs/projects/webcam-object-counter/index.md
+++ b/docs/projects/webcam-object-counter/index.md
@@ -23,11 +23,11 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Install `uv` and set up a local project with OpenCV and a pretrained object-detection model.
-2. Run detection on a single bundled sample image and draw bounding boxes around what it finds.
-3. Count objects of one target class (e.g. `person`) and print a running total.
-4. Process a short bundled sample video frame-by-frame.
-5. Wire the same detection loop up to your own webcam for live, real-time counting.
+1. **Set up** a local project with `uv`, OpenCV, and a pretrained object-detection model.
+2. **Run** detection on a single bundled sample image and **draw** bounding boxes around what it finds.
+3. **Count** objects of one target class (e.g. `person`) and **print** a running total.
+4. **Process** a short bundled sample video frame-by-frame.
+5. **Apply** the same detection loop to your own webcam for live, real-time counting.
## Where to run this
@@ -300,3 +300,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+
diff --git a/docs/projects/wordle-clone/index.md b/docs/projects/wordle-clone/index.md
index 0c1d937..54141af 100644
--- a/docs/projects/wordle-clone/index.md
+++ b/docs/projects/wordle-clone/index.md
@@ -23,10 +23,10 @@ This is optional and ungraded. See [Real-World Projects](/docs/projects) for the
## 🎯 What you'll do
-1. Implement the core guess-feedback logic — comparing a guess to a target word and producing green/yellow/gray marks per letter, correctly handling repeated letters (the classic Wordle logic bug).
-2. Build an interactive game loop backed by a real word list, giving the player 6 guesses.
-3. Validate guesses against the word list and give clear feedback when a guess is rejected.
-4. Add persistent stats tracking — win rate, current streak, and a guess-count distribution — saved to a local JSON file so it survives across runs.
+1. **Implement** the core guess-feedback logic — comparing a guess to a target word and producing green/yellow/gray marks per letter, correctly handling repeated letters (the classic Wordle logic bug).
+2. **Build** an interactive game loop backed by a real word list, giving the player 6 guesses.
+3. **Validate** guesses against the word list and **give** clear feedback when a guess is rejected.
+4. **Add** persistent stats tracking — win rate, current streak, and a guess-count distribution — saved to a local JSON file so it survives across runs.
## Where to run this
@@ -328,3 +328,4 @@ Built something you're proud of? [`examples/student-projects/`](https://github.c
Welcome to writing Python outside the browser. 🎓
+