The big ideas
In one sentence
Nine ideas carry all of Drafter; teach them in this order and everything else is detail.
The idea
Each idea below names the concept, the canonical student page for it, and what to emphasize. The guided projects introduce them in roughly this order, always behavior first, vocabulary second.
- A route is a function that returns a page. (Routes and pages) The single most load-bearing idea, and the most commonly garbled. A route is not a page; it is a function that builds and returns one, the way a recipe is not a cake. Students who hold this distinction can reason about parameterized and conditional pages; students who lose it treat routes as static documents.
- Buttons and links name the route to call.
(Button) A
Button("Feed", "feed")connects to the route by its name as a string. Clicking means calling that function. - State is one dataclass, threaded through every route. (State) Routes receive the state, may change its fields, and pass it into the returned page. This is the course's mutation-and-aliasing story in a context where it visibly matters.
- Form fields become parameters, matched by name.
(Forms and input) A
TextBox("color")submits its value to a parameter namedcolor. The name contract is where most early form bugs live. - Type annotations drive conversion. Form values arrive as
text unless the parameter's annotation says otherwise;
guesses: intis a meaningful, load-bearing annotation, not decoration. - Pages can differ because state differs. (Dynamic pages) Conditionals and loops inside routes, helper functions that return components, one route serving many items.
- Routes are testable functions. (Test a feature) Build a state, call the route, assert. Worth modeling constantly in lecture, not saving for a testing week.
- The program runs twice, and there is no server. (How Drafter works) Once on the student's computer (startup and tests), once in the browser where the real app lives. State is in memory and lost on reload; nothing is secret or secure.
- Deployment is compilation. (Deploy and submit) The app becomes static files; GitHub Pages serves them. No server to administer, and also no server to store anything on.
See it
Ideas 1 through 7 fit in one small program, which makes it a good running lecture example:
from drafter import *
from dataclasses import dataclass
@dataclass
class State:
treats: int
@route
def index(state: State) -> Page:
return Page(state, [
Header("Captain's Treat Counter"),
"Treats given: " + str(state.treats) + "\n",
TextBox("amount", "1"),
"\n",
Button("Give treats", "give")
])
@route
def give(state: State, amount: int) -> Page:
state.treats = state.treats + amount
return index(state)
assert_state(give(State(0), 3), State(3))
start_server(State(0))
One route builds the page from state (ideas 1, 3), the button
names the give route (2), the text box's name matches the
amount parameter (4), the int annotation converts it (5), the
page text varies with state (6), and the assertion tests the route
by calling it (7).
What this means for your code examples
- Say "the route that builds the page", never "the page's code". Small phrasing choices either reinforce idea 1 or erode it.
- Thread state visibly: examples where a change on one page shows up on another page make idea 3 concrete faster than any diagram.
- Put one assertion in every example you show, from the first week you use Drafter.
- Keep examples inside the known-constructs set (functions, dataclasses, lists, loops); the student docs never assume more.
Where people get confused
Every idea above has a matching failure mode in Student misconceptions, with symptoms and repair moves. The two most consequential: believing the app runs on a remote server (idea 8), and believing the browser's back button undoes the last action rather than replaying a route.
Go deeper
- Concepts index: the student-facing concept ladder these map onto.
- Beyond the student docs: what to teach students who outrun the spine.