diff --git a/.agents/product-marketing-context.md b/.agents/product-marketing-context.md
new file mode 100644
index 0000000..c933921
--- /dev/null
+++ b/.agents/product-marketing-context.md
@@ -0,0 +1,166 @@
+# Product Marketing Context
+
+*Last updated: 2026-03-25*
+
+## Product Overview
+**One-liner:** Bay Area IT is a local managed IT and business technology partner for small and mid-sized businesses in Corpus Christi and the Coastal Bend.
+
+**What it does:** The company provides ongoing IT support, help desk, network infrastructure, business email, device support, security basics, backups, and related technology services for local businesses. It also offers adjacent services such as web design, shared drive setup, printer/scanner installation, and hardware procurement. The positioning throughout the site emphasizes reliable day-to-day operations, fast support, and a local partner that can help remotely or on-site.
+
+**Product category:** Managed IT services, IT support, outsourced IT support, IT help desk, business technology services for SMBs.
+
+**Product type:** Local B2B service business.
+
+**Business model:** Service-led business with monthly recurring support plans plus project-based services. Pricing signals on the site suggest transparent monthly pricing for support and per-unit pricing for some offers (example: business email at `$5` per inbox). Primary conversion is a free 20-minute assessment / consultation.
+
+## Target Audience
+**Target companies:** Small and mid-sized businesses in Corpus Christi and the broader Coastal Bend, including Portland, Rockport, Aransas Pass, Kingsville, and Port Aransas. Strong fit for offices, service businesses, healthcare-related practices, growing teams, and companies without a full in-house IT department.
+
+**Decision-makers:** Business owners, office managers, operations leaders, and IT-responsible managers at SMBs. Secondary audiences likely include executive assistants, practice managers, and internal technical contacts who influence vendor selection.
+
+**Primary use case:** Outsource day-to-day IT management so the business can reduce downtime, improve security, and keep employees productive without building a full internal IT team.
+
+**Jobs to be done:**
+- Keep our systems, email, devices, Wi-Fi, and users working reliably every day.
+- Give employees a clear support channel so small issues stop turning into business delays.
+- Put practical security, backup, and monitoring in place without overcomplicating the environment.
+
+**Use cases:**
+- Ongoing managed IT support for SMBs without in-house IT
+- Remote-first help desk with on-site escalation when needed
+- Business email setup, migration, and support
+- Network cleanup, Wi-Fi improvement, firewall/router/switch management
+- New user onboarding, device setup, and account/access support
+- Web design and domain/DNS support for small local businesses
+
+## Personas
+| Persona | Cares about | Challenge | Value we promise |
+|---------|-------------|-----------|------------------|
+| Business owner / President | Predictable costs, fewer disruptions, trust in provider, fast escalation | They are tired of acting as part-time IT and losing time to avoidable issues | We take IT ownership off their plate with clear communication, local accountability, and practical support |
+| Office manager / Operations lead | Employee productivity, quick fixes, simple process, dependable vendor | Staff lose time to recurring tickets, login issues, printer/email/network friction | We give your team a responsive help desk and structured support workflow that keeps work moving |
+| Practice manager / Admin lead | Reliability, compliance-adjacent security basics, smooth communication systems | Email, devices, and access issues disrupt client or patient-facing work | We stabilize the environment and implement simple security and backup foundations |
+| Internal technical contact | Competence, clean implementation, sane network/security setup | They need outside help without inheriting chaos or vague recommendations | We provide hands-on implementation, monitoring, and support without unnecessary complexity |
+| Financial buyer | Cost control, ROI, avoiding headcount, lower risk | Hiring full-time IT is expensive and overkill for many SMBs | Outsourced IT gives predictable monthly pricing and broader coverage than a single in-house hire |
+
+## Problems & Pain Points
+**Core problem:** Business technology has become unpredictable, reactive, and distracting. Employees hit avoidable issues, support requests pile up, and owners or managers end up spending time managing IT instead of running the business.
+
+**Why alternatives fall short:**
+- Break-fix support is reactive and does not create ongoing stability
+- Remote-only national providers can feel slow, generic, and disconnected from local urgency
+- A single in-house generalist is expensive and may not cover the full range of needs
+- DIY setups for email, networking, security, and backups create hidden fragility
+
+**What it costs them:** Lost productivity, downtime, delayed customer response, missed emails, security exposure, recurring employee frustration, and management time pulled away from growth.
+
+**Emotional tension:** Frustration, lack of confidence in systems, fear of outages or security incidents, and fatigue from being forced to “figure IT out” internally.
+
+## Competitive Landscape
+**Direct:** Local MSPs and IT support providers in Corpus Christi / Coastal Bend — often positioned similarly on help desk, managed IT, and outsourced support; likely to fall short on responsiveness, communication clarity, or service breadth if they are inconsistent.
+
+**Secondary:** Freelance IT technicians, break-fix computer repair shops, and one-person outsourced support providers — cheaper upfront but often reactive, less structured, and weaker on ongoing monitoring, security baselines, and business process support.
+
+**Indirect:** Hiring an internal IT employee, relying on a tech-savvy office employee, or using vendor support from Microsoft/Google/ISP/hardware providers — these options are fragmented, slower for cross-system problems, and usually do not provide clear ownership of the full environment.
+
+## Differentiation
+**Key differentiators:**
+- Local provider based in Corpus Christi with regional service coverage
+- Remote-first support with on-site availability when needed
+- Broad business technology scope: help desk, email, networking, devices, security basics, backups, web, DNS/domain support
+- Clear, practical positioning instead of overly technical jargon
+- Free 20-minute assessment as a low-friction first step
+
+**How we do it differently:** We position the company as a local IT partner that combines fast support, hands-on implementation, and practical business judgment. The site consistently emphasizes reliable operations, simple explanations, and support that fits SMB reality rather than enterprise complexity.
+
+**Why that's better:** SMB buyers get one accountable partner, faster issue resolution, lower management overhead, and support that balances remote speed with local presence.
+
+**Why customers choose us:** They want predictable help, local accountability, straightforward communication, and a provider who can support everyday business operations instead of only isolated technical tasks.
+
+## Objections
+| Objection | Response |
+|-----------|----------|
+| “We’re too small to need managed IT.” | Small businesses are often the most disrupted by recurring tech issues because they have less internal coverage. Outsourced support gives you structure and expertise without hiring a full-time team. |
+| “We already have someone who helps with IT.” | That can work until issues span email, networking, security, users, and vendors at the same time. We provide broader coverage, clearer ownership, and ongoing support instead of ad hoc fixes. |
+| “A remote provider or break-fix shop is cheaper.” | Lower upfront cost usually means slower response, less accountability, and more recurring issues. The site’s positioning is around reducing downtime and management distraction, not just closing tickets cheaply. |
+
+**Anti-persona:** Large enterprises with internal IT departments and complex procurement, buyers shopping only on the lowest hourly rate, and organizations that want purely transactional break-fix work with no ongoing relationship.
+
+## Switching Dynamics
+**Push:** Recurring downtime, slow systems, unresolved support tickets, weak Wi-Fi, email problems, unclear ownership, and security/backups that feel too risky to ignore.
+
+**Pull:** Local support, fast response, clear communication, monthly support options, practical security baseline, and an easy first step via a free assessment.
+
+**Habit:** Existing vendor relationships, internal workarounds, “good enough” support, reluctance to document the current environment, and the inertia of staying reactive.
+
+**Anxiety:** Fear of disruption during migration, concern about cost, worry that the new provider will overcomplicate things, and uncertainty about whether a local MSP will actually be more responsive.
+
+## Customer Language
+**How they describe the problem:**
+- “The internet is slow.”
+- “The system is glitchy.”
+- “Our email stopped working.”
+- “Support requests never end.”
+- “I’m tired of playing part-time IT.”
+- “We need reliable IT without hiring in-house staff.”
+
+**How they describe us:**
+- “Local IT support”
+- “Outsourced IT support”
+- “Fast remote assistance with on-site support when needed”
+- “Reliable IT partner”
+- “Help desk for employees”
+
+**Words to use:** reliable, local, fast response, outsourced IT support, help desk, remote support, on-site when needed, security baseline, backup monitoring, predictable monthly pricing, practical, clear, business-focused.
+
+**Words to avoid:** revolutionary, cutting-edge for its own sake, AI-first, disruption, synergy, enterprise transformation, generic “digital innovation” language.
+
+**Glossary:**
+| Term | Meaning |
+|------|---------|
+| Managed IT / ongoing IT support | Recurring support relationship covering maintenance, issue resolution, and operational stability |
+| Help desk | Day-to-day employee support for access, software, device, and common IT issues |
+| Security baseline | Practical protection measures like MFA, patching, endpoint protection, and backup basics |
+| Remote-first support | Resolving most issues quickly without waiting for an on-site visit |
+| On-site support | Physical support for hardware, installations, and network troubleshooting when required |
+
+## Brand Voice
+**Tone:** Professional, direct, practical, reassuring.
+
+**Style:** Conversational but credible. Explains technical work in business terms. Avoids jargon-heavy positioning and stays grounded in outcomes like uptime, productivity, and reliability.
+
+**Personality:** Local, dependable, clear, experienced, no-nonsense.
+
+## Proof Points
+**Metrics:**
+- 25+ years serving the region appears repeatedly across location/service pages
+- 30+ local businesses supported appears across multiple pages
+- 99.9% uptime and `<2 min` response time appear on the About page
+- Assessments can begin within 48 hours
+- 24/7 emergency support / monitoring is referenced in contact and CTA copy
+
+**Customers:** No named logos surfaced in the repo copy reviewed. The site references local businesses across the Coastal Bend rather than public logos.
+
+**Testimonials:**
+> No direct testimonial quotes were found in the repo sections reviewed. Add real customer quotes here when available.
+
+**Value themes:**
+| Theme | Proof |
+|-------|-------|
+| Local trust | Corpus Christi address, repeated local positioning, service-area pages for Coastal Bend cities |
+| Reliability | 99.9% uptime claim, remote-first help desk, proactive maintenance and monitoring language |
+| Experience | 25+ years claim across pages; long-standing regional presence |
+| Business fit | Positioning for small and mid-sized businesses without in-house IT |
+| Speed | Fast response, emergency support, assessments within 48 hours |
+
+## Goals
+**Business goal:** Generate qualified local SMB leads for managed IT, help desk, business email, networking, and related technology services.
+
+**Conversion action:** Book a free 20-minute assessment / consultation or submit a contact inquiry / call the office.
+
+**Current metrics:** Not fully established from the repo alone. Repo signals include claims around 30+ businesses supported, 99.9% uptime, fast response, and 48-hour assessment turnaround. Customer-count references conflict in the codebase and should be normalized before using in external collateral.
+
+## Open Questions / Conflicts To Resolve
+- Brand name is inconsistent: `Bay Area Affiliates`, `Bay Area IT`, and `Bay Area IT Services` all appear in the repo.
+- Customer count is inconsistent: some pages say `30+ local businesses`, while `AboutPage` also says `over 150 businesses`.
+- Founding timeline is inconsistent: timeline starts in `2000`, but hero/about copy also says `Since 2010`.
+- Pricing clarity is partial: one service has explicit `$5 per inbox` pricing, while broader managed IT pricing is only described as transparent monthly pricing.
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..20c690b
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,15 @@
+.git
+.gitignore
+.agents
+node_modules
+dist
+*.log
+Dockerfile
+docker-compose.yml
+README.md
+*.md
+bullet
+ellipsis
+em
+left
+right
diff --git a/.gitignore b/.gitignore
index a547bf3..4108b33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,24 @@
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
-
-node_modules
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/App.tsx b/App.tsx
index dff70be..93d049c 100644
--- a/App.tsx
+++ b/App.tsx
@@ -1,65 +1,93 @@
-import React, { useEffect } from 'react';
-import { BrowserRouter as Router, Routes, Route, useLocation } from 'react-router-dom';
-import Lenis from '@studio-freight/lenis';
+import React, { Suspense, useEffect, useRef } from 'react';
+import { BrowserRouter as Router, Routes, Route, Navigate, useLocation } from 'react-router-dom';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import { ScrollToPlugin } from 'gsap/ScrollToPlugin';
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import BackToTop from './components/BackToTop';
-import HomePage from './src/pages/HomePage';
-import AboutPage from './src/pages/AboutPage';
-import ServicesPage from './src/pages/ServicesPage';
-import BlogPage from './src/pages/BlogPage';
-import ContactPage from './src/pages/ContactPage';
-import LocationPage from './src/pages/LocationPage';
-import ServicePage from './src/pages/ServicePage';
-import BlogPostPage from './src/pages/BlogPostPage';
-import { locationData, serviceData, blogPostData } from './src/data/seoData';
+import { BlogSeoRoute, LocationSeoRoute, ServiceSeoRoute, blogRoutes, locationRoutes, serviceRoutes, legacyRedirects } from './src/routes/seoRoutes';
// Register GSAP plugins globally
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
+import HomePage from './src/pages/HomePage';
+const AboutPage = React.lazy(() => import('./src/pages/AboutPage'));
+const ServicesPage = React.lazy(() => import('./src/pages/ServicesPage'));
+const BlogPage = React.lazy(() => import('./src/pages/BlogPage'));
+const ContactPage = React.lazy(() => import('./src/pages/ContactPage'));
+const LocationsPage = React.lazy(() => import('./src/pages/LocationsPage'));
+const PrivacyPolicyPage = React.lazy(() => import('./src/pages/PrivacyPolicyPage'));
+const TermsOfServicePage = React.lazy(() => import('./src/pages/TermsOfServicePage'));
+
// Grain Overlay Component
const GrainOverlay = () => (
);
+const RouteFallback = () => (
+
+ Loading page...
+
+);
+
const AppContent: React.FC = () => {
const location = useLocation();
+ const lenisRef = useRef(null);
useEffect(() => {
- // Initialize Lenis for smooth scrolling
- const lenis = new Lenis({
- duration: 1.2,
- easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
- direction: 'vertical',
- gestureDirection: 'vertical',
- smooth: true,
- smoothTouch: false,
- touchMultiplier: 2,
- } as any);
+ if (typeof window === 'undefined') {
+ return;
+ }
- // Synchronize Lenis with GSAP ScrollTrigger
- lenis.on('scroll', ScrollTrigger.update);
+ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
+ const finePointer = window.matchMedia('(pointer: fine) and (hover: hover)');
- const ticker = (time: number) => {
- lenis.raf(time * 1000);
- };
+ if (prefersReducedMotion.matches || !finePointer.matches) {
+ return;
+ }
- // Use GSAP ticker for smoother animation loop integration
- gsap.ticker.add(ticker);
+ let active = true;
+ let ticker: ((time: number) => void) | null = null;
- // Disable lag smoothing to prevent jumps
- gsap.ticker.lagSmoothing(0);
+ void import('@studio-freight/lenis').then(({ default: Lenis }) => {
+ if (!active) {
+ return;
+ }
- // Reset scroll on route change
- lenis.scrollTo(0, { immediate: true });
+ const lenis = new Lenis({
+ duration: 1.2,
+ easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
+ direction: 'vertical',
+ gestureDirection: 'vertical',
+ smooth: true,
+ smoothTouch: false,
+ touchMultiplier: 2,
+ } as any);
+
+ lenisRef.current = lenis;
+ lenis.on('scroll', ScrollTrigger.update);
+
+ ticker = (time: number) => {
+ lenis.raf(time * 1000);
+ };
+
+ gsap.ticker.add(ticker);
+ gsap.ticker.lagSmoothing(0);
+ });
return () => {
- gsap.ticker.remove(ticker);
- lenis.destroy();
+ active = false;
+ if (ticker) {
+ gsap.ticker.remove(ticker);
+ }
+ lenisRef.current?.destroy();
+ lenisRef.current = null;
};
+ }, []);
+
+ useEffect(() => {
+ lenisRef.current?.scrollTo(0, { immediate: true });
}, [location.pathname]);
return (
@@ -67,40 +95,55 @@ const AppContent: React.FC = () => {
-
- } />
- } />
- } />
- } />
- } />
+ }>
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
- {/* SEO Location Pages */}
- {locationData.map((data) => (
- }
- />
- ))}
+ {/* SEO Location Pages */}
+ {locationRoutes.map((data) => (
+
+ }
+ />
+
+ ))}
- {/* SEO Service Pages */}
- {serviceData.map((data) => (
- }
- />
- ))}
+ {/* SEO Service Pages */}
+ {serviceRoutes.map((data) => (
+
+ }
+ />
+
+ ))}
- {/* Authority Blog Posts */}
- {blogPostData.map((data) => (
- }
- />
- ))}
-
+ {/* Authority Blog Posts */}
+ {blogRoutes.map((data) => (
+
+ }
+ />
+
+ ))}
+
+ {/* Legacy URL redirects — preserve old flat URLs */}
+ {legacyRedirects.map(({ from, to }) => (
+
+ } />
+
+ ))}
+
+
@@ -114,4 +157,4 @@ export default function App() {
);
-}
\ No newline at end of file
+}
diff --git a/Caddyfile b/Caddyfile
new file mode 100644
index 0000000..7a84d94
--- /dev/null
+++ b/Caddyfile
@@ -0,0 +1,22 @@
+# Caddy inside the Docker container — listens on :80
+# The host Caddy reverse-proxies to this container and handles HTTPS.
+:80 {
+ root * /srv
+ encode zstd gzip
+
+ header {
+ X-Content-Type-Options nosniff
+ X-Frame-Options DENY
+ Referrer-Policy strict-origin-when-cross-origin
+ Permissions-Policy "geolocation=(), microphone=(), camera=()"
+ -Server
+ }
+
+ # Long-term caching for hashed assets
+ @assets path /assets/* /images/* /logo.svg /public/*
+ header @assets Cache-Control "public, max-age=31536000, immutable"
+
+ # SPA fallback: prerendered routes get their own index.html, rest falls back
+ try_files {path} {path}/index.html /index.html
+ file_server
+}
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..450db82
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,18 @@
+FROM node:22-alpine AS build
+
+WORKDIR /app
+
+COPY package*.json ./
+RUN npm ci
+
+COPY . .
+RUN npm run build
+
+FROM caddy:2.8-alpine
+
+COPY Caddyfile /etc/caddy/Caddyfile
+COPY --from=build /app/dist /srv
+
+EXPOSE 80
+
+CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
diff --git a/README.md b/README.md
index 54f3a1a..b8b70f6 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,293 @@
-# Bay Area Affiliates
+# Bay Area IT — Website
-Ein modernes React-Projekt erstellt mit Vite, TypeScript und Framer Motion.
+Marketing website for **Bay Area IT**, an IT service provider based in Corpus Christi, TX.
+Built with React 19, Vite 6, TypeScript, and Tailwind CSS. Deployed as a static site served by Caddy inside Docker.
-## Voraussetzungen
+---
-- Node.js (Version 18 oder höher empfohlen)
-- npm (wird mit Node.js installiert)
+## Table of Contents
-## Installation
+- [Tech Stack](#tech-stack)
+- [Project Structure](#project-structure)
+- [Local Development](#local-development)
+- [Build & Preview](#build--preview)
+- [Deployment (Docker + Caddy)](#deployment-docker--caddy)
+- [Adding Content](#adding-content)
+- [Scripts Reference](#scripts-reference)
-Klone das Repository und installiere die Abhängigkeiten:
+---
-```bash
-npm install
+## Tech Stack
+
+| Layer | Technology |
+|---|---|
+| UI Framework | React 19 |
+| Build Tool | Vite 6 |
+| Language | TypeScript 5 |
+| Styling | Tailwind CSS 3 |
+| Routing | React Router 7 |
+| Animations | Framer Motion 12, GSAP 3 |
+| Smooth Scroll | Lenis |
+| Web Server | Caddy 2 (inside Docker) |
+| Containerization | Docker + Docker Compose |
+
+---
+
+## Project Structure
+
+```
+bayarea/
+├── components/ # Shared UI components
+│ ├── Navbar.tsx
+│ ├── Footer.tsx
+│ ├── Hero.tsx
+│ ├── Services.tsx
+│ ├── Blog.tsx
+│ ├── CTA.tsx
+│ ├── Testimonials.tsx
+│ ├── Process.tsx
+│ ├── AreasWeServe.tsx
+│ ├── SEO.tsx # Head/meta tag injection
+│ ├── Breadcrumb.tsx
+│ └── LoadingScreen.tsx
+├── src/
+│ ├── pages/ # Route-level page components
+│ │ ├── HomePage.tsx
+│ │ ├── AboutPage.tsx
+│ │ ├── ServicesPage.tsx
+│ │ ├── ServicePage.tsx # Dynamic: /services/:slug
+│ │ ├── BlogPage.tsx
+│ │ ├── BlogPostPage.tsx # Dynamic: /blog/:slug
+│ │ ├── LocationPage.tsx # Dynamic: /locations/:slug
+│ │ ├── LocationsPage.tsx
+│ │ ├── ContactPage.tsx
+│ │ ├── PrivacyPolicyPage.tsx
+│ │ ├── TermsOfServicePage.tsx
+│ │ └── LegalPage.tsx
+│ ├── data/
+│ │ └── seoData.ts # All location, service, and blog post data
+│ ├── routes/ # Route definitions
+│ └── index.css # Global styles
+├── scripts/
+│ ├── prerender-routes.ts # Generates per-route index.html files
+│ ├── prune-dist-assets.mjs # Removes unused assets from dist/
+│ ├── generate-sitemap.ts # Generates public/sitemap.xml
+│ ├── generate-robots.ts # Generates public/robots.txt
+│ └── optimize-images.mjs # Converts images to WebP
+├── public/
+│ ├── assets/services/ # Service page images (.webp)
+│ ├── images/blog/ # Blog post images (.webp)
+│ ├── sitemap.xml
+│ └── robots.txt
+├── Dockerfile # Multi-stage: Node build → Caddy serve
+├── docker-compose.yml # Runs the container on localhost:8080
+├── Caddyfile # Caddy config inside the container
+├── caddy-host.snippet # Paste this into your host Caddy config
+├── tailwind.config.cjs
+├── postcss.config.cjs
+├── vite.config.ts
+└── tsconfig.json
```
-## Entwicklung
+---
-Starte den lokalen Entwicklungsserver:
+## Local Development
+
+### Prerequisites
+
+- Node.js 22+ (or use [nvm](https://github.com/nvm-sh/nvm))
+- npm
+
+### Setup
```bash
+# Install dependencies
+npm install
+
+# Start the dev server
npm run dev
```
-Die Anwendung ist dann unter `http://localhost:5173` erreichbar.
+The app runs at **http://localhost:3012**
-## Build
+Hot Module Replacement (HMR) is enabled. If port 3012 is taken, Vite picks the next available port automatically.
-Erstelle eine optimierte Version für die Produktion:
+---
+
+## Build & Preview
```bash
+# Production build (Vite + prerender + asset pruning)
npm run build
-```
-Die erzeugten Dateien befinden sich im `dist`-Verzeichnis.
-
-## Vorschau
-
-Teste den Produktions-Build lokal:
-
-```bash
+# Preview the production build locally
npm run preview
```
-## Technologien
+The build pipeline runs three steps in sequence:
-- [React](https://react.dev/)
-- [Vite](https://vitejs.dev/)
-- [TypeScript](https://www.typescriptlang.org/)
-- [Framer Motion](https://www.framer.com/motion/) (Animationen)
-- [GSAP](https://gsap.com/) (Animationen)
-- [Lenis](https://github.com/studio-freight/lenis) (Smooth Scrolling)
+1. **`vite build`** — bundles and outputs to `dist/`
+2. **`prune-dist-assets.mjs`** — removes any unreferenced files from `dist/assets/`
+3. **`prerender-routes.ts`** — writes a unique `index.html` per route into `dist/` with correct ``, ``, canonical URLs, Open Graph tags, and JSON-LD schema
+
+The result is a fully static site where every URL has its own HTML file — no server-side rendering required.
+
+---
+
+## Deployment (Docker + Caddy)
+
+This project uses a **two-Caddy setup**:
+
+```
+Internet
+ └── Host Caddy (HTTPS, port 443)
+ └── Docker container (internal port 80 → host localhost:8080)
+ └── Caddy inside container
+ └── /srv (built static files)
+```
+
+### Step 1 — Build and start the container
+
+On your server, copy the project files (or clone the repo), then run:
+
+```bash
+docker compose up -d --build
+```
+
+This builds the image (Node 22 compiles the app, Caddy serves it) and starts the container.
+The app is now available at **http://localhost:8080** — only reachable from the server itself.
+
+To verify:
+
+```bash
+curl -I http://localhost:8080
+# HTTP/1.1 200 OK
+```
+
+### Step 2 — Configure the host Caddy
+
+Add the following to your host Caddy config (usually `/etc/caddy/Caddyfile`).
+A ready-to-paste version is in `caddy-host.snippet`:
+
+```caddy
+bayareait.services, www.bayareait.services {
+ encode zstd gzip
+ reverse_proxy localhost:8080
+
+ @www host www.bayareait.services
+ redir @www https://bayareait.services{uri} permanent
+}
+```
+
+Replace `bayareait.services` with your actual domain.
+
+### Step 3 — Reload host Caddy
+
+```bash
+sudo systemctl reload caddy
+# or
+caddy reload --config /etc/caddy/Caddyfile
+```
+
+Caddy automatically obtains and renews an SSL certificate from Let's Encrypt — no manual certificate management needed.
+
+### Updating the site
+
+```bash
+# Pull latest changes, rebuild, restart
+git pull
+docker compose up -d --build
+```
+
+Zero-downtime: Docker Compose replaces the old container while the new one starts.
+
+### Useful Docker commands
+
+```bash
+# View logs
+docker compose logs -f
+
+# Stop the container
+docker compose down
+
+# Rebuild without cache
+docker compose build --no-cache
+docker compose up -d
+```
+
+---
+
+## Adding Content
+
+All page content is driven by **`src/data/seoData.ts`**. No new page files needed for standard locations, services, or blog posts — just add a new entry to the right array.
+
+### Add a location page
+
+```ts
+// src/data/seoData.ts → locationData array
+{
+ city: "Sinton",
+ slug: "locations/it-support-sinton",
+ title: "IT Support Sinton, TX | Bay Area IT",
+ description: "...",
+ h1: "IT Support for Businesses in Sinton, TX",
+ keywords: ["IT support Sinton", "..."],
+ content: `
...
`,
+ faq: [
+ { question: "...", answer: "..." }
+ ]
+}
+```
+
+### Add a service page
+
+```ts
+// src/data/seoData.ts → serviceData array
+{
+ id: "9",
+ slug: "services/cloud-backup",
+ title: "Cloud Backup Services | Bay Area IT",
+ description: "...",
+ h1: "Cloud Backup for Corpus Christi Businesses",
+ keywords: ["cloud backup", "..."],
+ content: `
...
`,
+ faq: []
+}
+```
+
+### Add a blog post
+
+```ts
+// src/data/seoData.ts → blogPostData array
+{
+ slug: "blog/your-post-slug",
+ title: "Your Post Title | Bay Area IT",
+ description: "...",
+ h1: "Your Post Heading",
+ keywords: ["..."],
+ content: `
...
`,
+ date: "2026-03-25",
+ image: "/images/blog/your-image.webp"
+}
+```
+
+After adding content, rebuild:
+
+```bash
+npm run build
+# or on the server:
+docker compose up -d --build
+```
+
+---
+
+## Scripts Reference
+
+| Script | Command | Description |
+|---|---|---|
+| Dev server | `npm run dev` | Starts Vite dev server on port 3012 |
+| Production build | `npm run build` | Vite build + asset pruning + prerendering |
+| Preview build | `npm run preview` | Serves `dist/` locally via Vite |
+| Generate sitemap | `npm run generate:seo` | Writes `public/sitemap.xml` and `public/robots.txt` |
+| Optimize images | `npm run optimize:images` | Converts images in `public/` to WebP |
+| Prerender only | `npm run prerender:routes` | Re-runs route prerendering on existing `dist/` |
diff --git a/bullet b/bullet
new file mode 100644
index 0000000..e69de29
diff --git a/caddy-host.snippet b/caddy-host.snippet
new file mode 100644
index 0000000..79abf4b
--- /dev/null
+++ b/caddy-host.snippet
@@ -0,0 +1,12 @@
+# Paste this block into your HOST Caddy config (e.g. /etc/caddy/Caddyfile)
+# Replace the domain and adjust the port if you changed it in docker-compose.yml
+
+bayareait.services, www.bayareait.services {
+ encode zstd gzip
+
+ reverse_proxy localhost:8080
+
+ # Optional: redirect www → non-www
+ @www host www.bayareait.services
+ redir @www https://bayareait.services{uri} permanent
+}
diff --git a/competitor-alternatives.md b/competitor-alternatives.md
new file mode 100644
index 0000000..eca1920
--- /dev/null
+++ b/competitor-alternatives.md
@@ -0,0 +1,240 @@
+# Competitor Alternatives Plan
+
+## Context
+
+- Product: Bay Area IT
+- Category: Managed IT services for SMBs
+- Market: Corpus Christi and the Coastal Bend
+- Primary goal: Generate qualified local leads for managed IT and outsourced IT support
+- Primary CTA: Book a free 20-minute IT assessment
+
+## Positioning Summary
+
+Bay Area IT should frame itself as the practical local alternative to reactive break-fix shops, generic remote-only MSPs, and the cost of hiring a full in-house IT person too early. The strongest angle is not "more features." It is clearer ownership, faster help, better day-to-day reliability, and local accountability for small and mid-sized businesses.
+
+## Recommended Page Set
+
+### Priority 1
+
+1. `outsourced-it-support-vs-in-house-it.md`
+2. `break-fix-it-support-alternative.md`
+3. `managed-it-services-vs-freelance-it-support.md`
+
+### Priority 2
+
+1. `best-it-support-companies-corpus-christi.md`
+2. `remote-it-support-vs-local-it-support.md`
+3. `msp-vs-internal-it-manager.md`
+
+### Priority 3
+
+1. `bay-area-it-vs-national-it-provider.md`
+2. `computer-repair-shop-vs-managed-it-services.md`
+3. `best-managed-it-service-alternatives-coastal-bend.md`
+
+## Why These Pages Matter
+
+These pages match the real evaluation paths local SMB buyers use:
+
+- They compare outsourced IT against hiring.
+- They look for alternatives after frustration with reactive support.
+- They compare local accountability against cheaper but fragmented options.
+- They often search by problem first, not by a known competitor brand.
+
+## Core Messaging Angles
+
+### Bay Area IT is best for
+
+- SMBs that want one accountable technology partner
+- Teams losing time to recurring issues, slow machines, email problems, and network friction
+- Businesses that need remote-first support with on-site help when needed
+- Owners and office managers who are tired of acting as part-time IT
+
+### Bay Area IT is not the best fit for
+
+- Large enterprises with full internal IT departments
+- Buyers who only want ad hoc hourly repair
+- Organizations seeking the absolute lowest-cost option with no ongoing support relationship
+
+## Common Switch Triggers
+
+- Slow computers and outdated systems reduce productivity
+- Support requests keep piling up without a clear owner
+- Email, Wi-Fi, printer, and access issues interrupt normal work
+- Current provider is reactive, vague, or hard to reach
+- Internal staff are spending too much time on IT work
+
+## Page Template 1: Break-Fix IT Support Alternative
+
+### Suggested URL
+
+`/break-fix-it-support-alternative`
+
+### Title Tag
+
+Break-Fix IT Support Alternative for Corpus Christi Businesses
+
+### Meta Description
+
+Looking for a better alternative to break-fix IT support? See how Bay Area IT helps Corpus Christi businesses reduce downtime with ongoing support, monitoring, and fast local help.
+
+### H1
+
+The Local Alternative to Break-Fix IT Support
+
+### TL;DR
+
+Break-fix support can be fine for isolated issues, but it usually leaves SMBs stuck in a cycle of recurring downtime, surprise costs, and no clear ownership. Bay Area IT is a better fit for businesses that want ongoing support, faster response, and a partner focused on keeping systems stable before problems escalate.
+
+### Section Outline
+
+#### Why businesses look for an alternative
+
+Many small businesses start with break-fix support because it feels simpler and cheaper. The problem is that it only starts working after something is already broken. That means slow computers, email issues, weak Wi-Fi, and recurring employee tickets keep coming back, while managers keep losing time coordinating repairs.
+
+#### Bay Area IT as the alternative
+
+Bay Area IT provides ongoing support instead of isolated repair visits. That includes day-to-day help desk coverage, practical security baselines, device and user support, network help, and a local team that can step in remotely or on-site. The difference is not just fixing issues faster. It is reducing how often they happen in the first place.
+
+#### Comparison snapshot
+
+| Category | Bay Area IT | Break-Fix Provider |
+|---|---|---|
+| Support model | Ongoing monthly support | Reactive per-incident support |
+| Ownership | One accountable partner | Usually ticket-by-ticket |
+| Cost structure | Predictable recurring pricing | Variable and harder to forecast |
+| Prevention | Monitoring and maintenance | Limited preventive work |
+| Business fit | SMBs that want reliability | SMBs with very occasional issues |
+
+#### Who should switch
+
+Bay Area IT is the better choice if your team depends on email, cloud apps, printers, Wi-Fi, shared drives, and employee devices every day and cannot afford repeated disruption. Break-fix is still reasonable for very small environments that truly only need occasional repair.
+
+#### CTA
+
+Book a free 20-minute assessment and see whether ongoing IT support would reduce downtime for your team.
+
+## Page Template 2: Outsourced IT Support vs In-House IT
+
+### Suggested URL
+
+`/outsourced-it-support-vs-in-house-it`
+
+### Title Tag
+
+Outsourced IT Support vs In-House IT for Small Businesses
+
+### Meta Description
+
+Comparing outsourced IT support to hiring in-house IT? See the tradeoffs in cost, coverage, speed, and business fit for Corpus Christi small businesses.
+
+### H1
+
+Outsourced IT Support vs In-House IT: Which Is Better for a Growing SMB?
+
+### TL;DR
+
+For many small and mid-sized businesses, outsourced IT is the more practical option because it provides broader coverage at a lower fixed cost than hiring a full-time internal employee too early. In-house IT becomes stronger when the business has enough scale, internal complexity, and daily demand to justify dedicated full-time ownership.
+
+### Comparison Table
+
+| Category | Bay Area IT / Outsourced IT | In-House IT |
+|---|---|---|
+| Cost | Usually lower and more predictable for SMBs | Higher salary, benefits, and hiring overhead |
+| Coverage | Broader skill coverage across support areas | Depends on one person's strengths |
+| Speed | Fast remote help with local escalation | Strong if fully staffed and available |
+| Scalability | Easier to ramp without adding headcount | Requires hiring and management |
+| Best for | SMBs without a mature IT department | Larger or more complex environments |
+
+### Key Sections
+
+#### Cost comparison
+
+Most SMBs underestimate the full cost of internal IT. Salary is only the starting point. Hiring, benefits, downtime risk during turnover, and tool overhead all add up quickly. Outsourced support works best when a company needs coverage across many day-to-day IT functions but does not need a full internal team yet.
+
+#### Breadth vs depth
+
+An internal IT hire can be valuable, but one person rarely covers everything equally well across support, networking, email, vendors, security basics, onboarding, backups, and documentation. Bay Area IT should position breadth and consistency as a major advantage here.
+
+#### Best-fit summary
+
+Choose outsourced IT if you want dependable support without taking on full-time headcount. Choose in-house IT when your environment is large enough to justify dedicated internal ownership every day.
+
+## Page Template 3: Managed IT Services vs Freelance IT Support
+
+### Suggested URL
+
+`/managed-it-services-vs-freelance-it-support`
+
+### Title Tag
+
+Managed IT Services vs Freelance IT Support
+
+### Meta Description
+
+Freelance IT support can work for occasional help, but managed IT services offer more structure, accountability, and continuity for growing small businesses.
+
+### H1
+
+Managed IT Services vs Freelance IT Support
+
+### TL;DR
+
+Freelance IT support can be affordable and flexible, but it often depends on one person's availability and process. Managed IT services are a better fit for businesses that want reliable response, recurring maintenance, clearer documentation, and less operational risk.
+
+### Key Differentiators
+
+- Process and coverage over one-person availability
+- Ongoing support instead of ad hoc fixes
+- Better continuity if one technician is unavailable
+- Stronger fit for teams with multiple users and recurring support needs
+
+## Reusable Proof Themes
+
+- Local presence in Corpus Christi
+- Regional service across the Coastal Bend
+- Remote-first support with on-site help when needed
+- Broad scope across help desk, email, networking, devices, backups, and security basics
+- Low-friction CTA through a free 20-minute assessment
+
+## Honest Weaknesses to Acknowledge
+
+- Bay Area IT is not the lowest-cost option if a business only needs one-off repairs
+- Businesses with complex enterprise compliance requirements may need a larger specialist provider
+- No public customer-switching quotes are currently documented in the repo
+
+## Content Gaps To Fill Before Publishing
+
+1. Confirm the canonical brand name: Bay Area IT, Bay Area IT Services, or Bay Area Affiliates.
+2. Normalize proof points that currently conflict in the repo, especially years in business and customer count.
+3. Add at least 2 real switching testimonials.
+4. Document migration/onboarding process for new managed IT clients.
+5. Add concrete pricing guidance or example monthly plan ranges if the business is comfortable publishing them.
+
+## Competitor Data Template
+
+```yaml
+competitor:
+ name:
+ type:
+ geography:
+ target_audience:
+ pricing_model:
+ strengths: []
+ weaknesses: []
+ best_for: []
+ not_ideal_for: []
+ common_complaints: []
+ migration_notes: []
+ comparison_angle:
+```
+
+## CTA Options
+
+- Book your free 20-minute IT assessment
+- Talk to a local IT partner about your current setup
+- See if managed IT support would reduce downtime for your team
+
+## Recommended Next Step
+
+Turn the first three priority pages into publishable landing-page copy, then add local proof and real switching testimonials before rollout.
diff --git a/components/AreasWeServe.tsx b/components/AreasWeServe.tsx
index c9a4f25..9cb9acc 100644
--- a/components/AreasWeServe.tsx
+++ b/components/AreasWeServe.tsx
@@ -3,6 +3,10 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { locationData } from '../src/data/seoData';
+const cityLocations = locationData.filter(loc =>
+ loc.slug.startsWith('locations/it-support-')
+);
+
const AreasWeServe: React.FC = () => {
return (
@@ -12,11 +16,11 @@ const AreasWeServe: React.FC = () => {
We provide professional IT support and IT services for businesses throughout Corpus Christi and the surrounding Coastal Bend area.
- Our team supports local companies with business IT support, outsourced IT services, and help desk solutions, delivered remotely or on-site when needed.
+ Our team supports local companies with outsourced IT services and help desk solutions, delivered remotely or on-site when needed.
- {locationData.map((loc) => (
+ {cityLocations.map((loc) => (
{
Not sure if your location is covered? Contact us today to discuss your IT needs.
-
- Get local IT support in Corpus Christi and nearby areas
+
+ View all service areas →