Initial commit

This commit is contained in:
ponzischeme89
2026-05-02 08:26:18 +12:00
commit b7ea05f150
119 changed files with 13641 additions and 0 deletions
+22
View File
@@ -0,0 +1,22 @@
import { error, redirect } from '@sveltejs/kit';
import { staticPages, type StaticPageSlug } from '$lib/content/static-pages';
import { getSharedPageContent } from '$lib/server/content';
export async function load({ params }) {
if (params.slug === 'about-us') {
throw redirect(301, '/about');
}
const slug = params.slug as StaticPageSlug;
const page = staticPages[slug];
if (!page) {
throw error(404, 'Page not found');
}
return {
content: await getSharedPageContent(),
page,
slug
};
}
+238
View File
@@ -0,0 +1,238 @@
<script lang="ts">
import SeoHead from '$lib/components/SeoHead.svelte';
import AboutPage from '$lib/components/AboutPage.svelte';
import Footer from '$lib/components/Footer.svelte';
import Header from '$lib/components/Header.svelte';
import BookingPage from '$lib/components/BookingPage.svelte';
import LegalPage from '$lib/components/LegalPage.svelte';
import PricingPage from '$lib/components/PricingPage.svelte';
import { aboutPageContent } from '$lib/content/about';
import ServiceLandingPage from '$lib/components/ServiceLandingPage.svelte';
import { dogWalkingContent } from '$lib/content/dog-walking';
import { ourPricingContent } from '$lib/content/our-pricing';
import { packWalksContent } from '$lib/content/pack-walks';
import { privacyPolicyContent } from '$lib/content/privacy-policy';
import { puppyVisitsContent } from '$lib/content/puppy-visits';
import { termsAndConditionsContent } from '$lib/content/terms-and-conditions';
import type { PageData } from './$types';
export let data: PageData;
const siteUrl = 'https://www.goodwalk.co.nz';
const defaultSeoImage = '/images/auckland-dog-walking-happy-dog-hero.png';
const defaultSeoImageAlt = 'Goodwalk Auckland dog walking services';
function breadcrumbSchema(name: string, path: string) {
return {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{
'@type': 'ListItem',
position: 1,
name: 'Home',
item: siteUrl
},
{
'@type': 'ListItem',
position: 2,
name,
item: `${siteUrl}${path}`
}
]
};
}
let seoImage = defaultSeoImage;
let seoImageAlt = defaultSeoImageAlt;
let preloadHeroImage = false;
let pageStructuredData: Record<string, unknown>[] = [];
$: {
seoImage = defaultSeoImage;
seoImageAlt = defaultSeoImageAlt;
preloadHeroImage = false;
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'WebPage',
name: data.page.title,
description: data.page.description,
url: `${siteUrl}${data.page.canonicalPath}`
},
breadcrumbSchema(data.page.title, data.page.canonicalPath)
];
if (data.slug === 'pack-walks') {
preloadHeroImage = true;
seoImage = packWalksContent.hero.imageUrl;
seoImageAlt = packWalksContent.hero.imageAlt;
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'Service',
name: packWalksContent.hero.title,
description: data.page.description,
serviceType: 'Pack Walks',
provider: {
'@type': 'LocalBusiness',
name: 'Goodwalk',
url: siteUrl
},
areaServed: 'Auckland Central, New Zealand',
image: seoImage,
url: `${siteUrl}${data.page.canonicalPath}`
},
breadcrumbSchema('Pack Walks', data.page.canonicalPath)
];
} else if (data.slug === 'dog-walking') {
preloadHeroImage = true;
seoImage = dogWalkingContent.hero.imageUrl;
seoImageAlt = dogWalkingContent.hero.imageAlt;
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'Service',
name: dogWalkingContent.hero.title,
description: data.page.description,
serviceType: '1:1 Dog Walking',
provider: {
'@type': 'LocalBusiness',
name: 'Goodwalk',
url: siteUrl
},
areaServed: 'Auckland Central, New Zealand',
image: seoImage,
url: `${siteUrl}${data.page.canonicalPath}`
},
breadcrumbSchema('1:1 Walks', data.page.canonicalPath)
];
} else if (data.slug === 'puppy-visits') {
preloadHeroImage = true;
seoImage = puppyVisitsContent.hero.imageUrl;
seoImageAlt = puppyVisitsContent.hero.imageAlt;
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'Service',
name: puppyVisitsContent.hero.title,
description: data.page.description,
serviceType: 'Puppy Visits',
provider: {
'@type': 'LocalBusiness',
name: 'Goodwalk',
url: siteUrl
},
areaServed: 'Auckland Central, New Zealand',
image: seoImage,
url: `${siteUrl}${data.page.canonicalPath}`
},
breadcrumbSchema('Puppy Visits', data.page.canonicalPath)
];
} else if (data.slug === 'our-pricing') {
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'CollectionPage',
name: data.page.title,
description: data.page.description,
url: `${siteUrl}${data.page.canonicalPath}`
},
breadcrumbSchema('Our Pricing', data.page.canonicalPath)
];
} else if (data.slug === 'about' || data.slug === 'about-us') {
seoImage = aboutPageContent.sections[0].imageUrl;
seoImageAlt = aboutPageContent.sections[0].imageAlt;
pageStructuredData = [
{
'@context': 'https://schema.org',
'@type': 'AboutPage',
name: data.page.title,
description: data.page.description,
url: `${siteUrl}${data.page.canonicalPath}`,
image: seoImage
},
breadcrumbSchema('About Us', data.page.canonicalPath)
];
}
}
</script>
<SeoHead
title={data.page.title}
description={data.page.description}
canonicalPath={data.page.canonicalPath}
image={seoImage}
imageAlt={seoImageAlt}
structuredData={pageStructuredData}
preloadImage={preloadHeroImage}
/>
<Header navigation={data.content.navigation} />
{#if data.slug === 'pack-walks'}
<ServiceLandingPage content={data.content} pageContent={packWalksContent} />
{:else if data.slug === 'dog-walking'}
<ServiceLandingPage content={data.content} pageContent={dogWalkingContent} />
{:else if data.slug === 'puppy-visits'}
<ServiceLandingPage content={data.content} pageContent={puppyVisitsContent} />
{:else if data.slug === 'our-pricing'}
<PricingPage content={data.content} pageContent={ourPricingContent} />
{:else if data.slug === 'about' || data.slug === 'about-us'}
<AboutPage content={data.content} pageContent={aboutPageContent} />
{:else if data.slug === 'terms-and-conditions'}
<LegalPage pageContent={termsAndConditionsContent} />
{:else if data.slug === 'privacy-policy'}
<LegalPage pageContent={privacyPolicyContent} />
{:else if data.slug === 'booking'}
<BookingPage booking={data.content.booking} />
{:else}
<main class="static-page">
<section class="static-page-hero">
<div class="static-page-inner">
<h1>{data.page.title}</h1>
</div>
</section>
</main>
{/if}
<Footer footer={data.content.footer} />
<style>
.static-page {
min-height: 50vh;
background: var(--off-white);
}
.static-page-hero {
padding: 96px 0 120px;
}
.static-page-inner {
max-width: var(--max-w);
margin: 0 auto;
padding: 0 50px;
}
h1 {
font-family: var(--font-head);
font-size: 56px;
line-height: 1.05;
letter-spacing: -0.04em;
color: #000;
}
@media (max-width: 768px) {
.static-page-hero {
padding: 56px 0 72px;
}
.static-page-inner {
padding: 0 24px;
}
h1 {
font-size: 34px;
}
}
</style>
@@ -0,0 +1,42 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { staticPages } from '$lib/content/static-pages';
import { sharedPageContent } from '../../test/fixtures';
const { getSharedPageContent } = vi.hoisted(() => ({
getSharedPageContent: vi.fn()
}));
vi.mock('$lib/server/content', () => ({
getSharedPageContent
}));
import { load } from './+page.server';
describe('static slug page server load', () => {
beforeEach(() => {
getSharedPageContent.mockReset();
});
it('redirects the legacy about-us slug to /about', async () => {
await expect(load({ params: { slug: 'about-us' } } as never)).rejects.toMatchObject({
status: 301,
location: '/about'
});
});
it('throws a 404 for unknown slugs', async () => {
await expect(load({ params: { slug: 'missing-page' } } as never)).rejects.toMatchObject({
status: 404
});
});
it('returns the shared content and page metadata for valid static routes', async () => {
getSharedPageContent.mockResolvedValue(sharedPageContent);
await expect(load({ params: { slug: 'pack-walks' } } as never)).resolves.toEqual({
content: sharedPageContent,
page: staticPages['pack-walks'],
slug: 'pack-walks'
});
});
});
+46
View File
@@ -0,0 +1,46 @@
import { render, screen } from '@testing-library/svelte';
import { describe, expect, it } from 'vitest';
import SlugPage from './+page.svelte';
import { createStaticRouteData } from '../../test/fixtures';
describe('static slug route page', () => {
it.each([
['pack-walks', 'Join our Tiny Gang!'],
['dog-walking', 'Walks for larger breeds, too!'],
['puppy-visits', 'Introducing Puppy Visits: Building strong foundations for our pack walks!'],
['our-pricing', 'Simple, transparent pricing — no lock-in contracts.'],
['about', 'Who we are'],
['booking', "Fill in the form below and we'll be in touch to arrange a free introduction."],
['terms-and-conditions', '1. Application of Terms'],
['privacy-policy', 'How we collect your information']
] as const)('renders the %s page branch', (slug, expectedText) => {
render(SlugPage, {
data: createStaticRouteData(slug)
});
expect(screen.getByText(expectedText)).toBeInTheDocument();
});
it('sets SEO metadata for rendered slug pages', () => {
render(SlugPage, {
data: createStaticRouteData('about')
});
expect(document.title).toBe('About Us | Dog Walkers | Goodwalk');
expect(document.head.innerHTML).toContain('AboutPage');
});
it.each(['terms-and-conditions', 'privacy-policy'] as const)(
'does not render booking or testimonial sections on %s',
(slug) => {
render(SlugPage, {
data: createStaticRouteData(slug)
});
expect(
screen.queryByText("Fill in the form below and we'll be in touch to arrange a free introduction.")
).not.toBeInTheDocument();
expect(screen.queryByText('Why people choose us!')).not.toBeInTheDocument();
}
);
});