Black Swan Bistro — Part 1
Build Your First Web Page
How this fits the full project: In Part 1, you are building the homepage foundation for Black Swan Bistro. Later parts turn this into a more complete multi-page site with a menu page, about page, contact page, reusable components, and layout systems guided by the project brief.
🍽️ From Blank Screen to Restaurant Website
You walk into a brand-new restaurant. There’s no sign outside, no menu on the table, no information about opening hours. It doesn’t matter how good the food is — nobody will stick around long enough to find out.
A website works the same way. You need a clear homepage that tells visitors who you are, what you offer, and how to find you. In this project you’ll build exactly that — the homepage foundation for Black Swan Bistro, a fictional Perth restaurant — from an empty folder to a styled, working web page.
- Think of a restaurant website you’ve visited. What info did you look for first?
- What makes a homepage feel trustworthy vs. unfinished?
- Have you ever left a website because it was hard to read or looked broken?
Over the next 60 minutes you’ll set up a project folder, write semantic HTML, link a stylesheet, and see your page come alive in the browser. This is Part 1 of a 7-part series that will take you from first page to fully deployed site.
Learning Objectives
By the end of this lesson, you'll be able to:
- ✓ Set up a project folder with proper file and folder structure
- ✓ Write a semantically correct HTML homepage from scratch
- ✓ Use headings, paragraphs, lists, links, images, and a table in context
- ✓ Create Create a linked CSS stylesheet with colour variables, typography, and layout
- ✓ Preview and debug your page in a browser
Why This Matters:
Most tutorials teach HTML and CSS as separate topics. Real projects need both working together. By building a complete page from start to finish, you’ll see how everything connects — and you’ll have a genuine project to show for it.
Step 1 — Set Up Your Project
Every professional web project starts the same way: an organised folder with files in predictable locations. Let’s create ours.
Where Should Your Project Live?
Before you create anything, decide where on your computer your web projects will live. Pick one location and stick with it — consistency will save you time later.
| Operating System | Recommended Location |
|---|---|
| macOS | ~/Sites/ — This is the traditional web development folder on Mac. Open Finder and you’ll find it in your home directory. If it doesn’t exist, create it. |
| Windows | C:\Users\YourName\Projects\ — Create a Projects folder in your user directory. Avoid putting projects on the Desktop or in OneDrive — syncing services can interfere with development tools. |
| Linux | ~/projects/ or ~/Sites/ — Either works. Create whichever name you prefer in your home directory. |
Important: Avoid putting projects in cloud-synced folders (Dropbox, iCloud, OneDrive) or on external drives. Build tools like Vite can create thousands of tiny files in node_modules, which confuse sync services and slow everything down.
Create the Black Swan Bistro project
Navigate to your projects folder
Open your terminal and navigate to the folder where your web projects live:
# macOS
cd ~/Sites
# Windows (Command Prompt)
cd %USERPROFILE%\Projects
# Linux
cd ~/projectsIf the folder doesn’t exist yet, create it first:
# macOS
mkdir -p ~/Sites && cd ~/Sites
# Windows (Command Prompt)
mkdir %USERPROFILE%\Projects && cd %USERPROFILE%\Projects
# Linux
mkdir -p ~/projects && cd ~/projects💡 Need a hint?
Create the project folder
Now create the project folder and move into it:
mkdir black-swan-bistro
cd black-swan-bistroOr create a new folder called black-swan-bistro in Finder / File Explorer.
💡 Need a hint?
Create subfolders
Inside your project folder, create three subfolders:
mkdir css js imagesIn VS Code you can right-click in the Explorer panel → New Folder.
💡 Need a hint?
Create the core files
Create the starter files in their correct locations:
touch index.html css/style.css js/main.jsOr right-click the appropriate folder in VS Code → New File.
💡 Need a hint?
Open in VS Code
Open the project folder in VS Code:
code .Or launch VS Code and go to File → Open Folder…, then navigate to your black-swan-bistro folder (e.g. ~/Sites/black-swan-bistro on Mac).
You should see all three subfolders and your files in the Explorer sidebar on the left. If the sidebar isn’t visible, press Cmd+B (Mac) or Ctrl+B (Windows/Linux) to toggle it.
💡 Need a hint?
Your project structure should now look like this:
black-swan-bistro/
├── index.html
├── css/
│ └── style.css
├── js/
│ └── main.js
└── images/
└── (empty for now)⏸️ Pause & Check: Do You Understand?
Before moving forward, can you answer these?
- Why is the homepage called index.html and not home.html?
- What are the three standard subfolders and what goes in each?
- Why do we use lowercase names with hyphens (e.g., black-swan-bistro)?
Check Your Answers
- Web servers look for index.html by default. When someone visits your domain without specifying a filename, the server automatically serves index.html.
- css/ for stylesheets, js/ for JavaScript files, and images/ for pictures, icons, and graphics.
- URLs are case-sensitive on most servers. Spaces cause problems in URLs (they become %20). Hyphens are readable and safe across all operating systems and web servers.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Step 2 — Build the HTML
With the folder ready, it’s time to write the HTML. We’ll build the page section by section, using semantic elements — HTML tags that describe what the content is, not just how it looks.
The Boilerplate
Open index.html in VS Code and add the document shell. This is the foundation every HTML page needs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Black Swan Bistro | Casual Riverside Dining in Perth</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- We'll add content here -->
</body>
</html>Tip: In VS Code, type ! then press Tab to generate the boilerplate instantly (Emmet shortcut). Then add the <link> and <title> manually.
Header & Navigation
Inside the <body>, start with a <header> containing the restaurant name and a simple navigation. In Part 1 these links can point to sections on the homepage, but keep the labels aligned with the later multi-page project: Home, Menu, About, Contact.
<header>
<h1>Black Swan Bistro</h1>
<nav>
<ul>
<li><a href="#hero">Home</a></li>
<li><a href="#menu">Menu</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</header>Why these labels matter: The project brief and later tutorials use Home, Menu, About, and Contact as the shared site navigation. Keeping those labels now makes the jump from a single homepage to a multi-page site feel much more natural.
Why semantic elements? A <header> tells the browser (and screen readers) “this is the top section of the page.” A <nav> says “this is navigation.” Plain <div>s don’t communicate anything — they’re invisible to accessibility tools.
Hero Section
Below the header, add a hero section that welcomes visitors:
<section id="hero">
<h2>Casual Riverside Dining in Perth</h2>
<p>The Black Swan Bistro offers casual lunch and dinner fare
in a relaxed riverside atmosphere. The menu changes
seasonally to highlight the freshest Western Australian
ingredients.</p>
<a href="#menu">View Our Menu</a>
</section>About Section
<section id="about">
<h2>Our Story</h2>
<p>Founded in 2010 by Chef <strong>Maria Rodriguez</strong>,
Black Swan Bistro brings over 20 years of culinary
experience to Perth’s Elizabeth Quay. We blend
traditional Australian flavours with modern techniques,
showcasing the finest local produce.</p>
<p><em>Farm to table. Sustainability. Community.</em></p>
</section>Notice: We use <strong> for the chef’s name (important information) and <em> for the tagline (emphasis). These are semantic choices — they convey meaning, not just bold/italic styling.
Featured Menu
The full menu will come in Part 4, but a homepage should tease the highlights:
<section id="menu">
<h2>Featured Menu</h2>
<h3>Starters</h3>
<ul>
<li><strong>Sydney Rock Oysters</strong> — served with
lemon myrtle mignonette</li>
<li><strong>Kangaroo Carpaccio</strong> — with native
pepperberry & wattleseed crisps</li>
<li><strong>Pumpkin & Macadamia Soup</strong> —
roasted butternut with toasted macadamia</li>
</ul>
<h3>Mains</h3>
<ul>
<li><strong>Pan-Seared Barramundi</strong> — with
lemon butter, asparagus & crushed potatoes</li>
<li><strong>Grass-Fed Ribeye</strong> — 300g with
red wine jus & roasted vegetables</li>
<li><strong>Wild Mushroom Risotto</strong> —
arborio rice with truffle oil & parmesan</li>
</ul>
<h3>Desserts</h3>
<ul>
<li><strong>Chocolate Lava Cake</strong> — with
vanilla bean ice cream</li>
<li><strong>Pavlova</strong> — with seasonal
berries & passionfruit coulis</li>
</ul>
</section>⏸️ Pause & Check: Do You Understand?
Before moving forward, can you answer these?
- What is the difference between <section> and <div>?
- Why do we use <strong> for menu item names instead of <b>?
- What does the id attribute on a <section> do?
Check Your Answers
- A <section> is a semantic element — it tells browsers and screen readers "this is a distinct section of content." A <div> has no meaning; it's just a generic container. Use <section> when the content represents a thematic grouping.
- <strong> means "this content is important" — screen readers will emphasise it. <b> just makes text bold visually without conveying any meaning. Semantic HTML uses <strong> for importance.
- It gives the section a unique identifier. Navigation links can point to it using href="#id" to scroll the user directly to that section. Each id must be unique on the page.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Hours & Location
A table is the right element when you have rows and columns of related data — like opening hours:
<section id="hours">
<h2>Hours & Location</h2>
<table>
<thead>
<tr>
<th>Day</th>
<th>Hours</th>
</tr>
</thead>
<tbody>
<tr>
<td>Monday</td>
<td>Closed</td>
</tr>
<tr>
<td>Tuesday – Saturday</td>
<td>5:30 pm – 10:00 pm</td>
</tr>
<tr>
<td>Sunday Lunch</td>
<td>12:00 pm – 3:00 pm</td>
</tr>
</tbody>
</table>
<address>
123 Gourmet Lane, Elizabeth Quay<br>
Perth, WA 6000<br>
<a href="tel:+61893001234">(08) 9300 1234</a><br>
<a href="mailto:hello@blackswanbistro.com.au">
hello@blackswanbistro.com.au</a>
</address>
</section>Why <address>? The <address> element tells search engines and screen readers “this is contact information.” It’s a small semantic detail that improves accessibility and SEO.
Footer
<footer>
<p>© 2025 Black Swan Bistro. All rights reserved.</p>
<p>
<a href="#">Facebook</a> |
<a href="#">Instagram</a> |
<a href="#">TripAdvisor</a>
</p>
</footer>Save the file and open index.html in your browser. You should see all your content displayed in plain, unstyled HTML — readable, structured, and semantic. It won’t look pretty yet, but every element is in place.
Step 3 — Style with CSS
Now let’s transform that plain HTML into something that looks like a real restaurant website. Open css/style.css and we’ll build the stylesheet section by section.
Colour Variables & Base Styles
Start by defining the restaurant’s brand colours as CSS custom properties. This means you only need to change one value to update the colour everywhere it’s used:
/* ── Brand colours ─────────────────────────────── */
:root {
--bistro-burgundy: #7d1c20;
--bistro-gold: #d4af37;
--bistro-ink: #2a1c16;
--bistro-charcoal: #1c1c1c;
--bistro-cream: #f6f1eb;
--bistro-smoke: #ede7df;
}
/* ── Base reset & typography ──────────────────── */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Source Sans Pro', Arial, sans-serif;
color: var(--bistro-ink);
background-color: var(--bistro-cream);
line-height: 1.6;
}Why custom properties? If the client says “make the burgundy a bit darker,” you change one line and every heading, link, and border using var(--bistro-burgundy) updates automatically. This is how professionals manage colours.
Header & Navigation
/* ── Header ────────────────────────────────────── */
header {
background-color: var(--bistro-charcoal);
color: #f8f8f8;
padding: 1.5rem 2rem;
text-align: center;
}
header h1 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 2.4rem;
letter-spacing: 0.05em;
margin-bottom: 0.5rem;
}
/* ── Navigation ───────────────────────────────── */
nav ul {
list-style: none;
display: flex;
justify-content: center;
gap: 2rem;
}
nav a {
color: #f8f8f8;
text-decoration: none;
font-size: 1.1rem;
transition: color 0.3s ease;
}
nav a:hover {
color: var(--bistro-gold);
}Hero Section
/* ── Hero ──────────────────────────────────────── */
#hero {
background-color: var(--bistro-burgundy);
color: #fff;
text-align: center;
padding: 4rem 2rem;
}
#hero h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 2rem;
margin-bottom: 1rem;
}
#hero p {
max-width: 600px;
margin: 0 auto 1.5rem;
font-size: 1.1rem;
line-height: 1.8;
}
#hero a {
display: inline-block;
padding: 0.75rem 2rem;
background-color: var(--bistro-gold);
color: var(--bistro-charcoal);
text-decoration: none;
font-weight: 600;
border-radius: 4px;
transition: background-color 0.3s ease;
}
#hero a:hover {
background-color: #c9a030;
}Content Sections
/* ── Sections (shared) ─────────────────────────── */
section {
max-width: 900px;
margin: 0 auto;
padding: 3rem 2rem;
}
section h2 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 1.8rem;
color: var(--bistro-burgundy);
margin-bottom: 1rem;
border-bottom: 2px solid var(--bistro-gold);
padding-bottom: 0.5rem;
}
section h3 {
font-size: 1.3rem;
color: var(--bistro-charcoal);
margin-top: 1.5rem;
margin-bottom: 0.75rem;
}Menu List Styling
/* ── Menu items ────────────────────────────────── */
#menu ul {
list-style: none;
padding: 0;
}
#menu li {
padding: 0.75rem 0;
border-bottom: 1px dotted var(--bistro-smoke);
}
#menu li:last-child {
border-bottom: none;
}Hours Table
/* ── Table ─────────────────────────────────────── */
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 2rem;
}
th {
background-color: var(--bistro-burgundy);
color: #fff;
padding: 0.75rem 1rem;
text-align: left;
}
td {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--bistro-smoke);
}
tr:nth-child(even) {
background-color: var(--bistro-smoke);
}
/* ── Address ───────────────────────────────────── */
address {
font-style: normal;
line-height: 1.8;
}
address a {
color: var(--bistro-burgundy);
}Footer
/* ── Footer ────────────────────────────────────── */
footer {
background-color: var(--bistro-charcoal);
color: #ccc;
text-align: center;
padding: 2rem;
margin-top: 2rem;
}
footer a {
color: var(--bistro-gold);
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}⏸️ Pause & Check: Do You Understand?
Before moving forward, can you answer these?
- What advantage do CSS custom properties (variables) give you over hard-coded colour values?
- Why does the nav use display: flex and gap instead of float?
- What does box-sizing: border-box do, and why set it on every element?
Check Your Answers
- You define a colour once in :root and reference it everywhere with var(). To change the brand colour, you update one line instead of hunting through the entire stylesheet.
- Flexbox handles horizontal spacing cleanly — items auto-centre, gap adds even spacing, and it's easy to switch to vertical stacking on mobile. Float-based navigation requires clearfix hacks and is harder to maintain.
- It makes width and height include padding and border, so a 300px-wide element stays 300px even when you add padding. Without it, padding increases the total size, which breaks layouts.
How confident are you with this concept?
😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!
Step 4 — Make It Responsive
Your page needs to work on phones too. Add this at the bottom of your stylesheet:
/* ── Responsive ────────────────────────────────── */
@media (max-width: 700px) {
header h1 {
font-size: 1.8rem;
}
nav ul {
flex-direction: column;
gap: 0.75rem;
}
#hero {
padding: 2.5rem 1rem;
}
#hero h2 {
font-size: 1.5rem;
}
section {
padding: 2rem 1rem;
}
}Save, refresh your browser, and resize the window. The nav should stack vertically on narrow screens, and the text should stay readable at any width.
Step 5 — Preview & Debug
Before calling this done, run through this quick checklist:
Pre-Flight Checklist
- Open in browser — double-click
index.htmlor use VS Code’s Live Server extension - Check DevTools Console — press F12 and look for errors (red text). A 404 means a file path is wrong
- Validate your HTML — right-click → “View Page Source” and scan for unclosed tags or typos
- Resize the window — does the layout hold up at phone, tablet, and desktop widths?
- Check links — click each nav link. They should scroll to the matching section
Common issues:
- Styles not loading? Check the
<link>tag — doeshref="css/style.css"match your actual file path? - Fonts not changing? Google Fonts requires an internet connection. We’ll add the
<link>for Playfair Display in Part 2; for now the fallback serif will kick in. - Nav links not scrolling? Make sure each section’s
idmatches thehrefin the nav (e.g.,id="menu"andhref="#menu").
💪 Extend Your Homepage
Now try this on your own without hints!
Your Task:
You’ve built the core homepage. Now add two more features on your own:
- A “Catering” section between About and Menu. Include a heading, a short paragraph about Black Swan Catering for events, and a link that says “Enquire Now” pointing to
#contact. - A “Gallery Preview” section before the footer. Add three placeholder
<img>tags with descriptivealttext (the images can be broken for now — we’ll add real images in Part 2). Hint: use<figure>and<figcaption>.
Requirements:
- Catering section uses a semantic <section> with an id
- Heading hierarchy is correct (h2 for section title, not h1)
- Enquire Now link points to #contact
- Gallery uses <figure> and <figcaption> elements
- All images have descriptive alt text
Stretch Goals (Optional):
- Add matching CSS styles for both new sections
- Add a nav link for the Catering section in the header
- Style the gallery images in a row using display: flex
Success Criteria:
| Criteria | You've succeeded if... |
|---|---|
| Catering section uses a semantic <section> with an id | Section has <section id=catering> wrapping the content |
| Heading hierarchy is correct | Uses <h2> for the section heading, not <h1> |
| Gallery uses <figure> and <figcaption> | Each image is wrapped in <figure> with a <figcaption> caption |
| New sections have matching CSS styles | Styles follow the same pattern as existing sections |
What You’ve Built
Take a moment to appreciate what you’ve accomplished. You now have:
- A properly structured project folder with separated HTML, CSS, JS, and images
- A semantic HTML homepage with header, nav, hero, about, menu, hours table, address, and footer
- A CSS stylesheet with custom properties, typography, layout, and a responsive media query
- A page that works on desktop and mobile
Coming Up in Part 2
In Part 2 — Layout & Sections, you’ll take this single-column page and give it a professional multi-section layout using CSS Flexbox. You’ll add Google Fonts, images, and refine the spacing and visual hierarchy.
Summary
🏁 Part 1 Complete: Your First Web Page
Key Takeaways:
- Every web project starts with a clean folder structure: index.html at the root, css/, js/, and images/ subfolders.
- Semantic HTML (<header>, <nav>, <section>, <footer>, <address>) communicates meaning to browsers, screen readers, and search engines.
- CSS custom properties (--bistro-burgundy) let you manage brand colours from a single place.
- A mobile-friendly @media query ensures your page works on any device.
- DevTools (F12) is your debugging partner — always check the Console for errors.
Learning Objectives Review:
Look back at what you set out to learn. Can you now:
- ✅ Set up a project folder with proper structure Check!
- ✅ Write a semantic HTML homepage from scratch Got it!
- ✅ Use headings, paragraphs, lists, links, a table, and address Can explain it!
- ✅ Create a linked CSS stylesheet with variables and layout Could teach this!
- ✅ Preview and debug in a browser Check!
If you can confidently answer "yes" to most of these, you're ready to move on!
Think & Reflect:
🏗️ Building from Scratch
- What was the most surprising thing about building a real page from scratch?
- Which step felt most natural? Which felt hardest?
🎨 HTML & CSS Together
- Which HTML element did you find most useful? Which felt unfamiliar?
- How did adding CSS change your perception of the plain HTML page?
🚀 Next Steps
- If you were building this for a real restaurant, what would you add next?
🤔 Real-World Test:
Every real website follows this same process:
- Set up a project folder with clear structure
- Write semantic HTML with proper heading hierarchy
- Link a stylesheet and define brand colours as variables
- Test in the browser and fix issues with DevTools
You’ve just done all four. This is genuinely how professional web developers start every project.
🎯 Looking Ahead:
In Part 2, you’ll transform this single-column page into a proper layout with Flexbox, add images, integrate Google Fonts, and refine the visual design. Your Black Swan Bistro site is just getting started!
Recommended Next Steps
Continue Learning
Ready to move forward? Continue with the next tutorial in this series:
Black Swan Bistro (BSB) Part 2: Build the Homepage Wireframe Layout with CSSAdditional Resources
Deepen your understanding with these helpful resources:
- MDN: Getting started with HTML - Comprehensive guide to HTML basics from Mozilla.
Progress tracking is disabled. Enable it in to track your completed tutorials.
Cookie Settings