Last week you drew a workflow on paper. Today you open the app built from it.
| 1 | Product tour — the app as a user, then the folder behind it. |
| 2 | Get the repo — ZIP → Codex → running in your browser. |
| 3 | Concepts to explore — six words you need to read the code. |
| 4 | The question sheet — ten questions. One live, nine in your group. |
Groups of 3–4, one screen per group.
Codex is the coding side of ChatGPT. It lives in the ChatGPT desktop app, on the free plan.
Free, no student verification, identical on Mac and Windows. Install, sign in, done.
Reads your project, answers questions, edits files and runs commands — after asking you first.
Keep it today. Everything on the sheet works in either. Switch when you're ready.
Setup guide on the course site: uv + the ChatGPT app. About 15 minutes.
| 0 | Not installed yet? Course site → Setup: one line installs uv, then the ChatGPT app → sign in → Codex. Done already? Skip. |
| 1 | Go to the course site → Week 2. Same links are on Moodle. |
| 2 | Download your app's ZIP (splitit.zip or tiny-crm.zip) and unzip it into a folder you'll find again. |
| 3 | Open the folder in Codex. Open folder → the one that contains app.py. Codex calls it a project. |
| 4 | Run it. A terminal in the folder, then uv run streamlit run app.py. First time: a minute of downloads. Or ask Codex "Run the app" and approve the command. |
Cloned it last week? That works too. Everything stays on your laptop today.
Last week's trip workflow, as software. Same steps, same decisions, same data.
data/Group, member, expense. Three CSV files. That's the whole database.
app.pyOne function per screen. Where a person acts, there's a button.
logic.pyWho's in the split, how much each, who owes whom. The rules, as functions.
Groups have members, members pay for things, the app works out balances. Tables: groups · members · expenses. Half-built: settle up.
Leads move through stages, with notes, activities and follow-up dates. Tables: leads · notes · activities. Half-built: move a lead to any stage.
Both have user-reported bugs in issues/ and the same question sheet, ONBOARDING.md. Demos use SplitIt; CRM groups follow along in their own folder.
Three tools, three words, one thing on your disk.
Files in a directory. What you unzipped. Finder and File Explorer only know this word.
A folder Codex has opened. Same files, plus the memory of your threads about them.
A folder whose history is tracked. Every change recorded, undoable, copyable to GitHub. Yours becomes one next week.
One app · one folder · one project · one repository. Don't rename it, don't move it, don't nest it.
app.py | The screens. What uv run streamlit run app.py starts. |
logic.py | The rules. Balances, stages, searches, validation. |
db.py | Reads and writes the CSV files. Nothing else touches them. |
data/ | The live database. seed/ is the pristine copy; uv run python seed.py restores it. |
tests/ | Small programs that check the app. Next week. |
issues/ | Four bug reports from users. You fix #1 today. |
specs/ | Feature requests from the product manager. Next week. |
ONBOARDING.md | Your question sheet. Answer inside the file. |
One .py file, one job. app.py screens, logic.py rules, db.py storage.
A named block that does one thing: def add_expense(...). Read the name and the docstring first.
One function using another: logic.add_expense(...) inside app.py.
A CSV file: the first line is the columns, each other line a row.
The file that runs first. Here, app.py.
A check before saving: is_valid_name. Without it, bad data gets in.
Three ways to find out.
Find the button's text in app.py. Read what it calls. Read what that calls. Stop when you reach db.py.
Search the project for the exact words you see on screen. "Find the text 'Add expense' in this project — file and line only." A match, not an opinion.
Ask Codex to explain, then verify: make it show the line it names, and read it.
ONBOARDING.md — in your folder.1 · what the app does · 2 · which file runs first · 3 · where the data lives · 4 · which function a button runs · 5 · a function used twice · 6 · what happens with bad input.
7 · ask the AI what happens when you do X, then do X · 8 · make it explain a function, catch what it glossed over · 9 · bug #1: reproduce, find the line, fix it · 10 · three questions for the developer who left.
Answer inside the file. Every answer says where you checked: a file and line, or what you clicked.
| 1 | Follow the click. Search app.py for "Add expense". It's inside show_expenses. The line under the button calls logic.add_expense(...). |
| 2 | Follow the call. Open logic.py, find def add_expense. It builds a row and calls db.append_row("expenses", ...). |
| 3 | Stop at the database. db.py, append_row: opens data/expenses.csv and writes one line. Done. |
| 4 | Now ask the AI the same question. Did it name the same three functions? |
A good answer: "show_expenses (app.py, line 81) → logic.add_expense (logic.py, line 54) → db.append_row (db.py, line 42). Verified by reading the three lines."
| Q2 | Which file runs first? Weak: "app.py". Good: "app.py — it's what uv run streamlit run app.py starts, and the last line of the file calls main(), which picks the screen." |
| Q5 | A function used in more than one place. Weak: "get_group_members, it's reused". Good: "called at app.py 35, 46, 70 and logic.py 87, 105. Fix it once, it's right everywhere." |
| Q6 | Bad input. Weak: "it gives an error". Good: "I added an expense of 0 and one of −20: both saved, no message. add_expense in logic.py has no check — compare with is_valid_name, which members do have." |
| Q7 | "What happens to the balances when I delete a member who paid?" Paste the AI's answer. Then remove João from Jantar de Curso and write what actually happened. Was the AI right? |
| Q8 | "Explain compute_balances." Compare the comment inside the function with what the code does. Where did the AI just repeat the comment? |
| Q9 | Bug #1, the 001 file in issues/. See the wrong number on screen. Find the line, fix it, see the right number. Show the TA before and after. |
logic.py line 39, or "clicked Add expense with amount 0".Broke the data? uv run python seed.py puts it back.
| 1 | Read the error. The last line says what went wrong; the line above it says where. |
| 2 | Paste it to the AI and ask it to explain before it fixes anything. |
| 3 | Ask the group next to you. |
| 4 | Ask the TA, with the error on screen. |
ONBOARDING.md.specs/feature-1. That's what we build in Class 3.