Compare commits

..

6 Commits

Author SHA1 Message Date
d0aad0b313 line-clamp-3 removed 2026-06-26 17:03:14 -05:00
2128824c2f other added 2026-06-26 16:38:06 -05:00
b1345e6d4f fixed customer changes 2026-06-26 16:31:39 -05:00
576e6fcf0b bugfixes 2026-06-23 15:00:30 -05:00
a3e0f4b29f label 2026-06-23 13:50:57 -05:00
7aa82f337c remarks 2026-06-23 13:49:32 -05:00
15 changed files with 554 additions and 166 deletions

View File

@@ -7,9 +7,15 @@ services:
- "3040:3000" # Kannst du später sogar löschen, wenn es nur noch über Caddy laufen soll
environment:
- NODE_ENV=production
- SES_SMTP_HOST=${SES_SMTP_HOST:-email-smtp.us-east-2.amazonaws.com}
- SES_SMTP_PORT=${SES_SMTP_PORT:-587}
- SES_SMTP_USER=${SES_SMTP_USER}
- SES_SMTP_PASS=${SES_SMTP_PASS}
- SES_FROM_EMAIL=${SES_FROM_EMAIL:-website@buddelectric.net}
- SES_TO_EMAIL=${SES_TO_EMAIL:-buddelectric@grandecom.net}
networks:
- bizmatch # <-- NEU: Container ins selbe Netz wie Caddy hängen
networks: # <-- NEU: Netzwerk deklarieren
bizmatch:
external: true
external: true

21
package-lock.json generated
View File

