Ships the static landing page to the existing k3s cluster at 65.20.110.165, served at www.apexturf.es (apexturf.es redirects to it), using a self-hosted Gitea instance as the container registry. - deploy/Dockerfile + nginx.conf: nginx:alpine image serving dist/ (SPA-safe fallback, gzip, cache headers). Build-tested locally against the real dist/ output. - deploy/k8s/apex-turf/: Namespace, Deployment, Service, and two Ingresses (www.apexturf.es + a Traefik Middleware redirect from the bare domain). - deploy/k8s/cert-manager/: Let's Encrypt ClusterIssuers (prod + staging) for HTTP-01 via the cluster's bundled Traefik. - deploy/k8s/gitea/: Helm values for a lightweight, SQLite-backed Gitea at git.apexturf.es with its container registry enabled. - docs/DEPLOYMENT.md: full phased runbook with exact commands, troubleshooting, and a redeploy cheat sheet. - docs/README.md: point at the new deploy/ tree and runbook. Nothing here touches the remote cluster — these are local manifests and docs for the user to apply themselves. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
113 lines
7.2 KiB
Markdown
113 lines
7.2 KiB
Markdown
# Apex Turf — Landing Page
|
||
|
||
A single-page marketing landing page for **Apex Turf**, a premium artificial-turf design & installation
|
||
company (residential landscaping, pádel courts, football/multisport pitches, and golf putting greens),
|
||
built with plain HTML, CSS and vanilla JavaScript — no build step, no frameworks, no dependencies.
|
||
|
||
## Where things live
|
||
|
||
```
|
||
dist/
|
||
├── index.html # the landing page
|
||
├── css/styles.css # all styling (CSS variables, layout, components)
|
||
├── js/main.js # all interactivity (vanilla JS, no dependencies)
|
||
└── assets/images/
|
||
├── animals/ # lion, shark, panther, eagle — hero/section imagery
|
||
│ (compressed to ~250–420KB JPEGs; originals lived in ../animals)
|
||
└── logos/ # apexturf-logo.png (full lockup), apexturf-icon.png (mark only)
|
||
(resized from ../logos, background-transparent variants)
|
||
docs/
|
||
├── README.md # this file
|
||
├── Changelog.md
|
||
├── CONTENT-SPECS.md # all 7 pdfs/ specs archived as markdown (4 used, 2 not-yet-built, 1 duplicate)
|
||
└── DEPLOYMENT.md # runbook: ship dist/ to the k3s cluster on Vultr
|
||
deploy/
|
||
├── Dockerfile # nginx:alpine serving dist/ (build context = repo root)
|
||
├── nginx.conf
|
||
└── k8s/
|
||
├── apex-turf/ # Namespace, Deployment, Service, Ingress (+www redirect) for the site
|
||
├── cert-manager/ # Let's Encrypt ClusterIssuers
|
||
└── gitea/ # Helm values for the self-hosted Gitea registry
|
||
```
|
||
|
||
To preview locally: open `dist/index.html` directly in a browser, or serve the folder
|
||
(`python3 -m http.server` from inside `dist/`) so the favicon/font preconnects behave exactly as in
|
||
production.
|
||
|
||
## Design source
|
||
|
||
The three reference mockups in `../website-ideas/` (`Websiteidea1.png` – `Websiteidea3.png`) all share one
|
||
layout: a full-bleed, diagonally-split hero — **Residential Turf** (lion) fixed on the left, and a rotating
|
||
**Sport Turf** category (Pádel/shark, Football/panther, Golf/eagle) on the right. Rather than picking one
|
||
mockup, the landing page **combines all three**: the hero's right pane auto-rotates through Pádel → Football
|
||
→ Golf every 6 seconds (with manual P/F/G tabs, pause-on-hover/focus), so every specialty shown across the
|
||
three reference images is represented on one page.
|
||
|
||
Copy, section structure, and messaging (headlines, value pillars, "Installers First, Not Salesmen", the
|
||
Apex Guarantee, etc.) are drawn from the four sport-specific and About Us page specifications in `../pdfs/`,
|
||
condensed from full dedicated pages into single-page sections since this build is one landing page rather
|
||
than a multi-page site. The full content of all 7 PDFs (`../pdfs/` has 8 files, but two golf specs are
|
||
identical duplicates) is archived as markdown in **`CONTENT-SPECS.md`** — including the two specs that
|
||
describe pages *not* built here: a gated "Maintenance Handbook" lead-magnet page, and a 3-step turf
|
||
project/sample-request questionnaire meant to replace the current one-screen quote form. Both are noted as
|
||
follow-up work in that file.
|
||
|
||
## Page structure
|
||
|
||
1. **Header** — logo, nav (Home / Landscaping / Pádel / Football / Golf / About Us), sticky on scroll,
|
||
hamburger menu on mobile.
|
||
2. **Hero** — split diagonal layout as above.
|
||
3. **Value pillars** — Child & Family Safe, Pet-Friendly, Built for Spanish Weather, Low Maintenance (not
|
||
no maintenance).
|
||
4. **Specialties grid** — 4 quick-nav cards (Landscaping / Pádel / Football / Golf) linking to detail
|
||
sections below.
|
||
5. **Detail sections ×4** — one per specialty, alternating image/text layout, each with its own feature
|
||
list and CTA, matching the messaging of the corresponding PDF spec.
|
||
6. **About** — "Master Installers. Absolute Precision." trust section with the two Apex Guarantee cards.
|
||
7. **Showcase/Gallery** — a 4-image visual recap of the specialties (not client project photos — there
|
||
were none supplied; swap in real installation photography here when available).
|
||
8. **Contact / quote form** — front-end-only form (name, email, phone, project type, message) with
|
||
client-side validation and a success message. **There is no backend** — see "What still needs wiring
|
||
up" below.
|
||
9. **Footer** — logo, quick links, contact info, social icons.
|
||
|
||
## Notable implementation details
|
||
|
||
- **No build tooling.** Plain CSS with custom properties for the palette/spacing scale; plain ES5-ish
|
||
vanilla JS (one IIFE, no bundler needed).
|
||
- **Self-contained interactivity**: sticky header, mobile nav, hero tab rotation, scroll-spy nav
|
||
highlighting, scroll-reveal animations, smooth-scroll with header offset, back-to-top button, and the
|
||
quote form — all in `js/main.js`, no external libraries.
|
||
- **Grid-blowout defense**: every `grid-template-columns` track uses `minmax(0, …fr)` rather than a bare
|
||
`fr`. A bare `fr` track's implicit `auto` minimum can exceed the container's padded content box and
|
||
force horizontal overflow — this was caught during testing (see Changelog) and fixed everywhere as a
|
||
standing defensive pattern, not just on the section where it first showed up.
|
||
- **Scroll-reveal never gets stuck hidden**: the fade-in-on-scroll effect (`.reveal` → `.is-visible`) is
|
||
wrapped in try/catch with a 2.5s safety-net timeout that force-reveals everything, and a `<noscript>`
|
||
rule shows everything immediately if JavaScript is unavailable.
|
||
- **`prefers-reduced-motion`** is respected throughout (reveal animations, hero auto-rotation, and smooth
|
||
scrolling all fall back to instant/static behavior).
|
||
- **Accessibility basics**: semantic landmarks, `aria-label`/`aria-expanded` on the nav toggle, `role=tab`
|
||
/ `aria-selected` on the hero sport tabs, alt text on every image, visible focus states inherited from
|
||
default UA styles (not suppressed).
|
||
- Images were re-compressed (JPEG quality ~72, resized logo PNGs) from the originals in `../animals` and
|
||
`../logos` to keep total page weight reasonable (~1.5MB of images total).
|
||
|
||
## What still needs wiring up before going live
|
||
|
||
This is a front-end-only deliverable. Before launch:
|
||
|
||
- **Contact form has no backend.** It currently just shows a client-side "thanks" message and does not
|
||
send an email or hit an API. Wire `#quoteForm`'s submit handler in `js/main.js` to a real form
|
||
endpoint (e.g. Formspree, a serverless function, or your own backend).
|
||
- **Placeholder contact details**: phone `+34 900 123 456`, email `hello@apexturf.com`, and "Madrid,
|
||
Spain" are placeholders (no real contact info was supplied) — replace with the real ones in `index.html`
|
||
(they appear in both the Contact section and the footer). Social links (`#`) are also placeholders —
|
||
point them at real profiles.
|
||
- **Gallery images are stand-ins.** The showcase/gallery section reuses the four mascot photos for lack
|
||
of real installation photography — swap in real project photos when available.
|
||
- **Two specced pages/flows aren't built at all yet** (full details in `CONTENT-SPECS.md`):
|
||
1. A gated "Maintenance Handbook" PDF lead-magnet page (email-capture → PDF download).
|
||
2. A 3-step turf project/sample-request questionnaire meant to eventually replace the current
|
||
single-screen `#quoteForm`, with supplier-webhook and CRM routing.
|