diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..50242bb --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.next +node_modules +npm-debug.log +Dockerfile +docker-compose.yml +README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b4069b2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +.next +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +.env +.env.local +.env.production +dist +coverage diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7d24247 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM node:22-alpine AS base +WORKDIR /app + +FROM base AS deps +COPY package.json package-lock.json* ./ +RUN npm install + +FROM base AS dev +ENV NODE_ENV=development +COPY --from=deps /app/node_modules ./node_modules +COPY . . +EXPOSE 3000 +CMD ["npm", "run", "dev", "--", "--hostname", "0.0.0.0"] + +FROM base AS builder +ENV NODE_ENV=production +COPY --from=deps /app/node_modules ./node_modules +COPY . . +RUN npm run build + +FROM node:22-alpine AS runner +WORKDIR /app +ENV NODE_ENV=production +ENV PORT=3000 +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/app/about/page.tsx b/app/about/page.tsx new file mode 100644 index 0000000..617600e --- /dev/null +++ b/app/about/page.tsx @@ -0,0 +1,196 @@ +import Image from "next/image"; +import Link from "next/link"; +import { Breadcrumbs } from "@/components/breadcrumbs"; +import { JsonLd } from "@/components/json-ld"; +import { aboutHighlights, buildStory, siteConfig } from "@/data/site-content"; +import { breadcrumbSchema, buildPageMetadata } from "@/lib/seo"; +import { MotionSection } from "@/components/motion-section"; +import { FadeUp, FadeIn, SlideIn } from "@/components/page-hero-motion"; + +export const metadata = buildPageMetadata({ + title: "About Southern Masonry Supply", + description: + "Learn how Southern Masonry Supply has served Corpus Christi with masonry and landscaping materials since 1990.", + path: "/about", +}); + +export default function AboutPage() { + const breadcrumbs = [ + { name: "Home", path: "/" }, + { name: "About", path: "/about" }, + ]; + + return ( + <> + + +
+
+ +
+
+ +
+
+
+ + Family owned and operated + + +

+ Serving Corpus Christi projects with material knowledge that lasts. +

+
+ +

+ Southern Masonry Supply has spent more than 34 years helping + contractors, homeowners, architects, and designers source the + right masonry and landscaping materials for projects large and + small. +

+
+ +
+ Since 1990 in South Texas + Family-owned: Sid Smith Jr. + Project-grounded recommendations +
+
+
+ + + Southern Masonry Supply heritage tools + + Built for long-horizon projects + + +
+
+ +
+
+
+ {buildStory.map((section, idx) => ( + +
+ {section.eyebrow} +

{section.title}

+

{section.copy}

+
+
+ ))} +
+ +
+ Flagstone pathway and landscaping project +
+
+
+
+ +
+
+ +
+ The Southern Standard +

Why builders trust our yard

+
+
+
+ {aboutHighlights.map((item, idx) => ( + +
+ +

{item.title}

+

{item.description}

+
+
+ ))} +
+
+
+ +
+
+ +
+ Delivery truck for masonry and landscaping orders +
+
+ + Service that stays practical +

+ Our mission is simple: make good material easier to source. +

+

+ Founded in 1990 and led by Sid Smith Jr., Southern Masonry Supply + stays focused on responsive service, reliable stock levels, and + materials worth putting into long-term work. Sid's hands-on + expertise in both masonry and landscaping ensures the yard remains + the southern standard for quality and practical guidance. +

+

+ Whether you are ordering flagstone by the ton, pebbles by the + bag, or masonry cement for a new project phase, our team keeps the + conversation grounded in application, quantity, and timing. +

+
+ + View masonry supplies + + + View landscaping supplies + +
+
+
+
+ + +
+
+
+ Visit or call +

{siteConfig.address.street}

+

+ Stop by the yard during business hours or call{" "} + {siteConfig.phoneDisplay} for material availability and delivery + planning. +

+
+ + Contact us + +
+
+
+ + ); +} diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts new file mode 100644 index 0000000..0bcb753 --- /dev/null +++ b/app/api/contact/route.ts @@ -0,0 +1,65 @@ +import { NextResponse } from "next/server"; + +type ContactPayload = { + name?: string; + phone?: string; + email?: string; + projectType?: string; + materialInterest?: string; + message?: string; +}; + +function isValidEmail(value: string) { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value); +} + +function isValidPhone(value: string) { + return /^[0-9()+.\-\s]{10,}$/.test(value); +} + +export async function POST(request: Request) { + const payload = (await request.json()) as ContactPayload; + const fieldErrors: Record = {}; + + const name = payload.name?.trim() ?? ""; + const phone = payload.phone?.trim() ?? ""; + const email = payload.email?.trim() ?? ""; + const message = payload.message?.trim() ?? ""; + + if (!name) { + fieldErrors.name = "Please enter your full name."; + } + + if (!phone) { + fieldErrors.phone = "Please enter a phone number."; + } else if (!isValidPhone(phone)) { + fieldErrors.phone = "Please enter a valid phone number."; + } + + if (!email) { + fieldErrors.email = "Please enter an email address."; + } else if (!isValidEmail(email)) { + fieldErrors.email = "Please enter a valid email address."; + } + + if (!message) { + fieldErrors.message = "Please describe your project or material request."; + } + + if (Object.keys(fieldErrors).length > 0) { + return NextResponse.json( + { + success: false, + message: "Please correct the highlighted fields and try again.", + fieldErrors, + }, + { status: 400 }, + ); + } + + return NextResponse.json({ + success: true, + message: + "Thanks for reaching out. This form is wired to a placeholder API route and ready for email delivery integration.", + }); +} diff --git a/app/contact/page.tsx b/app/contact/page.tsx new file mode 100644 index 0000000..a73c55e --- /dev/null +++ b/app/contact/page.tsx @@ -0,0 +1,155 @@ +import Image from "next/image"; +import Link from "next/link"; +import { Suspense } from "react"; +import { Breadcrumbs } from "@/components/breadcrumbs"; +import { ContactForm } from "@/components/contact-form"; +import { JsonLd } from "@/components/json-ld"; +import { deliveryHighlights, siteConfig } from "@/data/site-content"; +import { + breadcrumbSchema, + buildPageMetadata, +} from "@/lib/seo"; +import { FadeUp, FadeIn } from "@/components/page-hero-motion"; +import { MotionSection } from "@/components/motion-section"; + +export const metadata = buildPageMetadata({ + title: "Contact Southern Masonry Supply in Corpus Christi, TX", + description: + "Reach Southern Masonry Supply at 5205 Agnes St, Corpus Christi, TX 78405 or call (361) 289-1074 during business hours.", + path: "/contact", + image: "/images/delivery_truck_logistics_png_1773134721043.png", +}); + +export default function ContactPage() { + const breadcrumbs = [ + { name: "Home", path: "/" }, + { name: "Contact", path: "/contact" }, + ]; + + return ( + <> + + +
+
+ +
+
+ +
+
+
+ + Contact and delivery + + +

+ Reach the yard, request a quote, or line up a delivery. +

+
+ +

+ Share the material, quantity, and timing you need. We will get + back with the right next step. +

+
+ +
+ Quotes during business hours + Delivery thresholds made clear upfront + Material-first project guidance +
+
+
+ + + Southern Masonry Supply delivery service + + Call first for stock and routing + + +
+
+ +
+
+
+
+ Send us a message +

Tell us about your project.

+
+ Loading contact form...

}> + +
+
+ +
+
+
+