Phase 2: homepage that converts

- Hero says what and where, with No fix no fee / $35 diagnosis, Call and
  Text CTAs, and the real Google rating
- Common fixes grid with owner-confirmed labour prices, linking to
  service pages
- How it works, About (first person), testimonials, areas served with
  map, a short business IT block, rewritten FAQ and a final CTA band
- Sticky Call/Text bar on mobile (site-wide); Chatwoot bubble moved above it
- Button renders a link when given href (no more button-inside-link)
- Business facts (prices, rating, testimonials, contact links) in site.js

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
asownerytandClaude Opus 5.5 committed 2026-09-30 20:32:46 +13:00
1 parent c085e2b031
commit 7043b47de1
9 files changed
+413 -131

No files matched your search

+309 -106
View File
@@ -1,12 +1,12 @@
import Image from "next/image";
import Link from "next/link";
import styles from "./page.module.css";
import bgimage from "./assets/header-bg.jpg";
import Button from "./components/Button";
import Link from "next/link";
import { GoogleMapsEmbed } from "@next/third-parties/google";
import ContactForm from "./components/ContactForm";
import JsonLd from "./components/JsonLd";
import { pageMetadata, faqSchema } from "@/lib/site";
import { pageMetadata, faqSchema, business, links } from "@/lib/site";
import { homeFaqs } from "@/lib/faqs";
import {
Accordion,
@@ -14,6 +14,23 @@ import {
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import {
ArrowRight,
Briefcase,
Cpu,
FolderInput,
HardDrive,
Laptop,
MapPin,
MessageCircle,
MessageSquare,
Monitor,
MonitorCog,
Phone,
Power,
ShieldAlert,
Star,
} from "lucide-react";
export const metadata = pageMetadata({
title: "Computer & Laptop Repair Te Atatū | Te Atatu Computers",
@@ -22,6 +39,82 @@ export const metadata = pageMetadata({
path: "/",
});
const commonFixes = [
{
icon: Laptop,
title: "Cracked laptop screen",
price: "from $35",
href: "/services/computer-repair",
},
{
icon: Power,
title: "Won't turn on or won't boot",
price: "$35 diagnosis",
href: "/services/computer-repair",
},
{
icon: HardDrive,
title: "Slow computer? SSD upgrade",
price: "from $45 + the drive",
href: "/services/computer-upgrades",
},
{
icon: ShieldAlert,
title: "Viruses & scam pop-ups",
price: "from $35",
href: "/services/virus-removal",
},
{
icon: MonitorCog,
title: "Windows reinstall",
price: "from $45",
href: "/services/computer-upgrades",
},
{
icon: FolderInput,
title: "Move files to a new PC",
price: "from $45",
href: "/services/it-support",
},
{
icon: Monitor,
title: "New computer setup",
price: "from $35",
href: "/services/it-support",
},
{
icon: Cpu,
title: "Custom PC build",
price: "from $35",
href: "/contact",
},
];
const steps = [
{
title: "Get in touch",
text: "Call, text, WhatsApp or send the form. Tell me what's going on and I'll let you know the next step.",
},
{
title: "Get it to me",
text: "Drop it off at Graham Avenue by appointment, or I can pick it up or come to you (travel fee depends on distance). Many software problems can be fixed remotely.",
},
{
title: "Fixed and back to you",
text: "$35 diagnosis, and I'll tell you the cost before I start. Most repairs are done within 24–48 hours, although this isn't guaranteed.",
},
];
function SectionCta() {
return (
<p className="text-center mt-8">
<a href={links.tel} className="font-bold text-sky-800 hover:underline">
Call or text {business.phone}
</a>
</p>
);
}
export default function Home() {
return (
<div className={styles.page}>
@@ -43,35 +136,39 @@ export default function Home() {
<div className={styles.textbox}>
<div className="container mx-auto">
<div className={styles.textboxInner}>
<h1 className="mb-4 text-6xl font-bold">
Delivering Exceptional Service.
<h1 className="mb-4 text-4xl md:text-6xl font-bold">
Laptop & PC repairs in Te Atatū
</h1>
<p className={styles.p}>
<strong>
Your Local Experts for PCs, Laptops, IT Support &
More.
</strong>
<br />
From hardware fixes to software solutions, we&apos;re here
to help. Friendly, affordable service right in your
neighborhood!
<strong>No fix, no fee.</strong>{" "}A $35 diagnosis, then I&apos;ll
tell you what it costs before I start. Local, honest help
for West Auckland.
</p>
<Link href="/contact">
<Button>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M2 3.5A1.5 1.5 0 0 1 3.5 2h1.148a1.5 1.5 0 0 1 1.465 1.175l.716 3.223a1.5 1.5 0 0 1-1.052 1.767l-.933.267c-.41.117-.643.555-.48.95a11.542 11.542 0 0 0 6.254 6.254c.395.163.833-.07.95-.48l.267-.933a1.5 1.5 0 0 1 1.767-1.052l3.223.716A1.5 1.5 0 0 1 18 15.352V16.5a1.5 1.5 0 0 1-1.5 1.5H15c-1.149 0-2.263-.15-3.326-.43A13.022 13.022 0 0 1 2.43 8.326 13.019 13.019 0 0 1 2 5V3.5Z"
clipRule="evenodd"
/>
</svg>
Get a Quote Now
<div className="flex flex-col sm:flex-row gap-3 mb-6">
<Button href={links.tel}>
<Phone aria-hidden="true" />
Call {business.phone}
</Button>
</Link>
<Button href={links.sms} variant="outline">
<MessageSquare aria-hidden="true" />
Text me
</Button>
</div>
<p className="flex flex-wrap items-center gap-x-2 gap-y-1 text-sm">
<Star
aria-hidden="true"
className="size-4 fill-yellow-400 text-yellow-400"
/>
<a
href={business.googleBusinessProfileUrl}
className="underline hover:no-underline"
>
{business.rating.value} from {business.rating.count}{" "}
Google reviews
</a>
<span aria-hidden="true">·</span>
<span>Local to Te Atatū</span>
</p>
</div>
</div>
</div>
@@ -79,100 +176,170 @@ export default function Home() {
</section>
<section className="container mx-auto mb-32">
<h2 className="text-center text-3xl font-bold mb-4">
Services we Offer
<h2 className="text-center text-3xl font-bold mb-2">
Common fixes & prices
</h2>
<div className="text-center mb-4 flex flex-row flex-wrap justify-center">
<div className="max-w-xs p-4 text-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
width="6rem"
className="mx-auto mb-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 17.25v1.007a3 3 0 0 1-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0 1 15 18.257V17.25m6-12V15a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 15V5.25m18 0A2.25 2.25 0 0 0 18.75 3H5.25A2.25 2.25 0 0 0 3 5.25m18 0V12a2.25 2.25 0 0 1-2.25 2.25H5.25A2.25 2.25 0 0 1 3 12V5.25"
/>
</svg>
<h3 className="text-xl font-bold mb-2">
Computer Repair/Upgrades
</h3>
<p>
We can fix anything from a broken screen to a software issue, or
upgrade your computer&apos;s parts and optimise Windows to get
your PC running like new again.
</p>
</div>
<div className="max-w-xs p-4 text-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
width="6rem"
className="mx-auto mb-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 0 0 2.25-2.25V6.75a2.25 2.25 0 0 0-2.25-2.25H6.75A2.25 2.25 0 0 0 4.5 6.75v10.5a2.25 2.25 0 0 0 2.25 2.25Zm.75-12h9v9h-9v-9Z"
/>
</svg>
<p className="text-center mb-8 text-slate-600">
Labour prices. Parts are extra, and I&apos;ll always quote before
starting.
</p>
<ul className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{commonFixes.map(({ icon: Icon, title, price, href }) => (
<li key={title}>
<Link
href={href}
className="flex h-full items-center gap-4 rounded-lg border p-4 transition hover:border-sky-800 hover:shadow-sm"
>
<Icon
aria-hidden="true"
className="size-8 shrink-0 text-sky-800"
strokeWidth={1.5}
/>
<span>
<span className="block font-bold">{title}</span>
<span className="block text-sky-800">{price}</span>
</span>
</Link>
</li>
))}
</ul>
<SectionCta />
</section>
<h3 className="text-xl font-bold mb-2">Desktop PC Building</h3>
<p>
We&apos;ll help you pick the parts and build a custom gaming or
workstation PC for you.
</p>
</div>
<div className="max-w-xs p-4 text-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
width="6rem"
className="mx-auto mb-4"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"
/>
</svg>
<h3 className="text-xl font-bold mb-2">Remote Access Support</h3>
<p>
We can remotely connect to your computer and fix
software/operating system related issues from the comfort of
your own home.
</p>
</div>
<section className="bg-slate-100 py-16 mb-32">
<div className="container mx-auto">
<h2 className="text-center text-3xl font-bold mb-8">
How it works
</h2>
<ol className="grid grid-cols-1 md:grid-cols-3 gap-8">
{steps.map(({ title, text }, i) => (
<li key={title} className="text-center max-w-sm mx-auto">
<span className="mx-auto mb-4 flex size-12 items-center justify-center rounded-full bg-sky-800 text-xl font-bold text-white">
{i + 1}
</span>
<h3 className="text-xl font-bold mb-2">{title}</h3>
<p>{text}</p>
</li>
))}
</ol>
<SectionCta />
</div>
</section>
<section className="container mx-auto flex flex-col gap-8 lg:flex-row mb-32">
<ContactForm />
<section className="container mx-auto mb-32 max-w-3xl text-center">
<h2 className="text-3xl font-bold mb-4">
Hi, I&apos;m {business.ownerName}
</h2>
<p className="text-lg mb-4">
I run Te Atatu Computers from Te Atatū Peninsula. When you call or
text, you&apos;re talking to the person who will actually fix your
computer. There&apos;s no call centre and no being passed around.
</p>
<p className="text-lg">
I&apos;ll explain what&apos;s wrong in plain language and tell you
what it will cost before I start. If I can&apos;t fix it, you
don&apos;t pay the diagnosis fee.
</p>
<SectionCta />
</section>
<section className="container mx-auto mb-32">
<h2 className="text-center text-3xl font-bold mb-8">
What customers say
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 max-w-4xl mx-auto">
{business.testimonials.map(({ name, quote }) => (
<figure key={name} className="rounded-lg border p-6">
<blockquote className="mb-3">&ldquo;{quote}&rdquo;</blockquote>
<figcaption className="font-bold">{name}</figcaption>
</figure>
))}
</div>
<p className="text-center mt-8">
<a
href={business.googleBusinessProfileUrl}
className="inline-flex items-center gap-1 font-bold text-sky-800 hover:underline"
>
Read all reviews on Google
<ArrowRight aria-hidden="true" className="size-4" />
</a>
</p>
</section>
<section className="container mx-auto mb-32 flex flex-col gap-8 lg:flex-row">
<div className="w-full">
<h2 className="text-3xl font-bold mb-4">Areas I serve</h2>
<p className="mb-4 flex items-start gap-2">
<MapPin aria-hidden="true" className="size-5 shrink-0 mt-0.5" />
<span>
Based at {business.address.street}, {business.address.suburb}.
Drop-offs by appointment.
</span>
</p>
<p className="mb-4">
Onsite visits, pickup and return, and remote support across:
</p>
<ul className="grid grid-cols-2 gap-2 mb-6 list-disc pl-6">
{business.serviceArea.map((area) => (
<li key={area}>{area}</li>
))}
</ul>
<p>
Not on the list? Get in touch and I&apos;ll let you know if I can
help.
</p>
<p className="mt-4">
<a
href={links.tel}
className="font-bold text-sky-800 hover:underline"
>
Call or text {business.phone}
</a>
</p>
</div>
<div className="w-full">
<GoogleMapsEmbed
apiKey="AIzaSyDbgQY55TQY5CefsCUwKbc8RfoOUe8U5gY"
width="100%"
height="600px"
height="400px"
mode="place"
q="place_id:ChIJz0ZoDYhADW0R0TDgWoWMq0M"
/>
</div>
</section>
<section className="container mx-auto mb-16 max-w-3xl mb-32 scroll-mt-20" id="faq">
<section className="container mx-auto mb-32">
<div className="rounded-lg border p-6 md:p-8 flex flex-col md:flex-row gap-6 md:items-center">
<Briefcase
aria-hidden="true"
className="size-12 shrink-0 text-sky-800"
strokeWidth={1.5}
/>
<div className="flex-1">
<h2 className="text-2xl font-bold mb-2">For local businesses</h2>
<p>
IT support for small businesses: Wi-Fi and networks, email,
backups, security and new PC setup. Onsite or remote, from
$35 an hour.
</p>
</div>
<Link
href="/services/it-support"
className="inline-flex items-center gap-1 font-bold text-sky-800 hover:underline"
>
Business IT support
<ArrowRight aria-hidden="true" className="size-4" />
</Link>
</div>
</section>
<section
className="container mx-auto max-w-3xl mb-32 scroll-mt-20"
id="faq"
>
<JsonLd data={faqSchema(homeFaqs)} />
<h2 className="text-center text-3xl font-bold mb-8">
Frequently Asked Questions
Frequently asked questions
</h2>
<Accordion className="mb-8">
{homeFaqs.map(({ question, answer, list }, i) => (
@@ -191,6 +358,42 @@ export default function Home() {
</AccordionItem>
))}
</Accordion>
<SectionCta />
</section>
<section className="bg-sky-900 text-white py-16">
<div className="container mx-auto text-center">
<h2 className="text-3xl font-bold mb-4">
Get your computer sorted
</h2>
<p className="mb-8">
Call or text now, or send the details and I&apos;ll get back to
you with a quote.
</p>
<div className="flex flex-col sm:flex-row flex-wrap justify-center gap-3">
<Button href={links.tel}>
<Phone aria-hidden="true" />
Call {business.phone}
</Button>
<Button href={links.sms} variant="outline">
<MessageSquare aria-hidden="true" />
Text me
</Button>
<Button href={links.whatsapp} variant="outline">
<MessageCircle aria-hidden="true" />
WhatsApp
</Button>
<Button href="#quote" variant="outline">
Get a quote
</Button>
</div>
</div>
</section>
<section
id="quote"
className="container mx-auto max-w-2xl py-16 scroll-mt-20"
>
<ContactForm />
</section>
</main>
</div>