Connect Your Pages

BookIt has five routes now: /, /about, /contact, /services and /services/[slug], — but users can only reach them by typing URLs into the address bar. That’s not how websites work. Let’s add proper navigation so users can click their way through the app.


What You’ll Learn

  • Use standard anchor tags for navigation
  • Understand SvelteKit’s automatic link optimization
  • Build navigation into BookIt’s pages
  • Link from services list to service details

Here’s the good news: you don’t need a special component. Standard HTML anchor tags work perfectly:

<a href="/services">View Services</a>

SvelteKit automatically intercepts these links and handles navigation client-side — no full page reload, no special imports required.


Add Navigation to the Homepage

Let’s update BookIt’s homepage to link to other pages.

<!-- filename: src/routes/+page.svelte -->
<script>
	const appName = 'BookIt'
	const tagline = 'Book your next service appointment in minutes.'
</script>

<div class="hero">
	<h1>Welcome to {appName}</h1>
	<p class="tagline">{tagline}</p>
</div>

<nav>
	<a href="/services">Browse Services</a>
	<a href="/about">About Us</a>
	<a href="/contact">Contact</a>
</nav>

<section>
	<h2>How It Works</h2>
	<ol>
		<li>Browse our available services</li>
		<li>Choose a time that works for you</li>
		<li>Confirm your booking</li>
	</ol>
	<a href="/services">Get Started →</a>
</section>

Save and test. Clicking “Browse Services” should take you to /services without a page refresh. The URL changes, content updates, but it feels instant.


The services list should link to individual service pages. Update your services page:

<!-- filename: src/routes/services/+page.svelte -->
<script>
	const services = [
		{
			id: '1',
			slug: 'lawn-mowing',
			name: 'Lawn Mowing',
			description: 'Professional lawn mowing service for residential properties.',
			price: 50,
			duration: 60
		},
		{
			id: '2',
			slug: 'hedge-trimming',
			name: 'Hedge Trimming',
			description: 'Expert hedge and shrub trimming to keep your garden tidy.',
			price: 75,
			duration: 90
		},
		{
			id: '3',
			slug: 'garden-consultation',
			name: 'Garden Consultation',
			description: 'One-on-one consultation for garden planning and advice.',
			price: 100,
			duration: 60
		}
	]
</script>

<h1>Our Services</h1>
<p>Browse our available services and book your appointment.</p>

<ul>
	{#each services as service}
		<li>
			<h2>
				<a href="/services/{service.slug}">{service.name}</a>
			</h2>
			<p>{service.description}</p>
			<p><strong>${service.price}</strong> · {service.duration} minutes</p>
			<a href="/services/{service.slug}">View Details →</a>
		</li>
	{/each}
</ul>

The key addition is href="/services/{service.slug}". This creates links like /services/lawn-mowing, /services/hedge-trimming, etc. — exactly what our dynamic route expects.


Add Navigation to the Detail Page

Service detail pages should link back to the services list:

<!-- filename: src/routes/services/[slug]/+page.svelte -->
<script>
	let { data } = $props()
</script>

<nav>
	<a href="/services">← Back to Services</a>
</nav>

{#if data.service}
	<h1>{data.service.name}</h1>
	<p>{data.service.description}</p>

	<dl>
		<dt>Price</dt>
		<dd>${data.service.price}</dd>

		<dt>Duration</dt>
		<dd>{data.service.duration} minutes</dd>
	</dl>

	<button>Book Now</button>
{:else}
	<h1>Service Not Found</h1>
	<p>Sorry, we couldn't find a service matching "{data.slug}".</p>
{/if}

Create a Simple Navigation Component

At its core, the navigation should appear dynamically on every page, with a few exceptions. For now, we’ll add it manually to each page. In the next module, we’ll introduce layouts, which handle this in a cleaner and more scalable way.

Add this navigation block as the first part of HTML markup in each +page.svelte file:

<nav>
	<a href="/">BookIt</a>
	<a href="/services">Services</a>
	<a href="/about">About</a>
	<a href="/contact">Contact</a>
</nav>

Yes, this is repetitive. You’ll fix it with layouts. For now, it works.


When you click a link in SvelteKit:

  1. SvelteKit intercepts the click
  2. Instead of a full page load, it fetches only what changed
  3. The URL updates in the browser
  4. The new page renders instantly

This “client-side routing” makes navigation feel snappy. But if JavaScript fails to load, links still work — they become regular page navigations. This is called progressive enhancement.

SvelteKit won’t intercept links that:

  • Have a target attribute (target="_blank")
  • Point to different origins (https://external-site.com)
  • Have the rel="external" attribute
  • Have a download attribute
<!-- These navigate normally (full page load) -->
<a href="https://google.com">External Link</a>
<a href="/file.pdf" download>Download PDF</a>
<a href="/services" target="_blank">Open in New Tab</a>

Test Your Navigation

With the dev server running, click through BookIt:

  1. Start at homepage (/)
  2. Click “Browse Services” → /services
  3. Click a service name → /services/lawn-mowing
  4. Click “Back to Services” → /services
  5. Click “About” → /about
  6. Click “Contact” → /contact
  7. Click “BookIt” logo → /

Every click should be instant. Watch the URL bar — it updates without the page flickering or reloading.


Common Mistakes

Missing Leading Slash

<!-- ❌ Relative path — might break depending on current route -->
<a href="services">Services</a>

<!-- ✅ Absolute path — always works -->
<a href="/services">Services</a>

Always use absolute paths (starting with /) for navigation links. Relative paths resolve based on the current URL, which can cause unexpected behavior.

Hardcoding Dynamic Paths

<!-- ❌ Hardcoded — doesn't use actual data -->
<a href="/services/lawn-mowing">View Details</a>

<!-- ✅ Dynamic — works for any service -->
<a href="/services/{service.slug}">View Details</a>

When linking to dynamic routes, always build the URL from your data.


Summary

Navigation in SvelteKit uses standard anchor tags. SvelteKit automatically makes them fast with client-side routing while keeping them functional without JavaScript.

Key takeaways:

  • Use regular <a href="..."> tags for navigation
  • SvelteKit intercepts and optimizes internal links automatically
  • Build dynamic links using template syntax: href="/path/{variable}"
  • Always use absolute paths starting with /

Module Complete! 🎉

You’ve finished Module 2: Basic Routing. BookIt now has:

  • Homepage at /
  • Services list at /services
  • Individual service pages at /services/[slug]
  • About page at /about
  • Contact page at /contact
  • Navigation between all pages

What’s Missing: The navigation is duplicated across every page. That’s tedious and error-prone.


Next Steps

Continue with Module 3: Layouts where you’ll learn to share UI (like navigation) across all pages without repetition.