Personal Website - Home
You have learned Flask, templates, Bootstrap, PookieDB, and fetch. Now you are going to put those skills together and build a real three-page personal website.
The three pages are: Home, About, and Contact. Each one is a separate page with its own URL. They all share the same navigation links at the top.
The problem with copying
If you made a separate HTML file for each page, you would have to paste the navigation into every single one. Change the nav later and you have to update all three files. That gets messy fast.
There is a better way.
base.html - write it once, use it everywhere
Flask templates support something called template inheritance. The idea is simple: you write one shared template called base.html that holds everything every page has in common - the navigation, the <head>, the basic structure. Then each page just says "start with base.html, and here is my content."
You write the nav once. All pages share it automatically.
Two new Jinja tags make this work:
In base.html:
{% block content %}{% endblock %}
This is a placeholder. It says: "whatever page extends me, put its content here."
In each page template:
{% extends "base.html" %}
{% block content %}
... this page's content goes here ...
{% endblock %}
{% extends "base.html" %} tells Flask: start with base.html, then fill in the block with what is below.
That is the whole idea. One file holds the shared structure. Each page fills in its own section.
The project structure
my-website/
app.py
templates/
base.html
home.html
about.html
contact.html
base.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My Website</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav>
<a href="/">Home</a> |
<a href="/about">About</a> |
<a href="/contact">Contact</a>
</nav>
<div class="container mt-4">
{% block content %}{% endblock %}
</div>
</body>
</html>
The nav is just plain anchor tags with a | separator. Simple. The container and mt-4 you already know - they centre the content and add a bit of space at the top.
app.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/about')
def about():
return render_template('about.html')
@app.route('/contact')
def contact():
return render_template('contact.html')
if __name__ == '__main__':
app.run(debug=True)
Three routes, three templates. Nothing new here - you have written routes like this before.
home.html
{% extends "base.html" %}
{% block content %}
<h1>Hi, I'm Grace</h1>
<p>Welcome to my personal website. I am learning to build things for the web.</p>
{% endblock %}
That is it. Flask takes base.html, finds the {% block content %} placeholder, drops in what is between {% block content %} and {% endblock %} in home.html, and sends the finished page to the browser.
Challenge
Replace the name and paragraph with your own. Run the app and visit /, /about, and /contact in your browser. All three should load - about and contact will be blank for now. That is fine. You will fill them in on the next pages.