PYTH-290 · Lesson 1 of 12 · 25 min
Choosing the project and users
▶ Video coming soon A video version of this lesson is on the way.
Every course in this program has added one piece to the software that runs Ridgeline Coffee Roasters. In PYTH-101 Jordan Reyes wrote a menu-driven stock and sales tool. PYTH-102 turned it into a package with modules and classes, PYTH-110 put it under version control, PYTH-215 moved the data into SQLite, PYTH-220 built a web shop, PYTH-230 added tests, PYTH-240 connected outside services, PYTH-250 made the reports fast and PYTH-270 redesigned the order code around a service layer. Each piece works. Together they are a pile of scripts, two databases, a web shop and a folder of reports that only Jordan fully understands.
This capstone course is different from the others. Instead of learning one new technique, you will plan, build, test, secure, deploy, document and present one complete application as part of a small team, the way professional developers do. The lessons follow the life of a real project from the first conversation with the people who will use it to the demo and the retrospective at the end. Each lesson still teaches, with runnable examples and graded exercises, but the exercises now build pieces of one application that grows through the course.
The team is small. Jordan leads it. Sam Okoye, the co-op student who joined in PYTH-110, is back for his final term. Nia Brooks, a second-year student from the same college program, joins for the capstone term on a work placement. Lena Park, the design coach from PYTH-270, spends one day a week reviewing their work. You can think of yourself as the fourth member of the team: every exercise is a task Jordan would hand to a new developer.
What a capstone project is for
A capstone project proves that you can do the whole job, not just the parts. Employers who read a junior developer's resume see a list of courses and a list of skills. What they want to know is whether the person can take a vague request, turn it into something useful, finish it, and explain it. A well-run capstone answers that question better than any grade, because it leaves behind working code, a written record of decisions and a story you can tell in an interview.
That means a capstone has three products, and you should plan for all three from the first day:
- Working software that real users can try, small enough to finish but complete enough to be useful.
- A record of the work: requirements, decisions, plans, tests, reviews and documentation, kept in the repository where anyone can read them.
- A presentation: a short demo and a retrospective that show what was built, why, and what the team learned.
Most failed student projects fail on scope, not on skill. The team picks something too large, spends weeks on infrastructure, and arrives at demo day with half-finished features that cannot be shown. The habits in this lesson, choosing deliberately, naming real users and agreeing what is out of scope, are the main defense against that.
Gathering candidate projects
Jordan did not start by deciding what to build. He started by listening. On the first Monday of the term the team spent an hour with each person at Ridgeline, asking the same three questions: what takes you too long, what goes wrong, and what would you do if you had more time? Sam typed notes into a shared document while Nia drew rough sketches of anything that sounded like a screen.
The conversations produced eleven ideas. Some were small (Mei wanted the cafe menu board to show which coffees were out of stock), some were large (Rosa dreamed of an app for wholesale customers), and some were really several ideas at once. Kai's request, a better roast log, turned out to mean three things: recording roasts faster, seeing trends over weeks, and warning when a green coffee lot was running low.
Good discovery interviews have a few habits worth copying. Ask about the last time something went wrong rather than about opinions, because stories reveal the real workflow. Watch people do the task if you can: Theo's description of packing orders left out the ten minutes he spent copying addresses from the shop into the courier's website. Write down the person's words, not your solution. And always ask who else is affected, because the person asking for a feature is not always the person who will use it.
Five of the ideas kept coming up in different words from different people. Jordan wrote them on the whiteboard:
Scoring the ideas
With five reasonable ideas and five weeks, the team needed a fair way to choose. Arguing until the loudest person wins is common and produces bad projects. A simple weighted scoring matrix is better: agree on a few criteria, agree how much each one matters, score every idea against every criterion, and multiply. The numbers do not make the decision for you, but they make the reasoning visible and expose disagreements early.
The team chose four criteria. Value is how much the project helps the business and its users. Feasibility is how likely the team is to finish a useful version in the time available with the skills it has. Learning is how much the project exercises the skills the capstone is meant to show. Risk is how much could go wrong, such as unclear requirements, outside services or sensitive data, scored so that a higher number means less risk. They weighted value most heavily, because a capstone that nobody uses teaches less than one that people rely on.
WEIGHTS = {"value": 0.4, "feasibility": 0.3, "learning": 0.2, "low_risk": 0.1}
IDEAS = {
"Coffee subscriptions": {"value": 5, "feasibility": 4, "learning": 5, "low_risk": 3},
"Wholesale ordering portal": {"value": 5, "feasibility": 2, "learning": 4, "low_risk": 2},
"Roast log and lot tracking": {"value": 4, "feasibility": 4, "learning": 3, "low_risk": 4},
"Unified daily report": {"value": 4, "feasibility": 4, "learning": 3, "low_risk": 4},
"Menu board stock display": {"value": 2, "feasibility": 5, "learning": 2, "low_risk": 5},
}
def weighted(scores):
return round(sum(WEIGHTS[k] * scores[k] for k in WEIGHTS), 2)
ranked = sorted(IDEAS, key=lambda name: weighted(IDEAS[name]), reverse=True)
for name in ranked:
print(f"{weighted(IDEAS[name]):4.2f} {name}")4.50 Coffee subscriptions 3.80 Roast log and lot tracking 3.80 Unified daily report 3.60 Wholesale ordering portal 3.20 Menu board stock display
Coffee subscriptions came out on top, but not by much, and the team looked closely at why. The wholesale portal had the same value but much lower feasibility: it needed accounts for outside businesses, invoices and credit terms, and Rosa admitted she was not sure what the cafes wanted. The roast log and the daily report scored the same as each other and only a little below subscriptions.
Lena pointed out something the matrix could not show: the top three ideas overlap. A subscription system needs to know what is in stock, which depends on what has been roasted, and its sales must appear in Anita's daily report. Rather than choose one, the team defined the project as Ridgeline Ops: a single application built around subscriptions, with just enough of the roast log and the daily report to make subscriptions work end to end. The wholesale portal and the menu board went on a list called Later.
Try it yourself
Rank the project ideas
Write weighted(scores, weights) that returns the sum of each criterion score times its weight, rounded to 2 decimal places, and rank(ideas, weights) that returns the idea names sorted from highest to lowest weighted score.
When two ideas have the same weighted score, put them in alphabetical order so the ranking is always the same. ideas maps each name to a dictionary of scores, and every criterion in weights appears in every scores dictionary.
def weighted(scores, weights):
return sum(scores.values())
def rank(ideas, weights):
return list(ideas)
WEIGHTS = {"value": 0.4, "feasibility": 0.3, "learning": 0.2, "low_risk": 0.1}
IDEAS = {
"Roast log": {"value": 4, "feasibility": 4, "learning": 3, "low_risk": 4},
"Daily report": {"value": 4, "feasibility": 4, "learning": 3, "low_risk": 4},
"Subscriptions": {"value": 5, "feasibility": 4, "learning": 5, "low_risk": 3},
}
print(rank(IDEAS, WEIGHTS))Naming the users
Once the project is chosen, the most important question is who will use it. It is tempting to say everyone, or the business, or customers. Those answers are too vague to design for. A user is a specific kind of person with a specific job to get done, and different users of the same system often want contradictory things.
Ridgeline Ops has six kinds of users. Subscribers are customers who sign up for regular deliveries and want to pause, skip or change their coffee without phoning the shop. Theo, the operations manager, needs to know every morning which subscription orders to pack and ship. Kai needs to know how much of each coffee to roast this week to cover subscriptions and normal sales. Anita, the bookkeeper, needs subscription revenue to appear in her daily totals with tax handled correctly. Rosa, the owner, wants to see how many subscribers there are, how many cancel, and what they are worth. Mei, the cafe lead, needs to sign up regulars at the till.
Some teams write personas: short invented profiles that give each kind of user a name, a goal, a frustration and a typical day. Personas are useful when the real users are strangers. At Ridgeline the team can walk into the roastery and ask Theo directly, so they wrote one persona, for subscribers, and used the real staff for the rest. The subscriber persona was based on three regular customers Mei knew well:
- Name and situation: Priya, a nurse who works rotating twelve-hour shifts and buys a bag of Ethiopia Guji every two weeks.
- Goal: never run out of coffee, and never have a bag arrive while she is on night shifts and cannot answer the door.
- Frustration: she forgets to reorder, then buys supermarket coffee she does not like.
- What success looks like: she can skip a delivery from her phone in under a minute.
The persona describes a need, not a feature. It does not say Priya wants a pause button. It says she wants deliveries to fit her schedule, which might be met by pausing, skipping, changing the delivery day or choosing pickup at the cafe. Keeping needs separate from solutions leaves room to find the simplest one.
Try it yourself
Group requests by user
The interview notes are a list of (user, request) pairs. Write by_user(notes) that returns a dictionary mapping each user to the list of their requests, in the order they were noted, with the users ordered by how many requests they made (most first) and ties broken alphabetically by user name.
Ignore a request that the same user already made, so duplicates in the notes do not inflate the counts.
def by_user(notes):
result = {}
for user, request in notes:
result[user] = [request]
return result
NOTES = [
("Theo", "print packing list"), ("Kai", "log roasts faster"),
("Theo", "courier labels"), ("Anita", "one daily total"),
("Kai", "warn when green coffee is low"), ("Theo", "print packing list"),
("Kai", "weekly roast plan"),
]
print(by_user(NOTES))Agreeing the scope
The last step in choosing a project is writing down what it is and what it is not. The team wrote a one-page project charter and asked Rosa to read it and say yes before any code was written. A charter that fits on one page gets read; a ten-page document gets filed. Ridgeline's charter had six short sections:
- Problem: regular customers forget to reorder, staff retype orders, and nobody can see subscription revenue.
- Goal: by 18 December, customers can subscribe to a coffee every two or four weeks, staff can see and pack each day's subscription orders, and subscription sales appear in the daily report.
- Users: subscribers, operations, roasting, bookkeeping, the owner and the cafe.
- In scope: subscriptions, renewal orders, a stock check against the roast plan, a daily report and a simple web API with a staff page.
- Out of scope for this term: online card payments (staff will charge subscribers through the existing shop until a payment provider is chosen), the wholesale portal, the menu board and a mobile app.
- Success measures: at least ten real subscribers in the first month, Theo packs subscription orders from the system instead of from email, and Anita's daily report needs no manual corrections.
The out-of-scope list is the most valuable part. Every project attracts good ideas that would take it past its deadline. When Rosa later asked whether the subscription page could also take wholesale orders, Jordan could point to the charter: a good idea, already on the Later list, and not part of this term. Agreeing scope early turns a hard conversation into a quick one.
The success measures matter too. They are concrete and they describe outcomes for users, not output from the team. Ten subscribers, packing from the system and a report without corrections are things anyone can check on 18 December. A measure like write a subscription module describes work, not results; it can be finished while the business gains nothing.
Choosing a project for your own portfolio
If you are doing a capstone of your own, the same process applies even if there is no Rosa to interview. Choose a real problem for a real person: a club that tracks members in a spreadsheet, a relative's small business, a volunteer group, a tool for your own studies or hobby. A project with a real user teaches you to handle changing requirements and gives you a better story than an invented one. Score your candidate ideas, name the users, and write a one-page charter with an honest out-of-scope list.
Avoid three common traps. Do not clone a famous product, such as a social network or a ride-sharing app, because the scope is enormous and the result invites unflattering comparison. Do not choose a project whose main difficulty is outside your control, such as one that depends on a paid service you cannot access. And do not choose a project so small that it shows nothing new; a to-do list app is fine for learning a framework but weak as a capstone.
Common mistakes
MistakeStarting to code on the first day because the idea seems obvious.
InsteadSpend the first days on discovery: interview users, watch them work and write down their words before choosing.
MistakeChoosing the most exciting idea without comparing it to the others.
InsteadScore every candidate against agreed, weighted criteria so the reasoning is visible and disagreements surface early.
MistakeDescribing users as everyone or the business.
InsteadName each kind of user and the specific job they need to get done; different users want different things.
MistakeWriting a persona that lists the features the persona wants.
InsteadDescribe goals and frustrations; leave room for the simplest solution to emerge later.
MistakeLeaving scope open so the project can grow with new ideas.
InsteadWrite an explicit out-of-scope list and get the project sponsor to agree to it in writing.
MistakeSetting success measures that describe the team's work, such as finish the module.
InsteadMeasure outcomes for users, such as ten subscribers or a report that needs no corrections.
Summary and key terms
- A capstone proves you can do the whole job: working software, a record of the work and a presentation.
- Most student projects fail on scope rather than skill, so choosing deliberately matters.
- Discovery interviews ask about real recent events, watch people work and record their words, not your solutions.
- A weighted scoring matrix makes the choice between candidate projects visible and fair.
- Overlapping ideas can sometimes be combined into one project with a clear center.
- Name each kind of user and their job; use personas when the real users are not available.
- A one-page charter states the problem, goal, users, scope, out-of-scope items and success measures.
- Success measures describe outcomes for users that anyone can check on the deadline.
- capstone project
- A final project that brings together the skills of a whole program in one piece of real work.
- discovery
- The early phase of a project spent understanding users, their problems and their workflow.
- stakeholder
- Anyone who is affected by the project or can influence it.
- weighted scoring matrix
- A table that scores options against criteria, each multiplied by an agreed weight.
- persona
- A short invented profile of a typical user, with goals and frustrations, based on research.
- project charter
- A short document stating a project's problem, goal, users, scope and success measures.
- scope
- The agreed set of features and work a project will deliver.
- scope creep
- The gradual growth of a project as new requests are added without changing time or resources.
- success measure
- A concrete, checkable outcome that shows whether the project achieved its goal.
Practice problems
Work each problem on paper first, then reveal the answer to check.
Why do discovery interviews ask about the last time something went wrong instead of asking for opinions?
Show answer
Stories about real events reveal the actual workflow and its problems, while opinions tend to describe how people think things should work.
An idea scores 5 for value, 2 for feasibility, 4 for learning and 2 for low risk. With weights 0.4, 0.3, 0.2 and 0.1, what is its weighted score?
Show answer
0.4 x 5 + 0.3 x 2 + 0.2 x 4 + 0.1 x 2 = 2.0 + 0.6 + 0.8 + 0.2 = 3.6.
Rewrite the success measure "build the subscription module" as an outcome.
Show answer
For example: at least ten customers have active subscriptions by the end of the first month.
Why does a persona describe goals rather than features?
Show answer
So the team can find the simplest way to meet the goal instead of committing early to one feature.
What is the purpose of the out-of-scope list in a charter?
Show answer
It records what the project will not do, so new requests can be deferred quickly and the deadline protected.
Name two traps to avoid when choosing a portfolio capstone.
Show answer
Cloning a famous product, depending on something outside your control, or choosing a project too small to show anything new.
Lesson quiz · 5 questions
Score 60% or more to complete this lesson.
Create a free account to save your progress, take quizzes and earn a certificate.