Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ca671ac7bb | |||
| 822f929ba5 | |||
| 293857d6ab | |||
| ed5e865c54 | |||
| b91b685737 |
@@ -1,75 +1,22 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Halant } from "next/font/google";
|
|
||||||
import { Inter } from "next/font/google";
|
import { Inter } from "next/font/google";
|
||||||
import { Poppins } from "next/font/google";
|
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
import { ServiceWrapper } from "@/components/ServiceWrapper";
|
import "./styles/variables.css";
|
||||||
import Tag from "@/tag/Tag";
|
import "./styles/base.css";
|
||||||
|
|
||||||
const halant = Halant({
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
variable: "--font-halant",
|
|
||||||
subsets: ["latin"],
|
|
||||||
weight: ["300", "400", "500", "600", "700"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const inter = Inter({
|
|
||||||
variable: "--font-inter",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const poppins = Poppins({
|
|
||||||
variable: "--font-poppins",
|
|
||||||
subsets: ["latin"],
|
|
||||||
weight: ["100", "200", "300", "400", "500", "600", "700", "800", "900"],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Hydroseeding Brentwood NH | 5-Star Professional Lawn Service",
|
title: "Fowler's Fine Grass - Premium Hydroseeding in Brentwood NH", description: "Owner-operated hydroseeding specialist serving Brentwood, Exeter, Seacoast NH, Southern Maine & Northern MA. Premium seed blends, expert care, 5-star rated."};
|
||||||
description: "Premium hydroseeding in Brentwood, Exeter & Seacoast NH. Owner-operated, fully insured. Free estimates. Residential & commercial. Thick, healthy lawns guaranteed.",
|
|
||||||
keywords: "hydroseeding Brentwood NH, hydroseeding Exeter NH, hydroseeding Seacoast NH, lawn installation NH, commercial hydroseeding, new construction lawns",
|
|
||||||
metadataBase: new URL("https://fowlersfinegrass.com"),
|
|
||||||
alternates: {
|
|
||||||
canonical: "https://fowlersfinegrass.com",
|
|
||||||
},
|
|
||||||
openGraph: {
|
|
||||||
title: "Fowler's Fine Grass | Professional Hydroseeding NH",
|
|
||||||
description: "5-star rated hydroseeding specialist serving Brentwood, Exeter, and Seacoast NH with premium materials and owner-operated expertise.",
|
|
||||||
url: "https://fowlersfinegrass.com",
|
|
||||||
siteName: "Fowler's Fine Grass LLC",
|
|
||||||
type: "website",
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: "https://fowlersfinegrass.com/og-image.jpg",
|
|
||||||
alt: "Fowler's Fine Grass - Premium Hydroseeding Service",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
twitter: {
|
|
||||||
card: "summary_large_image",
|
|
||||||
title: "Fowler's Fine Grass | Hydroseeding Specialists",
|
|
||||||
description: "Premium hydroseeding service in Brentwood & Exeter, NH. 5-star rated. Call today for a free estimate.",
|
|
||||||
images: ["https://fowlersfinegrass.com/twitter-image.jpg"],
|
|
||||||
},
|
|
||||||
robots: {
|
|
||||||
index: true,
|
|
||||||
follow: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="en" suppressHydrationWarning>
|
<html lang="en">
|
||||||
<ServiceWrapper>
|
<body className={inter.className}>{children}
|
||||||
<body
|
|
||||||
className={`${halant.variable} ${inter.variable} ${poppins.variable} antialiased`}
|
|
||||||
>
|
|
||||||
<Tag />
|
|
||||||
{children}
|
|
||||||
|
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: `
|
__html: `
|
||||||
@@ -1437,7 +1384,6 @@ export default function RootLayout({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</body>
|
</body>
|
||||||
</ServiceWrapper>
|
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
117
src/app/page.tsx
117
src/app/page.tsx
@@ -30,15 +30,36 @@ import {
|
|||||||
Send,
|
Send,
|
||||||
ArrowRight,
|
ArrowRight,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ name: "Home", id: "/" },
|
{ name: "Home", id: "/" },
|
||||||
{ name: "Why Us", id: "#why-us" },
|
{ name: "Why Us", id: "#why-us" },
|
||||||
{ name: "Services", id: "#services" },
|
{ name: "Services", id: "#services" },
|
||||||
|
{ name: "Calculator", id: "#calculator" },
|
||||||
{ name: "Contact", id: "#contact" },
|
{ name: "Contact", id: "#contact" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
|
const [squareFootage, setSquareFootage] = useState("");
|
||||||
|
const [estimate, setEstimate] = useState<number | null>(null);
|
||||||
|
|
||||||
|
const calculateEstimate = () => {
|
||||||
|
if (squareFootage) {
|
||||||
|
const footage = parseFloat(squareFootage);
|
||||||
|
if (!isNaN(footage) && footage > 0) {
|
||||||
|
const costPerSqFt = 0.15;
|
||||||
|
const total = footage * costPerSqFt;
|
||||||
|
setEstimate(total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setSquareFootage("");
|
||||||
|
setEstimate(null);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
defaultButtonVariant="text-shift"
|
defaultButtonVariant="text-shift"
|
||||||
@@ -165,6 +186,102 @@ export default function HomePage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="calculator" data-section="calculator" className="py-20 px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="mx-auto max-w-2xl">
|
||||||
|
<div className="rounded-lg bg-gradient-to-br from-[var(--card)] to-[var(--background-accent)] p-8 shadow-lg">
|
||||||
|
<h2 className="mb-2 text-3xl font-bold text-[var(--foreground)]">
|
||||||
|
Square Footage Calculator
|
||||||
|
</h2>
|
||||||
|
<p className="mb-8 text-[var(--foreground)] opacity-80">
|
||||||
|
Enter your property's square footage to get an instant estimate for hydroseeding costs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label className="mb-3 block text-sm font-medium text-[var(--foreground)]">
|
||||||
|
Square Footage
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
placeholder="Enter square footage (e.g., 5000)"
|
||||||
|
value={squareFootage}
|
||||||
|
onChange={(e) => setSquareFootage(e.target.value)}
|
||||||
|
className="w-full rounded-lg border-2 border-[var(--accent)] bg-[var(--background)] px-4 py-3 text-[var(--foreground)] placeholder-[var(--foreground)] placeholder-opacity-50 focus:outline-none focus:ring-2 focus:ring-[var(--primary-cta)]"
|
||||||
|
/>
|
||||||
|
<p className="mt-2 text-xs text-[var(--foreground)] opacity-60">
|
||||||
|
Don't know your square footage? Measure your lawn's length and width, then multiply them together.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<button
|
||||||
|
onClick={calculateEstimate}
|
||||||
|
className="flex-1 rounded-lg bg-[var(--primary-cta)] px-6 py-3 font-semibold text-[var(--primary-cta-text)] hover:opacity-90 transition-opacity"
|
||||||
|
>
|
||||||
|
Calculate Estimate
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleClear}
|
||||||
|
className="flex-1 rounded-lg border-2 border-[var(--accent)] bg-transparent px-6 py-3 font-semibold text-[var(--foreground)] hover:bg-[var(--accent)] hover:bg-opacity-10 transition-colors"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{estimate !== null && (
|
||||||
|
<div className="rounded-lg border-2 border-[var(--accent)] bg-[var(--background-accent)] bg-opacity-20 p-6">
|
||||||
|
<p className="mb-2 text-sm font-medium text-[var(--foreground)] opacity-75">
|
||||||
|
Estimated Cost
|
||||||
|
</p>
|
||||||
|
<p className="mb-4 text-4xl font-bold text-[var(--primary-cta)]">
|
||||||
|
${estimate.toFixed(2)}
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-[var(--foreground)] opacity-60">
|
||||||
|
Based on $0.15 per square foot. This is an approximate estimate. Call for a precise quote.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="border-t border-[var(--accent)] pt-6">
|
||||||
|
<h3 className="mb-3 font-semibold text-[var(--foreground)]">
|
||||||
|
What's Included:
|
||||||
|
</h3>
|
||||||
|
<ul className="space-y-2 text-sm text-[var(--foreground)]">
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<CheckCircle className="h-4 w-4 text-[var(--primary-cta)]" />
|
||||||
|
Premium seed blend optimized for NH climate
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<CheckCircle className="h-4 w-4 text-[var(--primary-cta)]" />
|
||||||
|
100% biodegradable wood fiber mulch
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<CheckCircle className="h-4 w-4 text-[var(--primary-cta)]" />
|
||||||
|
Slow-release fertilizer for strong growth
|
||||||
|
</li>
|
||||||
|
<li className="flex items-center gap-2">
|
||||||
|
<CheckCircle className="h-4 w-4 text-[var(--primary-cta)]" />
|
||||||
|
Professional site preparation
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<p className="mb-3 text-sm text-[var(--foreground)]">
|
||||||
|
Ready to get started?
|
||||||
|
</p>
|
||||||
|
<Link
|
||||||
|
href="tel:(603)944-5527"
|
||||||
|
className="inline-block rounded-lg bg-[var(--primary-cta)] px-8 py-3 font-semibold text-[var(--primary-cta-text)] hover:opacity-90 transition-opacity"
|
||||||
|
>
|
||||||
|
Call for Free Site Estimate
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="services" data-section="services">
|
<div id="services" data-section="services">
|
||||||
<ProductCardOne
|
<ProductCardOne
|
||||||
title="Our Services"
|
title="Our Services"
|
||||||
|
|||||||
Reference in New Issue
Block a user