Move services and team content to Markdown

This commit is contained in:
Kevin
2026-09-02 10:43:45 -04:00
parent 8b8c541b3c
commit 1b25dc37a6
12 changed files with 103 additions and 6 deletions
+24 -1
View File
@@ -23,4 +23,27 @@ const faq = defineCollection({
}),
});
export const collections = { blog, faq };
const services = defineCollection({
loader: glob({ base: './sites/www/content/services', pattern: '**/*.md' }),
schema: z.object({
title: z.string().min(3).max(80),
price: z.string().min(2).max(48),
items: z.array(z.string().min(3).max(80)).min(1).max(8),
order: z.number().int().min(0).max(99).default(0),
featured: z.boolean().default(false),
draft: z.boolean().default(false),
}),
});
const team = defineCollection({
loader: glob({ base: './sites/www/content/team', pattern: '**/*.md' }),
schema: z.object({
name: z.string().min(3).max(80),
role: z.string().min(3).max(80),
image: z.string().startsWith('/images/'),
order: z.number().int().min(0).max(99).default(0),
draft: z.boolean().default(false),
}),
});
export const collections = { blog, faq, services, team };
+4 -1
View File
@@ -1,7 +1,10 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import PageIntro from '../components/PageIntro.astro';
import { getCollection, render } from 'astro:content';
import { isBlog, site } from '../lib/site-data.js';
if (isBlog) return Astro.redirect('/');
const team = (await getCollection('team', ({ data }) => !data.draft)).sort((a, b) => a.data.order - b.data.order);
const teamCards = await Promise.all(team.map(async (member) => ({ member, Content: (await render(member)).Content })));
---
<BaseLayout title={`About | ${site.name}`}><PageIntro eyebrow="Our pack" title="We know that great care starts with knowing your dog." lede="The Happy Tails team brings patience, playfulness, and real experience to every visit." image="/images/happy-tails-team.jpg" imageAlt="Dogs and the Happy Tails team enjoying the park" /><section class="section"><div class="shell story-grid"><div><p class="eyebrow">How we work</p><h2>{site.story.heading}</h2><p class="lede">{site.story.copy}</p><p>Our team communicates clearly, keeps routines consistent, and makes safety a habit—not an afterthought.</p></div><img src={site.story.image} alt={site.story.imageAlt} loading="lazy" /></div></section><section class="section surface"><div class="shell"><div class="section-heading"><p class="eyebrow">Meet the team</p><h2>Good people for good dogs.</h2></div><div class="team-grid">{site.team.map((member) => <article class="team-card"><div class="team-avatar" aria-hidden="true">{member.name.split(' ').map((part) => part[0]).join('')}</div><div><p class="eyebrow">{member.role}</p><h3>{member.name}</h3><p>{member.bio}</p></div></article>)}</div></div></section></BaseLayout>
<BaseLayout title={`About | ${site.name}`}><PageIntro eyebrow="Our pack" title="We know that great care starts with knowing your dog." lede="The Happy Tails team brings patience, playfulness, and real experience to every visit." image="/images/happy-tails-team.jpg" imageAlt="Dogs and the Happy Tails team enjoying the park" /><section class="section"><div class="shell story-grid"><div><p class="eyebrow">How we work</p><h2>{site.story.heading}</h2><p class="lede">{site.story.copy}</p><p>Our team communicates clearly, keeps routines consistent, and makes safety a habit—not an afterthought.</p></div><img src={site.story.image} alt={site.story.imageAlt} loading="lazy" /></div></section><section class="section surface"><div class="shell"><div class="section-heading"><p class="eyebrow">Meet the team</p><h2>Good people for good dogs.</h2></div><div class="team-grid">{teamCards.map(({ member, Content }) => <article class="team-card"><div class="team-avatar" aria-hidden="true">{member.data.name.split(' ').map((part) => part[0]).join('')}</div><div><p class="eyebrow">{member.data.role}</p><h3>{member.data.name}</h3><Content /></div></article>)}</div></div></section></BaseLayout>
+4 -1
View File
@@ -2,7 +2,10 @@
import BaseLayout from '../layouts/BaseLayout.astro';
import CallToAction from '../components/CallToAction.astro';
import PageIntro from '../components/PageIntro.astro';
import { getCollection, render } from 'astro:content';
import { isBlog, site } from '../lib/site-data.js';
if (isBlog) return Astro.redirect('/');
const services = (await getCollection('services', ({ data }) => !data.draft)).sort((a, b) => a.data.order - b.data.order);
const serviceCards = await Promise.all(services.map(async (service) => ({ service, Content: (await render(service)).Content })));
---
<BaseLayout title={`Services | ${site.name}`}><PageIntro eyebrow="Services" title="Everything your dog needs for a brighter day." lede="Flexible, personal care—with no one-size-fits-all routines." image="/images/dog-grooming.jpg" imageAlt="A dog receiving gentle grooming care" /><section class="section"><div class="shell service-grid">{site.services.map((service, index) => <article class:list={['service-card', { featured: index === 1 }]}><p class="eyebrow">{service.price}</p><h2>{service.title}</h2><p>{service.description}</p><ul>{service.items.map((item) => <li>{item}</li>)}</ul><a class="text-link" href="/contact">Ask about {service.title.toLowerCase()} →</a></article>)}</div></section><CallToAction eyebrow="A simple start" heading="Let's meet your dog first." copy="Tell us a little about their routine, personality, and what would make their day better." href="/contact" label="Book a meet and greet" /></BaseLayout>
<BaseLayout title={`Services | ${site.name}`}><PageIntro eyebrow="Services" title="Everything your dog needs for a brighter day." lede="Flexible, personal care—with no one-size-fits-all routines." image="/images/dog-grooming.jpg" imageAlt="A dog receiving gentle grooming care" /><section class="section"><div class="shell service-grid">{serviceCards.map(({ service, Content }) => <article class:list={['service-card', { featured: service.data.featured }]}><p class="eyebrow">{service.data.price}</p><h2>{service.data.title}</h2><Content /><ul>{service.data.items.map((item) => <li>{item}</li>)}</ul><a class="text-link" href="/contact">Ask about {service.data.title.toLowerCase()} →</a></article>)}</div></section><CallToAction eyebrow="A simple start" heading="Let's meet your dog first." copy="Tell us a little about their routine, personality, and what would make their day better." href="/contact" label="Book a meet and greet" /></BaseLayout>