@@ -10,12 +10,14 @@
"dependencies": {
"lucide-react": "^0.563.0",
"next": "16.1.6",
"nodemailer": "^9.0.1",
"react": "19.2.3",
"react-dom": "19.2.3"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/nodemailer": "^8.0.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
@@ -1556,6 +1558,16 @@
"undici-types": "~6.21.0"
}
},
"node_modules/@types/nodemailer": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.1.tgz",
"integrity": "sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/react": {
"version": "19.2.13",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz",
@@ -5046,6 +5058,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/nodemailer": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.1.tgz",
"integrity": "sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw==",
"license": "MIT-0",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",

View File

@@ -11,12 +11,14 @@
"dependencies": {
"lucide-react": "^0.563.0",
"next": "16.1.6",
"nodemailer": "^9.0.1",
"react": "19.2.3",
"react-dom": "19.2.3"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/nodemailer": "^8.0.1",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

View File

@@ -1,7 +1,8 @@
import { Shield, CheckCircle2, Award, Clock } from "lucide-react";
import { Shield, Award, Clock } from "lucide-react";
import Link from "next/link";
import Image from "next/image";
import { Metadata } from "next";
import NewspaperClipping from "@/components/NewspaperClipping";
export const metadata: Metadata = {
title: "About Budd Electric Co. | Family-Owned Since 1969",
@@ -37,18 +38,8 @@ export default function AboutUs() {
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-16 items-center">
<div className="relative">
<div className="aspect-[4/3] rounded-lg overflow-hidden bg-gray-100 shadow-xl border-l-8 border-[color:var(--brand)]">
<Image
src="/images/residential.png"
alt="Budd Electric professional electrician team working on residential electrical services"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
className="object-cover"
loading="lazy"
quality={65}
/>
</div>
</div>
<NewspaperClipping />
</div>
<div>
<h2 className="text-sm font-bold tracking-[0.2em] text-[color:var(--brand)] uppercase mb-3">Who We Are</h2>
<h3 className="text-3xl md:text-4xl font-bold text-[color:var(--ink)] font-display mb-6">Three Generations of Excellence</h3>
@@ -65,13 +56,13 @@ export default function AboutUs() {
<span className="text-4xl font-bold text-[color:var(--brand)]">1969</span>
<span className="text-sm font-bold uppercase tracking-wider text-gray-400">Established</span>
</div>
<div className="flex flex-col gap-2">
<span className="text-4xl font-bold text-[color:var(--brand)]">3rd Gen</span>
<span className="text-sm font-bold uppercase tracking-wider text-gray-400">Master Electricians</span>
</div>
<div className="flex flex-col gap-2">
<span className="text-4xl font-bold text-[color:var(--brand)]">3rd Gen</span>
<span className="text-sm font-bold uppercase tracking-wider text-gray-400">Master Electricians</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@@ -0,0 +1,79 @@
import { NextRequest, NextResponse } from "next/server";
import nodemailer from "nodemailer";
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { firstName, lastName, email, phone, serviceType, message } = body;
if (!firstName || typeof firstName !== "string" || firstName.trim().length === 0) {
return NextResponse.json({ error: "First name is required." }, { status: 400 });
}
if (!lastName || typeof lastName !== "string" || lastName.trim().length === 0) {
return NextResponse.json({ error: "Last name is required." }, { status: 400 });
}
if (!email || typeof email !== "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
return NextResponse.json({ error: "A valid email address is required." }, { status: 400 });
}
if (!phone || typeof phone !== "string" || phone.trim().length === 0) {
return NextResponse.json({ error: "Phone number is required." }, { status: 400 });
}
if (!serviceType || typeof serviceType !== "string" || serviceType.trim().length === 0) {
return NextResponse.json({ error: "Please select a service type." }, { status: 400 });
}
if (!message || typeof message !== "string" || message.trim().length === 0) {
return NextResponse.json({ error: "Message is required." }, { status: 400 });
}
const smtpHost = process.env.SES_SMTP_HOST || "email-smtp.us-east-2.amazonaws.com";
const smtpPort = parseInt(process.env.SES_SMTP_PORT || "587", 10);
const smtpUser = process.env.SES_SMTP_USER;
const smtpPass = process.env.SES_SMTP_PASS;
const fromEmail = process.env.SES_FROM_EMAIL || "website@buddelectric.net";
const toEmail = process.env.SES_TO_EMAIL || "buddelectric@grandecom.net";
if (!smtpUser || !smtpPass) {
return NextResponse.json({ error: "Email service is not configured." }, { status: 500 });
}
const transporter = nodemailer.createTransport({
host: smtpHost,
port: smtpPort,
secure: false,
auth: {
user: smtpUser,
pass: smtpPass,
},
});
const serviceTypeLabels: Record<string, string> = {
residential: "Residential Service",
commercial: "Commercial Project",
generator: "Generator Quote",
other: "Other",
};
const htmlBody = `
<h2 style="color:#1e293b;">New Contact Form Submission</h2>
<table style="border-collapse:collapse;width:100%;max-width:600px;">
<tr><td style="padding:8px;border-bottom:1px solid #e2e8f0;font-weight:bold;">Name</td><td style="padding:8px;border-bottom:1px solid #e2e8f0;">${firstName} ${lastName}</td></tr>
<tr><td style="padding:8px;border-bottom:1px solid #e2e8f0;font-weight:bold;">Email</td><td style="padding:8px;border-bottom:1px solid #e2e8f0;">${email}</td></tr>
<tr><td style="padding:8px;border-bottom:1px solid #e2e8f0;font-weight:bold;">Phone</td><td style="padding:8px;border-bottom:1px solid #e2e8f0;">${phone}</td></tr>
<tr><td style="padding:8px;border-bottom:1px solid #e2e8f0;font-weight:bold;">Service Type</td><td style="padding:8px;border-bottom:1px solid #e2e8f0;">${serviceTypeLabels[serviceType] || serviceType}</td></tr>
<tr><td style="padding:8px;font-weight:bold;">Message</td><td style="padding:8px;">${message}</td></tr>
</table>
`;
await transporter.sendMail({
from: fromEmail,
to: toEmail,
replyTo: email,
subject: `New Contact Form Submission from ${firstName} ${lastName}`,
html: htmlBody,
});
return NextResponse.json({ success: true }, { status: 200 });
} catch {
return NextResponse.json({ error: "Failed to send your message. Please try again or call us directly." }, { status: 500 });
}
}

View File

@@ -1,6 +1,7 @@
import { MapPin, Phone, Mail, Clock } from "lucide-react";
import { Metadata } from "next";
import Image from "next/image";
import { MapPin, Phone, Mail, Clock } from "lucide-react";
import { Metadata } from "next";
import Image from "next/image";
import ContactForm from "@/components/ContactForm";
export const metadata: Metadata = {
title: "Contact Budd Electric Co. | Corpus Christi Electrician",
@@ -26,7 +27,7 @@ export default function Contact() {
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10 text-center">
<h1 className="text-4xl md:text-6xl font-bold text-white font-display mb-6">Contact Us</h1>
<p className="text-xl text-gray-400 max-w-2xl mx-auto">
Get in touch for a free quote or schedule a service call today.
Get in touch or schedule a service call today.
</p>
</div>
</section>
@@ -56,7 +57,6 @@ export default function Contact() {
<div>
<h4 className="font-bold text-lg text-[color:var(--ink)]">Call Us</h4>
<p className="text-[color:var(--muted)] text-xl font-bold text-[color:var(--brand)]">(361) 855-2255</p>
<p className="text-sm text-gray-400">24/7 Emergency Support Available</p>
</div>
</div>
@@ -76,7 +76,7 @@ export default function Contact() {
</div>
<div>
<h4 className="font-bold text-lg text-[color:var(--ink)]">Business Hours</h4>
<p className="text-[color:var(--muted)]">Monday - Friday: 8:00 AM - 5:00 PM<br />Saturday & Sunday: Emergency Only</p>
<p className="text-[color:var(--muted)]">Monday - Friday: 8:00 AM - 5:00 PM<br />Saturday & Sunday: Closed</p>
</div>
</div>
</div>
@@ -99,41 +99,7 @@ export default function Contact() {
{/* FORM */}
<div className="bg-white p-10 rounded shadow-2xl border-t-8 border-[color:var(--brand)]">
<h3 className="text-2xl font-bold font-display text-[color:var(--ink)] mb-6">Send us a Message</h3>
<form className="space-y-6">
<div className="grid grid-cols-2 gap-6">
<div className="space-y-2">
<label htmlFor="firstName" className="text-sm font-bold text-gray-700 uppercase tracking-wide">First Name</label>
<input id="firstName" name="firstName" type="text" required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="lastName" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Last Name</label>
<input id="lastName" name="lastName" type="text" required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
</div>
<div className="space-y-2">
<label htmlFor="email" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Email</label>
<input id="email" name="email" type="email" required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="phone" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Phone</label>
<input id="phone" name="phone" type="tel" required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="serviceType" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Service Type</label>
<select id="serviceType" name="serviceType" required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]">
<option value="">Select a service type</option>
<option value="residential">Residential Service</option>
<option value="commercial">Commercial Project</option>
<option value="generator">Generator Quote</option>
<option value="other">Other</option>
</select>
</div>
<div className="space-y-2">
<label htmlFor="message" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Message</label>
<textarea id="message" name="message" rows={4} required className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]"></textarea>
</div>
<button type="submit" className="w-full bg-[color:var(--brand)] text-white font-bold uppercase tracking-widest py-4 rounded hover:bg-[color:var(--brand-strong)] transition shadow-lg">Send Message</button>
</form>
<ContactForm />
</div>
</div>
</div>

View File

@@ -1,12 +1,12 @@
import { Home, Phone, Zap, Factory } from "lucide-react";
import { Home, Zap, Building2 } from "lucide-react";
import Link from "next/link";
import Image from "next/image";
import { ArrowRight } from "lucide-react";
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Electrical Services Corpus Christi | Residential & Commercial",
description: "Professional residential, commercial, and industrial electrical services in Corpus Christi, TX. Licensed electricians for all your electrical needs. Call (361) 855-2255.",
title: "Electrical Services Corpus Christi | Commercial & Residential",
description: "Professional commercial and residential electrical services in Corpus Christi, TX. Licensed electricians for all your electrical needs. Call (361) 855-2255.",
};
export default function Services() {
@@ -28,7 +28,7 @@ export default function Services() {
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10 text-center">
<h1 className="text-4xl md:text-6xl font-bold text-white font-display mb-6">Electrical Services</h1>
<p className="text-xl text-gray-400 max-w-2xl mx-auto">
Comprehensive solutions for every need. Residential, Commercial, and Industrial.
Comprehensive solutions for every need. Commercial and Residential electrical services.
</p>
</div>
</section>
@@ -36,18 +36,18 @@ export default function Services() {
{/* SERVICE LIST */}
<section className="py-24">
<div className="mx-auto max-w-7xl px-6 lg:px-8 space-y-24">
{/* RESIDENTIAL */}
<div id="residential" className="grid lg:grid-cols-2 gap-16 items-center">
{/* COMMERCIAL */}
<div id="commercial" className="grid lg:grid-cols-2 gap-16 items-center scroll-mt-36">
<div className="order-2 lg:order-1">
<div className="w-14 h-14 bg-red-50 text-[color:var(--brand)] rounded flex items-center justify-center mb-6">
<Home size={32} />
<Building2 size={32} />
</div>
<h2 className="text-3xl font-bold text-[color:var(--ink)] font-display mb-6">Residential Services</h2>
<h2 className="text-3xl font-bold text-[color:var(--ink)] font-display mb-6">Commercial Electrical Services</h2>
<p className="text-[color:var(--muted)] text-lg mb-8 leading-relaxed">
Your home is your sanctuary. We ensure it's powered safely and efficiently. From simple outlet repairs to full-home rewiring, no job is too small or too complex.
Serving South Texas for over 50 Years our team has experience, knowledge, skill and expertise in wiring new or existing Office Buildings, Strip Centers, Dental Offices and Medical Facilities as well as making repairs to existing installations.
</p>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{["Service Upgrades", "Safety Inspections", "Lighting Installation", "Ceiling Fans", "Outlet Repair", "Panel Replacement"].map((item, i) => (
{["Commercial New Construction and Renovations", "Lighting and Outlet Repairs", "Electrical System Upgrades", "Automated Lighting Controls", "Backup Generator Installations"].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-gray-700 font-medium">
<span className="w-2 h-2 bg-[color:var(--brand)] rounded-full"></span>
{item}
@@ -56,62 +56,62 @@ export default function Services() {
</ul>
</div>
<div className="order-1 lg:order-2 rounded-lg overflow-hidden shadow-xl aspect-[4/3] bg-gray-100 relative">
<Image
src="/images/residential.png"
alt="Professional residential electrical wiring and home electrical services"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
</div>
</div>
{/* COMMERCIAL */}
<div id="commercial" className="grid lg:grid-cols-2 gap-16 items-center">
<div className="rounded-lg overflow-hidden shadow-xl aspect-[4/3] bg-gray-100 relative">
<Image
src="/images/commercial.png"
alt="Commercial and industrial electrical wiring and services"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
</div>
<div>
<div className="w-14 h-14 bg-red-50 text-[color:var(--brand)] rounded flex items-center justify-center mb-6">
<Factory size={32} />
</div>
<h2 className="text-3xl font-bold text-[color:var(--ink)] font-display mb-6">Commercial & Industrial</h2>
<p className="text-[color:var(--muted)] text-lg mb-8 leading-relaxed">
Keep your business running smoothly with our expert commercial services. We handle everything from new construction build-outs to ongoing maintenance contracts.
</p>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{["New Construction Wiring", "Tenant Build-outs", "Parking Lot Lighting", "Emergency Lighting", "Data Cabling", "Troubleshooting"].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-gray-700 font-medium">
<span className="w-2 h-2 bg-[color:var(--brand)] rounded-full"></span>
{item}
</li>
))}
</ul>
<Image
src="/images/commercial.png"
alt="Commercial electrical wiring and service upgrades"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
</div>
</div>
{/* GENERATORS */}
<div id="generator" className="grid lg:grid-cols-2 gap-16 items-center">
<div className="order-2 lg:order-1">
<div id="generator" className="grid lg:grid-cols-2 gap-16 items-center scroll-mt-36">
<div className="rounded-lg overflow-hidden shadow-xl aspect-[4/3] bg-gray-100 relative">
<Image
src="/images/generator.png"
alt="Kohler whole-home standby generator installation and service"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
</div>
<div>
<div className="w-14 h-14 bg-red-50 text-[color:var(--brand)] rounded flex items-center justify-center mb-6">
<Zap size={32} />
</div>
<h2 className="text-3xl font-bold text-[color:var(--ink)] font-display mb-6">Kohler Generators</h2>
<p className="text-[color:var(--muted)] text-lg mb-8 leading-relaxed">
Don't be left in the dark during a storm. As an authorized Kohler dealer, we sell, install, and service standby generators to keep your power on when the grid goes down.
Don&apos;t be left in the dark during a storm. As an authorized Kohler Dealer we sell, install, and service standby generators to keep your power on when the grid goes down.
</p>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{["Sales & Consultation", "Professional Installation", "Maintenance Plans", "Warranty Service", "Transfer Switch Install"].map((item, i) => (
{["Sales & Consultation", "Turnkey Installation", "Maintenance Plans", "Warranty Service", "Troubleshooting/Repairs"].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-gray-700 font-medium">
<span className="w-2 h-2 bg-[color:var(--brand)] rounded-full"></span>
{item}
</li>
))}
</ul>
</div>
</div>
{/* RESIDENTIAL */}
<div id="residential" className="grid lg:grid-cols-2 gap-16 items-center scroll-mt-36">
<div className="order-2 lg:order-1">
<div className="w-14 h-14 bg-red-50 text-[color:var(--brand)] rounded flex items-center justify-center mb-6">
<Home size={32} />
</div>
<h2 className="text-3xl font-bold text-[color:var(--ink)] font-display mb-6">Residential Electrical Services</h2>
<p className="text-[color:var(--muted)] text-lg mb-8 leading-relaxed">
Your home is your sanctuary. We ensure it is powered safely and efficiently. From simple repairs to wiring a large custom home, no job is too small or too complex.
</p>
<ul className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{["Electrical Service Upgrades", "Lighting and Ceiling Fan Installation", "Outlet Repair and Installation", "Automated Lighting Controls", "Backup Generators", "Panel Replacement"].map((item, i) => (
<li key={i} className="flex items-center gap-3 text-gray-700 font-medium">
<span className="w-2 h-2 bg-[color:var(--brand)] rounded-full"></span>
{item}
@@ -120,19 +120,19 @@ export default function Services() {
</ul>
</div>
<div className="order-1 lg:order-2 rounded-lg overflow-hidden shadow-xl aspect-[4/3] bg-gray-100 relative">
<Image
src="/images/generator.png"
alt="Kohler whole-home standby generator installation and service"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
<Image
src="/images/residential.png"
alt="Professional residential electrical wiring and home electrical services"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
quality={65}
loading="lazy"
className="object-cover"
/>
</div>
</div>
</div>
</section>
</section>
{/* CTA */}
<section className="bg-[color:var(--bg-dark)] py-20 border-t border-white/10">
@@ -140,7 +140,7 @@ export default function Services() {
<h2 className="text-3xl font-bold text-white font-display mb-6">Need a custom solution?</h2>
<p className="text-gray-400 mb-8 max-w-2xl mx-auto">If you don't see the specific service you need listed, give us a call. We likely handle it.</p>
<Link href="/contact-us" className="inline-flex items-center gap-3 bg-[color:var(--brand)] text-white px-8 py-4 font-bold uppercase tracking-widest hover:bg-[color:var(--brand-strong)] transition rounded shadow-lg shadow-red-900/20">
Get a Free Quote <ArrowRight size={20} />
Contact Us Today <ArrowRight size={20} />
</Link>
</div>
</section>

View File

@@ -1,6 +1,6 @@
import Link from "next/link";
import Image from "next/image";
import { ArrowRight, Zap, Shield, Home as HomeIcon, Factory, HardHat, CheckCircle2, Star, Clock, MapPin, Phone } from "lucide-react";
import { ArrowRight, Zap, Shield, Home as HomeIcon, Building2, CheckCircle2, Star, Clock, MapPin, Phone } from "lucide-react";
import ReviewCarousel from "@/components/ReviewCarousel";
import HeroCarousel from "@/components/HeroCarousel";
import FAQSection from "@/components/FAQSection";
@@ -56,16 +56,12 @@ export default function Home() {
</Link>
</div>
<div className="mt-12 mb-16 flex flex-wrap items-center gap-4 md:gap-8 text-sm font-medium text-gray-400">
<div className="flex items-center gap-2">
<CheckCircle2 className="text-[color:var(--brand)]" size={18} />
<span>Licensed & Insured</span>
</div>
<div className="flex items-center gap-2">
<CheckCircle2 className="text-[color:var(--brand)]" size={18} />
<span>24/7 Emergency Support</span>
</div>
</div>
<div className="mt-12 mb-16 flex flex-wrap items-center gap-4 md:gap-8 text-sm font-medium text-gray-400">
<div className="flex items-center gap-2">
<CheckCircle2 className="text-[color:var(--brand)]" size={18} />
<span>Licensed & Insured</span>
</div>
</div>
</div>
<div className="relative hidden lg:block">
@@ -94,31 +90,31 @@ export default function Home() {
<div className="w-14 h-14 bg-white text-[color:var(--brand)] rounded flex items-center justify-center mb-6 shadow-sm border border-gray-100 group-hover:scale-110 transition">
<HomeIcon size={28} />
</div>
<h3 className="text-xl font-bold text-[color:var(--ink)] mb-3 font-display">Residential</h3>
<p className="text-gray-500 mb-6 line-clamp-3">
Complete home electrical services including safety inspections, repairs, lighting, and fan installations.
<h3 className="text-xl font-bold text-[color:var(--ink)] mb-3 font-display">Residential Electrical Services</h3>
<p className="text-gray-500 mb-6">
Complete home electrical services from Outlet Installations or Repairs, Light Fixture/ Ceiling Fan Installations to wiring a new Custom Home.
</p>
<Link href="/electrical-services" className="text-[color:var(--brand)] font-bold uppercase text-xs tracking-widest hover:underline" aria-label="Learn more about Residential services">Residential Services</Link>
<Link href="/electrical-services#residential" className="text-[color:var(--brand)] font-bold uppercase text-xs tracking-widest hover:underline" aria-label="Learn more about Residential services">Residential Services</Link>
</div>
</div>
{/* Card 2 */}
<div className="group bg-[color:var(--bg-dark)] text-white rounded-lg overflow-hidden shadow-2xl hover:shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] transition duration-300 relative transform md:-translate-y-4">
<div className="h-2 bg-[color:var(--brand)] w-0 group-hover:w-full transition-all duration-500"></div>
<div className="absolute top-0 right-0 p-4 opacity-10">
<Zap size={100} />
</div>
<div className="p-8 relative z-10">
<div className="w-14 h-14 bg-[color:var(--brand)] text-white rounded flex items-center justify-center mb-6 shadow-lg group-hover:scale-110 transition">
<Factory size={28} />
</div>
<h3 className="text-xl font-bold text-white mb-3 font-display">Commercial</h3>
<p className="text-gray-400 mb-6">
Reliable power for your business. New construction, maintenance, and industrial-grade solutions.
</p>
<Link href="/electrical-services" className="text-white font-bold uppercase text-xs tracking-widest hover:text-[color:var(--brand)] transition" aria-label="Learn more about Commercial services">Commercial Services</Link>
</div>
</div>
{/* Card 2 */}
<div className="group bg-[color:var(--bg-dark)] text-white rounded-lg overflow-hidden shadow-2xl hover:shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] transition duration-300 relative transform md:-translate-y-4">
<div className="h-2 bg-[color:var(--brand)] w-0 group-hover:w-full transition-all duration-500"></div>
<div className="absolute top-0 right-0 p-4 opacity-10">
<Zap size={100} />
</div>
<div className="p-8 relative z-10">
<div className="w-14 h-14 bg-[color:var(--brand)] text-white rounded flex items-center justify-center mb-6 shadow-lg group-hover:scale-110 transition">
<Building2 size={28} />
</div>
<h3 className="text-xl font-bold text-white mb-3 font-display">Commercial Electrical Services</h3>
<p className="text-gray-400 mb-6">
Complete electrical service for your business from electrical repairs, lighting upgrades, energy compliant lighting controls, to complete electrical system installations for new Commercial Buildings.
</p>
<Link href="/electrical-services#commercial" className="text-white font-bold uppercase text-xs tracking-widest hover:text-[color:var(--brand)] transition" aria-label="Learn more about Commercial services">Commercial Services</Link>
</div>
</div>
{/* Card 3 */}
<div className="group bg-gray-50 border border-gray-100 rounded-lg overflow-hidden hover:shadow-2xl transition duration-300 relative">
@@ -127,11 +123,11 @@ export default function Home() {
<div className="w-14 h-14 bg-white text-[color:var(--brand)] rounded flex items-center justify-center mb-6 shadow-sm border border-gray-100 group-hover:scale-110 transition">
<Zap size={28} />
</div>
<h3 className="text-xl font-bold text-[color:var(--ink)] mb-3 font-display">Generators</h3>
<p className="text-gray-500 mb-6 line-clamp-3">
Authorized Kohler dealer. Keep your lights on when the grid goes down with standby power.
<h3 className="text-xl font-bold text-[color:var(--ink)] mb-3 font-display">Kohler Generators</h3>
<p className="text-gray-500 mb-6">
Authorized Kohler Sales, Installation, and Service Dealer. Keep your lights on when the grid goes down with a new backup Kohler Generator.
</p>
<Link href="/electrical-services" className="text-[color:var(--brand)] font-bold uppercase text-xs tracking-widest hover:underline" aria-label="Learn more about Generator services">Generator Services</Link>
<Link href="/electrical-services#generator" className="text-[color:var(--brand)] font-bold uppercase text-xs tracking-widest hover:underline" aria-label="Learn more about Kohler Generator services">Kohler Generator Services</Link>
</div>
</div>
</div>

View File

@@ -0,0 +1,79 @@
import { Metadata } from "next";
import Image from "next/image";
export const metadata: Metadata = {
title: "Privacy Policy | Budd Electric Co.",
description: "Privacy policy for Budd Electric Co., a family-owned electrical contractor in Corpus Christi, TX. Learn how we collect, use, and protect your information.",
};
export default function PrivacyPolicy() {
return (
<div className="bg-[color:var(--bg)]">
{/* PAGE HERO */}
<section className="bg-[color:var(--bg-dark)] py-20 relative overflow-hidden -mt-20 pt-44">
<div className="absolute inset-0 opacity-10">
<Image
src="/images/hero-bg.png"
alt=""
fill
priority
quality={40}
sizes="100vw"
className="object-cover object-center"
/>
</div>
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10 text-center">
<h1 className="text-4xl md:text-6xl font-bold text-white font-display mb-6">Privacy Policy</h1>
<p className="text-xl text-gray-400 max-w-2xl mx-auto">
Last updated: June 23, 2026
</p>
</div>
</section>
{/* CONTENT */}
<section className="py-24">
<div className="mx-auto max-w-3xl px-6 lg:px-8">
<div className="prose prose-lg max-w-none text-[color:var(--muted)] space-y-8">
<p>
Budd Electric Co. (&ldquo;we,&rdquo; &ldquo;us,&rdquo; or &ldquo;our&rdquo;) respects your privacy. This policy explains what information we collect through our website, how we use it, and your choices.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Information We Collect</h2>
<p>
We collect the information you voluntarily provide through our contact form, such as your name, email address, phone number, selected service type, and any message details. We may also collect basic technical information automatically, such as your browser type and general usage data, to help us operate and improve the site.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">How We Use Your Information</h2>
<p>
We use the information you submit solely to respond to your inquiries, provide quotes, schedule service, and communicate with you about our electrical services. We do not sell or rent your personal information to third parties.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Sharing of Information</h2>
<p>
We may share information only with trusted service providers who help us operate our website and email communications (for example, our email delivery provider), and only as needed to provide those services. We may disclose information if required by law.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Data Retention</h2>
<p>
We retain contact submissions only as long as necessary to respond to your request and for our normal business records.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Your Choices</h2>
<p>
You may contact us at any time to ask what information we hold about you or to request that we delete it.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Contact Us</h2>
<p>
If you have any questions about this Privacy Policy, contact us at <a href="mailto:buddelectric@grandecom.net" className="text-[color:var(--brand)] hover:underline">buddelectric@grandecom.net</a> or <a href="tel:+13618552255" className="text-[color:var(--brand)] hover:underline">(361) 855-2255</a>.
</p>
<p className="italic text-sm text-gray-400 mt-12 border-t border-gray-200 pt-8">
This policy is provided for general informational purposes and does not constitute legal advice. Budd Electric Co. recommends reviewing it with a qualified attorney.
</p>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,79 @@
import { Metadata } from "next";
import Image from "next/image";
export const metadata: Metadata = {
title: "Terms of Service | Budd Electric Co.",
description: "Terms of service for the Budd Electric Co. website. Family-owned electrical contractor in Corpus Christi, TX since 1969.",
};
export default function TermsOfService() {
return (
<div className="bg-[color:var(--bg)]">
{/* PAGE HERO */}
<section className="bg-[color:var(--bg-dark)] py-20 relative overflow-hidden -mt-20 pt-44">
<div className="absolute inset-0 opacity-10">
<Image
src="/images/hero-bg.png"
alt=""
fill
priority
quality={40}
sizes="100vw"
className="object-cover object-center"
/>
</div>
<div className="mx-auto max-w-7xl px-6 lg:px-8 relative z-10 text-center">
<h1 className="text-4xl md:text-6xl font-bold text-white font-display mb-6">Terms of Service</h1>
<p className="text-xl text-gray-400 max-w-2xl mx-auto">
Last updated: June 23, 2026
</p>
</div>
</section>
{/* CONTENT */}
<section className="py-24">
<div className="mx-auto max-w-3xl px-6 lg:px-8">
<div className="prose prose-lg max-w-none text-[color:var(--muted)] space-y-8">
<p>
These Terms of Service (&ldquo;Terms&rdquo;) govern your use of the Budd Electric Co. website. By accessing or using this site, you agree to these Terms.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Use of the Website</h2>
<p>
This website is provided for informational purposes to learn about Budd Electric Co.&rsquo;s electrical services and to contact us. You agree to use the site only for lawful purposes.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">No Guarantee of Service</h2>
<p>
Submitting a contact form or request does not create a binding agreement for services. All electrical work is subject to a separate written estimate and agreement. Pricing, availability, and scheduling are confirmed directly with our team.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Intellectual Property</h2>
<p>
All content on this website, including text, logos, and images, is the property of Budd Electric Co. or its licensors and may not be reproduced without permission.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Disclaimer of Warranties</h2>
<p>
This website is provided &ldquo;as is&rdquo; without warranties of any kind. We do not guarantee that the site will be uninterrupted or error-free.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Limitation of Liability</h2>
<p>
Budd Electric Co. is not liable for any indirect or incidental damages arising from your use of this website.
</p>
<h2 className="text-2xl font-bold text-[color:var(--ink)] font-display mt-12">Contact</h2>
<p>
Questions about these Terms can be directed to <a href="mailto:buddelectric@grandecom.net" className="text-[color:var(--brand)] hover:underline">buddelectric@grandecom.net</a> or <a href="tel:+13618552255" className="text-[color:var(--brand)] hover:underline">(361) 855-2255</a>.
</p>
<p className="italic text-sm text-gray-400 mt-12 border-t border-gray-200 pt-8">
These Terms are provided for general informational purposes and do not constitute legal advice. Budd Electric Co. recommends reviewing them with a qualified attorney.
</p>
</div>
</div>
</section>
</div>
);
}

View File

@@ -0,0 +1,95 @@
"use client";
import { useState } from "react";
export default function ContactForm() {
const [formData, setFormData] = useState({
firstName: "",
lastName: "",
email: "",
phone: "",
serviceType: "",
message: "",
});
const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle");
const [statusMessage, setStatusMessage] = useState("");
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value }));
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setStatus("loading");
setStatusMessage("");
try {
const res = await fetch("/api/contact", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData),
});
const data = await res.json();
if (res.ok) {
setStatus("success");
setStatusMessage("Thank you! Your message has been sent. We'll get back to you shortly.");
setFormData({ firstName: "", lastName: "", email: "", phone: "", serviceType: "", message: "" });
} else {
setStatus("error");
setStatusMessage(data.error || "Something went wrong. Please try again.");
}
} catch {
setStatus("error");
setStatusMessage("Network error. Please check your connection and try again.");
}
};
return (
<form className="space-y-6" onSubmit={handleSubmit}>
<div className="grid grid-cols-2 gap-6">
<div className="space-y-2">
<label htmlFor="firstName" className="text-sm font-bold text-gray-700 uppercase tracking-wide">First Name</label>
<input id="firstName" name="firstName" type="text" required value={formData.firstName} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="lastName" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Last Name</label>
<input id="lastName" name="lastName" type="text" required value={formData.lastName} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
</div>
<div className="space-y-2">
<label htmlFor="email" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Email</label>
<input id="email" name="email" type="email" required value={formData.email} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="phone" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Phone</label>
<input id="phone" name="phone" type="tel" required value={formData.phone} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]" />
</div>
<div className="space-y-2">
<label htmlFor="serviceType" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Service Type</label>
<select id="serviceType" name="serviceType" required value={formData.serviceType} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]">
<option value="">Select a service type</option>
<option value="commercial">Commercial Project</option>
<option value="residential">Residential Project</option>
<option value="generator">Generator Inquiry</option>
<option value="other">Other</option>
</select>
</div>
<div className="space-y-2">
<label htmlFor="message" className="text-sm font-bold text-gray-700 uppercase tracking-wide">Message</label>
<textarea id="message" name="message" rows={4} required value={formData.message} onChange={handleChange} className="w-full bg-gray-50 border border-gray-200 p-3 rounded focus:outline-none focus:border-[color:var(--brand)] focus:ring-1 focus:ring-[color:var(--brand)]"></textarea>
</div>
{status === "success" && (
<div className="p-3 bg-green-50 border border-green-200 rounded text-green-700 text-sm">{statusMessage}</div>
)}
{status === "error" && (
<div className="p-3 bg-red-50 border border-red-200 rounded text-red-700 text-sm">{statusMessage}</div>
)}
<button type="submit" disabled={status === "loading"} className="w-full bg-[color:var(--brand)] text-white font-bold uppercase tracking-widest py-4 rounded hover:bg-[color:var(--brand-strong)] transition shadow-lg disabled:opacity-50 disabled:cursor-not-allowed">
{status === "loading" ? "Sending..." : "Send Message"}
</button>
</form>
);
}

View File

@@ -219,8 +219,8 @@ export default function Footer() {
<div className="border-t border-white/5 pt-8 flex flex-col md:flex-row justify-between items-center text-gray-500 text-xs uppercase tracking-wider">
<p>&copy; {new Date().getFullYear()} Budd Electric Co. TECL #17007</p>
<div className="flex gap-6 mt-4 md:mt-0">
<Link href="https://www.thryv.com/client-privacy-policy/" target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">Privacy Policy</Link>
<Link href="https://www.thryv.com/client-terms-of-use/" target="_blank" rel="noopener noreferrer" className="hover:text-white transition-colors">Terms of Service</Link>
<Link href="/privacy-policy" className="hover:text-white transition-colors">Privacy Policy</Link>
<Link href="/terms-of-service" className="hover:text-white transition-colors">Terms of Service</Link>
</div>
</div>
</div>

View File

@@ -45,7 +45,7 @@ export default function Header() {
href="/contact-us"
className="hidden lg:flex items-center gap-2 rounded bg-[color:var(--brand)] px-5 py-2.5 text-sm font-bold text-white shadow-lg shadow-red-900/20 transition hover:bg-[color:var(--brand-strong)] uppercase tracking-wider"
>
Free Quote
Contact Us
<ArrowRight size={14} strokeWidth={3} />
</Link>
<button
@@ -117,7 +117,7 @@ export default function Header() {
onClick={() => setMobileMenuOpen(false)}
className="flex items-center justify-center gap-2 rounded bg-[color:var(--brand)] px-7 py-4 text-sm font-bold text-white shadow-lg shadow-red-900/20 transition hover:bg-[color:var(--brand-strong)] hover:shadow-red-900/40 uppercase tracking-wider w-full"
>
Get a Quote
Contact Us
<ArrowRight size={16} strokeWidth={3} />
</Link>
</div>

View File

@@ -0,0 +1,74 @@
"use client";
import { useState, useEffect, useCallback } from "react";
import Image from "next/image";
import { X } from "lucide-react";
export default function NewspaperClipping() {
const [open, setOpen] = useState(false);
const close = useCallback(() => setOpen(false), []);
useEffect(() => {
if (!open) return;
const handleKey = (e: KeyboardEvent) => {
if (e.key === "Escape") close();
};
document.addEventListener("keydown", handleKey);
document.body.style.overflow = "hidden";
return () => {
document.removeEventListener("keydown", handleKey);
document.body.style.overflow = "";
};
}, [open, close]);
return (
<>
<div
className="aspect-[4/3] rounded-lg overflow-hidden bg-gray-100 shadow-xl border-l-8 border-[color:var(--brand)] cursor-pointer group relative"
onClick={() => setOpen(true)}
>
<Image
src="/images/newspaper.webp"
alt="Budd Electric Co. featured in the local newspaper"
fill
sizes="(max-width: 1024px) 100vw, 50vw"
className="object-contain p-3 group-hover:scale-105 transition-transform duration-300"
loading="lazy"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/10 transition-colors flex items-center justify-center">
<span className="text-white text-sm font-bold opacity-0 group-hover:opacity-100 transition-opacity bg-black/60 px-4 py-2 rounded">Click to enlarge</span>
</div>
</div>
<p className="mt-3 text-center text-sm text-gray-400 italic">Featured in the local press</p>
{open && (
<div
className="fixed inset-0 z-50 bg-black/85 flex items-center justify-center p-4 md:p-8"
onClick={close}
>
<button
onClick={close}
className="absolute top-4 right-4 text-white/80 hover:text-white transition-colors z-10"
aria-label="Close"
>
<X size={36} strokeWidth={2} />
</button>
<div
className="relative max-w-5xl w-full max-h-[90vh]"
onClick={(e) => e.stopPropagation()}
>
<Image
src="/images/newspaper.webp"
alt="Budd Electric Co. featured in the local newspaper"
width={1600}
height={1200}
className="object-contain w-full h-full max-h-[90vh]"
unoptimized
/>
</div>
</div>
)}
</>
);
}