No wrong answers. This helps us calibrate pairing and pacing.
Have you used git before? Branches? Pull requests?
Comfortable with Python? Ever built or worked on a web app?
Used ChatGPT, Copilot, Claude? For coding specifically?
Ever worked on code someone else wrote? Reviewed a PR?
Raise your hand for each: never used it / used it a little / use it regularly
A map of Brown County, WI (Green Bay area). Each colored dot is a household. Each shape is a store. Colors show food access scores.
Open the URL on your laptop. Click a household to see its data. Click "Step" to run one simulation tick. Watch the colors change.
By the end of today's setup, you'll have this same app running on your machine, connected to your own database.
Food access is the ability of a household to regularly obtain adequate, affordable, nutritious food. Four factors determine whether they can.
Supermarkets and convenience stores count very differently — proximity to the right kind of store is what matters.
A vehicle, a bus route, or just walking distance — each one expands or restricts the set of reachable stores.
Lower-income households make fewer trips, and tend to use the closest store regardless of what it stocks.
A supermarket with fresh produce isn't the same as a convenience store with packaged food. Quality drives the score.
Low food access correlates with poor diet, higher rates of obesity and diabetes, and other health outcomes.
It disproportionately affects low-income communities and communities of color. Better tools for measuring access make it easier for cities, public health researchers, and community organizations to do their work.
Tax break, zoning change, public-private partnership — what's the modeled lift in access scores?
A chain pulls out of a low-income area. Which households are most affected, and where should a replacement go?
A bus route connecting one neighborhood to a distant supermarket — does it close the access gap for carless households?
A seasonal store, smaller footprint, different shopping patterns — what's the modeled effect on its surroundings?
Evaluating proposed grocery store locations or transit improvements.
Studying the link between food access and health outcomes across demographics.
Modeling the impact of store closures and policy interventions.
Advocating for food access improvements with data-driven arguments.
Learning about spatial modeling, food systems, and agent-based simulation.
Instead of one big equation describing food access for a whole city, we create thousands of household agents that each independently figure out where to shop. Four properties define an ABM:
Each household has its own income, location, vehicles, workers — captures real-world diversity instead of an average.
No agent has a global view. Global patterns emerge from many local decisions made independently.
Every step, each agent re-evaluates its situation. You can model change over six months, a year, a decade.
Add or remove a store, re-run from the same state, compare outcomes. The whole point of the technique.
Income, household size, vehicles, number of workers, geographic location inside a census tract. Pulled from the US Census API.
A food store — supermarket, convenience, grocery, butcher. Each has a type, name, and location. Pulled from OSM via the Overpass API.
From Koh et al., 2019. The arithmetic is intentionally simple — most of the interesting behavior is upstream, in which store the household actually picks.
Fresh produce, broad selection, full grocery — high food availability.
Smaller footprint, more packaged food — limited food availability.
Minimal selection, emergency use. Low-income households may prioritize these. bc_pantries branch only.
Varies by resources: 7 with car & income, 8 without car, 6 with low income.
You don't need deep Mesa knowledge to contribute. The key idea: when GeoModel.step() runs, it calls Household.step() on every household — that's where all the food access math happens.
FEAST extends this as GeoModel.
Household and Store both extend Mesa's GeoAgent.
From mesa-geo. Distance calculations between agents on a map.
Calls step() on every agent in random order each tick.
High access score. Reaching supermarkets often.
Mid-range. Mixed trips, partial supermarket access.
Low access. Mostly convenience stops; few supermarket trips.
Click to inspect. Drag in new ones to test what-if.
FEAST originated through the NSF-funded ICICLE AI Institute (OAC 2112606).
The current implementation is focused on Brown County, Wisconsin as a proof of concept. The goal is to make it work for any US county — that generalization is one of the larger arcs in the backlog you'll be working from.
When you're debugging, ask first: which layer? Map not rendering — frontend. Score wrong — backend. Data missing — database. That single question cuts debugging time in half.
Name, ID, timestamps. The "outer container" for everything else.
Location, income, household_size, vehicles, workers, transit/walk/bike/drive times, food_score, stores_within_1_mile, closest_store_miles.
store_id, name, shop type, geometry (WKT), simulation_instance, simulation_step.
Household coordinates are stored in EPSG:4326 (lat/lon). Store geometries are in EPSG:3857 (Web Mercator, meters). This inconsistency means different coordinate handling per table, and the frontend uses proj4 to reproject stores for display. On the backlog as #67.
That whole loop, end to end, is the product. Student D will trace this in detail. Every PR you write touches some piece of it.
What the project is, how to work in it, what conventions to follow. Read by humans and AI agents.
A living document. Milestones, dependencies, critical path. Updated after each milestone, not written once and forgotten.
Architecture Decision Records. Document the reasoning, not just the result. You'll start writing these in Week 2.
This curriculum repo (FEAST_edu) uses all three. We practice what we teach.
You understand the system. Now: agentic coding tools, the rules for working with them, getting the app running, and your first assignments.
The agent handles syntax. You handle engineering. This curriculum teaches the right column.
Run in your terminal, read the whole codebase, execute commands. Conversational interface.
Full editors with AI in every interaction. Code completion, inline chat, multi-file editing.
Plugins for VS Code, JetBrains. Autocomplete and inline suggestions. Lightest-weight.
We recommend a CLI agent because its conversational interface matches how we want you to work: asking questions, not accepting autocomplete. Claude Code is our first choice if access is available; Gemini CLI is a free alternative. Both use project context files that double as documentation.
Demo: same question, with and without a context file
A freshman who learns to generate code in week 1 will never learn to read code. We build the muscle of reading and thinking first. Generation comes later, when you can spot when the tool is wrong.
Skips learning. You ship code you don't understand. Review fails.
Accelerates learning. You understand what you ship. Review passes.
Use the tool to push toward clarity. Simpler code is almost always better code.
We unlock more capability week by week. By week 6 you'll have full access. The restriction is the point: you're building the skill of reading code first. The tool will still be there when you're ready.
Git tracks every change to every file. You can always go back. When multiple people work on the same project, git keeps everyone's changes organized.
Your project folder, tracked by git. Contains every file and the full history of changes. You have a local copy; GitHub holds the remote copy.
A snapshot of your files at a moment in time. Each commit has a message describing what changed. Like a save point you can return to.
A named line of development. FEAST uses main (stable), dev (integration), and feature branches (your work). You work on your branch without affecting anyone else.
Download a repo from GitHub to your machine.
Once, during setup.
Switch to a different branch.
When moving between branches.
Stage your changes, then save a snapshot with a message.
After you make changes.
Upload your commits to GitHub so the team can see them.
After committing.
Your "where am I?" command. Shows branch, changed files, staged files.
Constantly. When in doubt, git status.
3.11 or later.
Node 18 or later.
Local instance, or shared.
SSH key set up, repo access granted.
Python package manager.
Claude Code (preferred), Gemini CLI (free), or Copilot as baseline.
Senior students: if you solve something non-obvious during setup, write it down. Those notes become part of CONTRIBUTING.md in a couple of weeks.
curl localhost:8000/api/simulation-instances returns a JSON list. Health: /api/health
Map loads at localhost:5173 centered on Brown County (Green Bay area).
Click a household — popup with income, vehicles, score. Click Step — colors change. Add a store — Step again — nearby scores improve.
Is PostgreSQL running? Are your .env credentials correct? Is backend on port 8000 (run_local.py)? Make sure client.js matches.
You may need to run the preprocessing pipeline or restore a database dump. Use insert_stores.py with a CSV for stores.
food_access_model/main.py allows localhost:5173. If you used api_server.py by accident, it only allows a Tapis staging URL.
Make sure you're on minimum_viable_product (backend) and Brown-County-Frontend (frontend). The main branch has different code.
Understanding what the tool does is a prerequisite to understanding how it works. Don't skip this.
| Student | Endpoint | What to focus on |
|---|---|---|
| Student AJ | GET /simulation-instances | Simplest endpoint. How does a request become a SQL query become a JSON response? |
| Student BJ | GET /households | How is household data structured? What do the column names mean? |
| Student CJ/S | POST /stores | How does a lat/lon become a polygon? What's the coordinate transform doing? |
| Student DS | POST /sim-instances/{id}/advance | The core simulation loop. How does one "Step" actually work end to end? |
| Student ES | POST /simulation-instances | What happens when you create a new simulation? Where does the data come from? |
Reviewed by a peer before the Week 2 session. Write for future you.
Match what you see in the browser to what's in the code.
Especially get_mfai(), has_resources(), step().
Use the LLM to explain things you don't understand — but verify against the actual code. The LLM can be confidently wrong.
Use the template in FEAST_edu/templates/CLAUDE.md as a starting point. Name it for your tool: CLAUDE.md, GEMINI.md, or .cursorrules. Customize it based on what you learned from the architecture overview and your endpoint trace.
Keep it under 50 lines. You'll update it as you learn more. This is your first project management artifact.
Open a PR for it alongside your endpoint trace.
Not a redesign from scratch. The same app, built the way a professional team would build it today. Then work backwards: what are the biggest gaps, and in what order should a team close them?
templates/vision-plan-template.md
This is not busywork. This is how the team builds a real backlog. By week 3 you'll be triaging it. By week 5 you'll be shaping it.
Package-relative in one file, shorthand in another.
Tapis URL, not relevant locally. Should be env-driven.
pyproject.toml says 3.11.11. Dockerfile says 3.12.
Imported in api_server.py but the module doesn't exist.
Multiple files. Should use the standard logging module.
95, 55, 0.8, income thresholds. No constants, no docstring.
FastAPI moved to lifespan handlers. routes.py still uses startup events.
Bypasses React, hard to debug, fights re-render cycle.
Two CSS frameworks. Pick one. (Probably Tailwind.)
Found something fixable in 30 minutes — the CORS hardcoding, a print-to-logging conversion?
Open a PR. Link it to the issue. That's your first taste of the full cycle.
If a J student is struggling to spot issues, sit with them over chat or a call.
Point things out. The junior files the issue — they need the practice. You help them see what to look for.
That's a lot. We get there one week at a time. The foundation is what we build today.
Bring laptops to the front so we can debug together. Anything that's confusing now will come up later — better to ask now.