Add and connect pages
Goal
You want your app to have more than one page, with ways to move between them.
Before you start
You can build a one-page app with a button. When you finish this page, your app will have several pages that link to each other, share a common header, and always offer a way back.
The smallest version
To add a page, add a route: a function marked with @route that
returns a Page. Connect pages with Button (an action to click) or
Link (an ordinary text link). Both name their target route as a
string:
from drafter import *
@route
def index() -> Page:
return Page([
"Welcome to the arcade.\n",
Button("Play a game", "game"),
Link("Read the rules", "rules")
])
@route
def game() -> Page:
return Page([
"The game happens here.\n",
Button("Back to the front", "index")
])
@route
def rules() -> Page:
return Page([
"Rule 1: have fun.\n",
Link("Back to the front", "index")
])
start_server()
Which one should you use? A Button looks like an action, so it works
best for doing things ("Play", "Submit", "Feed"). A Link looks like
ordinary text, so it works best for going places ("Read the rules",
"About"). Either one can point to any route.
Recipe: a shared header on every page
When several pages repeat the same top content, write a helper function that returns the shared components, and start each page's list with it. Adding the helper's list to the page's own list combines them into one content list:
from drafter import *
def header(title: str) -> list:
return [
Header(title),
Link("Home", "index"),
" | ",
Link("About", "about"),
"\n"
]
@route
def index() -> Page:
return Page(header("My Arcade") + [
"Pick a destination above."
])
@route
def about() -> Page:
return Page(header("About") + [
"Built with Drafter."
])
start_server()
When you change the header helper, every page that uses it changes with it. This is the same helper-function habit from the virtual pet's mood, applied to content.
Recipe: always offer a way back
Every page a visitor can reach should have a button or link leading
somewhere, usually back to index. A page with no way out forces the
visitor to use the browser's back button, which works but feels like a
dead end. Try walking through your own app: starting from index, can
you reach every page and return without touching the browser controls?
Common problems
- A "points to non-existent page" error: a button or link names a
route that does not exist. Check the spelling against the function
name, and make sure the function has
@route. - You wrote a route but cannot see it: nothing links to it yet. A route becomes reachable when some page names it, or when you visit its address directly.
- Two functions with the same name: Python silently keeps only the second definition. Every route needs its own name.
- Your pages have state but the new one errors: if your app has a
State, every route that page connects to should takestateas its first parameter and pass it along inPage(state, [...]).
Understand it
Routes and pages explains what a route is, how names become addresses, and how Drafter verifies connections.
See another example
Three linked pages shows a minimal ring of pages you can walk around in a circle.
Look it up
route, Page, Button, and Link.