diff --git a/.dockerignore b/.dockerignore index 20c690b..ec99e3e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,15 +1,6 @@ +node_modules +dist .git .gitignore .agents -node_modules -dist -*.log -Dockerfile -docker-compose.yml -README.md -*.md -bullet -ellipsis -em -left -right +npm-debug.log* diff --git a/Caddyfile b/Caddyfile index 7a84d94..e60c506 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,22 +1,12 @@ -# 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 + root * /srv + encode zstd gzip + try_files {path} {path}/ /index.html + file_server - 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 + header { + X-Content-Type-Options "nosniff" + Referrer-Policy "strict-origin-when-cross-origin" + X-Frame-Options "SAMEORIGIN" + } } diff --git a/Dockerfile b/Dockerfile index 450db82..97b954d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM node:22-alpine AS build WORKDIR /app -COPY package*.json ./ +COPY package.json package-lock.json ./ RUN npm ci COPY . . @@ -14,5 +14,3 @@ 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 b8b70f6..9d1f2a1 100644 --- a/README.md +++ b/README.md @@ -1,293 +1,41 @@ -# Bay Area IT — Website +# Bay Area IT -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. +Vite/React marketing site for `bayareait.services`. ---- - -## Table of Contents - -- [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) - ---- - -## 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 -``` - ---- - -## Local Development - -### Prerequisites - -- Node.js 22+ (or use [nvm](https://github.com/nvm-sh/nvm)) -- npm - -### Setup +## Local ```bash -# Install dependencies npm install - -# Start the dev server npm run dev ``` -The app runs at **http://localhost:3012** - -Hot Module Replacement (HMR) is enabled. If port 3012 is taken, Vite picks the next available port automatically. - ---- - -## Build & Preview +## Production build ```bash -# Production build (Vite + prerender + asset pruning) npm run build - -# Preview the production build locally -npm run preview ``` -The build pipeline runs three steps in sequence: +The production build regenerates `robots.txt` and `sitemap.xml`, runs Vite, prunes unused assets, and prerenders route HTML into `dist/`. -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 `
...
`, - 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/` | +- Static assets are served by Caddy inside the container. +- SPA fallback is enabled while prerendered route folders still resolve directly. +- Claims such as `24/7`, `30+ local businesses`, and legal company details should be verified before launch. diff --git a/docker-compose.yml b/docker-compose.yml index 661ab71..4770b86 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,9 @@ services: - web: + bayarea-site: build: context: . dockerfile: Dockerfile - image: bay-area-affiliates:latest + container_name: bayarea-site restart: unless-stopped ports: - "127.0.0.1:8080:80"