# Website Starter Kit — Reusable Build Blueprint

A portable, brand-agnostic recipe for building a **multi-page static marketing website** that deploys to **cPanel shared hosting** with no framework, no build step, and no PHP (PHP optional, only for a contact-form mail handler).

**How to use this file:** paste it into a new project and tell Claude *"build the site following this blueprint."* Fill in every `⟨PLACEHOLDER⟩` first (or have Claude ask you for them). Everything here is proven architecture — keep the structure, swap the brand.

---

## 0. Fill these in first (the only things that change per site)

| Placeholder | Example | Notes |
|---|---|---|
| `⟨BRAND_NAME⟩` | Innovare Commercial | Shown to users everywhere |
| `⟨TAGLINE⟩` | Commercial fitout & construction | One line |
| `⟨PHONE⟩` / `⟨PHONE_TEL⟩` | 0488 773 232 / `tel:0488773232` | Keep consistent on every page |
| `⟨EMAIL⟩` | info@example.com.au | |
| `⟨ADDRESS⟩` | 29/97 Creek St, Brisbane QLD 4000 | |
| `⟨TRUST_SIGNALS⟩` | Licence numbers, certifications, ABN | The credibility line in the utility bar + footer |
| `⟨PRIMARY_COLOR⟩` | `#17146E` | Brand color → `--ink` |
| `⟨ACCENT_COLOR⟩` | `#EBA53C` | Single accent → `--amber` (rename token to suit) |
| `⟨HEADING_FONT⟩` / `⟨BODY_FONT⟩` | Archivo / Hanken Grotesk | Two Google Fonts, one pairing |
| `⟨PAGE_LIST⟩` | home, about, services…, contact | Drives nav + `data-page` keys |
| `⟨REGIONS/KEYWORDS⟩` | Brisbane, Gold Coast, SEQ | For local SEO copy |

**Rule:** pick **one** brand color + **one** accent + **one** font pairing and apply consistently. Never introduce a third accent hue or a third font.

---

## 1. Architecture (the non-negotiable spine)

- **Pure static HTML + CSS + vanilla JS.** No framework, no bundler, no npm. Deploys by uploading files as-is to cPanel.
- **Global header & footer are injected at runtime** via `fetch()` of files in `includes/`. One edit updates every page.
  - ⚠ **Consequence:** the site must be served over **HTTP(S)** (cPanel does this automatically). Opening a page as `file://` will fail to load header/footer — that is expected, not a bug. Always test through a served preview.
- **One global stylesheet** (`assets/css/style.css`) = the entire design system.
- **One global script** (`assets/js/main.js`) = all behavior, IIFE, `'use strict'`, ES5-compatible vanilla (`var`, `function`, `Array.prototype.forEach`). No libraries.
- **Per-page `<head>`** holds the page's own unique `<title>` + `<meta description>` (intentionally NOT globalised — so SEO meta differs per page). Font `<link>`s + stylesheet link repeat in every head.
- **Pages stay flat in the root** — no page subfolders. All internal links are bare filenames (`about.html`, `services-x.html`).

### File tree
```
/                       ← all HTML pages flat in root
  index.html            ← data-page="home"
  about.html
  contact.html
  …one .html per page…
includes/
  header.html           ← utility bar, nav, mega menu, mobile panel
  footer.html
assets/
  css/style.css         ← single global stylesheet (all tokens + components)
  js/main.js            ← single global script
uploads/                ← source content / reference only, not shipped
```

### Page skeleton (every page, identical)
```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>⟨Unique Keyworded Title⟩ | ⟨BRAND_NAME⟩</title>
  <meta name="description" content="⟨Unique 150–160 char description⟩">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=⟨HEADING_FONT⟩:wght@…&family=⟨BODY_FONT⟩:wght@…&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="assets/css/style.css">
</head>
<body data-page="⟨PAGEKEY⟩">
<div data-include="header"></div>
<main> …sections… </main>
<div data-include="footer"></div>
<script src="assets/js/main.js" defer></script>
</body>
</html>
```

`data-page` values drive the active nav state (`home`, `about`, `services`, `contact`, …). Multiple pages can share a key (e.g. all service pages = `services`).

---

## 2. The global script (`assets/js/main.js`)

Single IIFE. `boot()` runs on `DOMContentLoaded`:
```
boot():
  loadIncludes().then(initNav)   // fetch includes/*.html into [data-include], THEN wire nav
  initAccordions()
  initFilters()
  initForm()
  initReveal()
```
- `loadIncludes()` — for each `[data-include="x"]`, fetch `includes/x.html` and replace the node's `outerHTML`. Nav wiring must wait for this (header doesn't exist until fetched).
- `initNav()` — sets active link from `body[data-page]`; mega-menu open/close (hover ≥861px + click + Escape + backdrop); mobile panel open/close + body scroll-lock; sets footer year.
- `initAccordions()` — toggle `.open`, animate `max-height`; single-open per `.acc` group.
- `initFilters()` — `.filter-btn[data-filter]` toggles `.hide` on `.card[data-sector]`.
- `initForm()` — client-side validation (required + email regex), inline `.err-msg`, success swap.
- `initReveal()` — `IntersectionObserver` adds `.in` to `[data-reveal]`; **feature-detect and fail safe** (no IO → show everything).
- **Every `initX()` guards with an early `return` if its element is absent** — never throw on a page that lacks that component. New behaviors get their own `initX()` + a call in `boot()`.

---

## 3. Color system (tokens in `:root`)

Define as CSS custom properties; **always use the token, never a raw hex in markup.** Rename tokens to suit the brand but keep the *roles*:

```css
:root{
  --ink:        ⟨PRIMARY_COLOR⟩;   /* brand color: headings, logo, dark buttons, icons */
  --ink-deep:   /* darkest shade */; /* utility bar, hero/footer/dark sections */
  --ink-2:      /* secondary */;     /* hovers, links, focus rings */
  --accent:     ⟨ACCENT_COLOR⟩;    /* the ONLY accent: CTAs, eyebrow rule, hover bars */
  --accent-dark:/* accent hover */;
  --paper:#fff;                      /* default bg */
  --soft: /* warm/cool off-white */; /* alternating section band (.section-soft) */
  --tint: /* light brand tint */;    /* icon chips, placeholder fills */
  --line: /* hairline */;            /* borders / dividers */
  --text: /* body */;
  --muted:/* secondary text */;
  --maxw:1240px; --pad:24px; --radius:4px;
  --shadow-sm/md/lg: /* soft, brand-tinted, large negative spread */;
  --ease:cubic-bezier(.16,.84,.44,1);
}
```
**Rules:** one brand color, one accent, derive any extra shade in `oklch` from the palette — never invent unrelated colors. On dark sections: text `#fff` / `rgba(255,255,255,.72)` / `.6`; accent eyebrow via `.eyebrow.light`.

---

## 4. Typography scale

Two Google Fonts: **⟨HEADING_FONT⟩** (headings, logo, numbers) + **⟨BODY_FONT⟩** (body, UI, default). Both `<link>`ed in every head. All sizes fluid via `clamp()`:

| El | Size | Weight |
|---|---|---|
| `h1/.h1` | `clamp(2.5rem,5.2vw,4.1rem)` | 800, ls -.025em |
| `h2/.h2` | `clamp(1.85rem,3.4vw,2.85rem)` | 800, ls -.02em |
| `h3/.h3` | `clamp(1.25rem,1.8vw,1.55rem)` | 700 |
| `.lead` | `clamp(1.05rem,1.5vw,1.28rem)` | 400, lh 1.6 |
| body | 17px (16px <560px) | 400, lh 1.7 |
| `.eyebrow` | 12.5px | 700, uppercase, ls .16em, accent, leading rule |

Headings `--ink` by default, `#fff` on dark sections. Use `text-wrap: pretty`.

---

## 5. Spacing & shape

- `.container` max 1240px / `.container-narrow` 880px; horizontal pad 24px.
- Section rhythm: `section{ padding:clamp(60px,8vw,112px) 0; }` — use the `<section>` element, don't hand-set vertical padding.
- `--radius:4px` everywhere (cards, buttons, inputs, placeholders); pills/chips `100px`. Keep corners sharp.
- **Always lay groups out with flex/grid + `gap`** — never inline-block whitespace or per-element margins.
- Card hover lift uses `--shadow-md`.

---

## 6. Component library (build these in `style.css`)

Reuse, don't reinvent. Core set:
- **Buttons:** `.btn` + `.btn-primary` (accent) / `.btn-dark` / `.btn-ghost` / `.btn-light` / `.btn-outline-light`. Inline arrow SVG slides on hover. `.link-arrow` = inline text link w/ sliding arrow.
- **Header:** `.site-header` = `.utility-bar` (trust signals + contact) + `.nav-bar` (logo `.brand`, `.nav-links`, CTA, `.nav-burger`) + `.mega` dropdown + `.mobile-panel`. Lives in `includes/header.html`.
- **Footer:** `.site-footer` = `.f-top` (4-col: brand+trust, links, links, contact) + `.f-bar`.
- **Logo:** prefer a CSS construct (`.brand .mark` shapes + two-line wordmark) or a single `<img>` — keep it in the include so it's global.
- **Hero:** `.hero` (homepage, 2-col + `.trust` stats) / `.page-hero` (interior; `.with-media` = 2-col image variant) with `.crumb` breadcrumb.
- **Trust strip:** `.trust-strip` of `.ts-item` + `.ts-sep`.
- **Cards:** `.svc-grid` (3-col) of `.svc-card` (icon chip `.ico`, h3, p, `.more`); accent top-bar animates on hover. Non-link cards get `style="cursor:default"`.
- **Feature grid:** `.feature-grid` of numbered `.feature` (hairline-divided).
- **Lists:** `ul.check-list` (`.two` = 2-col) w/ inline circled-check SVG. `.chips` of `.chip`. `.spec-list` of `.row` (`.k`/`.v`).
- **CTA band:** `.cta-band` (dark, accent radial glow) — closes most pages.
- **Accordion:** `.acc > .acc-item > .acc-q`(+`.acc-icon` plus→×) + `.acc-body > .acc-inner`.
- **Filterable grid:** `.filter-row` of `.filter-btn[data-filter]` controlling `.project-grid` of `.project-card[data-sector]`.
- **Blog:** `.blog-grid` of `.blog-card`. **Testimonials:** `.tm-grid` of `.tm-card`.
- **Contact:** `.contact-grid`, `.contact-card`, `.form-card`, `.field`/`.form-row`, `.steps`/`.step`.
- **Image placeholders:** `.ph` (diagonal-hatch fill) + shape modifier (`.ph-hero/-wide/-sq/-43`) + `.ph-inner` (icon + `.ph-label` + `.ph-tag`); `.ph.dark` for dark sections. **Use these for all imagery until real photos arrive**, each with a descriptive label.

### Section-head pattern (use everywhere)
```html
<div class="section-head"><!-- add .center to center -->
  <span class="eyebrow">Label</span>
  <h2>Heading</h2>
  <p>Supporting copy.</p>
</div>
```

---

## 7. UI patterns & page rhythm

- Alternate white and `.section-soft`, punctuated by **one** `.section-dark` block and a closing `.cta-band`. Max 1–2 background colors per page — don't checker every section.
- Interior/service pages typically: `page-hero.with-media` → intro prose (`.container-narrow .prose`) → `.svc-grid` → `.section-dark` split → optional `.spec-list` → FAQ `.acc` → `.cta-band`.
- Every interior page ends with a `.cta-band`.
- Cross-link 2–3 related pages with `.link-arrow`.

---

## 8. Responsive breakpoints (match exactly — don't add new ones casually)

- **1024px:** hero/page-hero → 1 col (media on top); 3-col grids → 2-col; mega menu → 2-col.
- **860px:** desktop `.nav-links` hidden, `.nav-burger` shown (mobile panel takes over); splits → 1 col; contact grid → 1 col; footer → 2 col.
- **560px:** body 16px; all card grids → 1 col; form rows → 1 col; spec rows stack; footer → 1 col.

Mobile menu = full-screen `.mobile-panel` sliding in from the right. Hit targets ≥ 44px. Sanity-check all 3 breakpoints after any layout change.

---

## 9. Animation guidelines

- **Scroll reveal:** `data-reveal` → IO adds `.in` (fade up 22px→0). Use sparingly on content blocks.
- **Hover:** ~.15–.25s w/ `--ease`. Cards lift `translateY(-3px)`+`--shadow-md`; buttons `translateY(-1px)`; arrows slide `translateX(3–4px)`; card top-bar `scaleX(0→1)`.
- **Accordion:** `max-height` .3s; icon rotates 45° (plus→×). **Mega menu:** opacity/visibility/translateY .22s.
- Keep motion subtle and functional. No autoplay, parallax, or looping background animation.

---

## 10. Accessibility requirements

- Semantic HTML (`header/nav/main/section/article/footer`), real `<button>` for controls, one `<h1>` per page then logical order.
- `aria-label` on icon-only controls; `aria-expanded` on the services toggle; filter buttons labelled.
- Keyboard-operable; `Escape` closes the mega menu; visible focus ring (`box-shadow:0 0 0 3px rgba(brand,.1)` on inputs).
- AA contrast: body text on white and white on darkest shade both pass. Reserve the accent (a mid-tone) for large/bold/non-critical text.
- Form fields: associated `<label>`, `required`, inline `.err-msg` (not color-only).
- Real images need descriptive `alt`; placeholders carry visible labels meanwhile.

---

## 11. SEO standards

- Unique `<title>` + `<meta description>` per page (that's why the head is per-page). Title pattern: `Primary Keyword Location | ⟨BRAND_NAME⟩`.
- Local SEO: name ⟨REGIONS/KEYWORDS⟩ in body copy. One `<h1>`; descriptive `<h2>/<h3>`; meaningful internal links with descriptive anchor text (no "click here").
- Keep genuine content depth + real FAQ answers for EEAT — don't strip to "tidy up."
- Optional future: JSON-LD (`LocalBusiness`, `FAQPage`) per page in `<head>`.

---

## 12. Coding standards

**HTML:** canonical HTML5 — close every non-void element, double-quote all attributes, no self-closing non-void elements, 2-space indent, lowercase tags/attrs. Use component classes; reserve inline styles for tiny one-off nudges (`style="cursor:default"`).

**CSS:** everything in the single global `style.css`. No per-page `<style>`, no extra stylesheets. Use `:root` tokens. Flat BEM-ish class names (`.svc-card`, `.tm-card .author .av`); low specificity. Mobile tweaks go in the existing `@media` blocks (1024/860/560).

**JS:** everything in the single global `main.js`. IIFE, `'use strict'`, ES5-compatible vanilla. No libraries/modules/build. Feature-detect + fail safe + early-return guards. `<script defer>` at end of `<body>`.

---

## 13. Naming conventions

- **Pages:** lowercase, hyphenated, keyword-led (`medical-centre-fitouts.html`, `strip-out-make-good.html`).
- **CSS classes:** lowercase-hyphenated, component-prefixed; modifiers as separate classes (`.section-soft`, `.btn-primary`, `.ph-wide`, `.eyebrow.light`).
- **Data attributes:** `data-page`, `data-include`, `data-filter`, `data-sector`, `data-reveal`.
- **IDs (JS hooks):** camelCase (`#servicesToggle`, `#megaMenu`, `#mobilePanel`, `#enquiryForm`, `#formSuccess`, `#footYear`).

---

## 14. Performance

- Static + light: no libraries; total JS is one small file.
- Fonts: preconnect to Google Fonts; request only the weights used.
- Use `.ph` placeholders until real images arrive. For real images: compress, set explicit `width`/`height`, `loading="lazy"` below the fold, prefer WebP/AVIF.
- One render-blocking CSS file is acceptable at this scale — don't fragment or inline per-page.

---

## 15. Rules for creating a NEW page

1. Copy an existing analogous page as the starting point.
2. Set a unique `<title>` + `<meta description>`; keep both font `<link>`s + stylesheet link.
3. Set `<body data-page="…">` to the correct nav key.
4. Keep the skeleton: `data-include="header"` → `<main>` → `data-include="footer"` → `main.js`.
5. Build `<main>` from existing components; end with `.cta-band`.
6. New nav destination? Add the link to header (nav + mega menu + mobile panel) **and** footer — in `includes/` only.
7. `.ph` placeholders for imagery, each with a clear `.ph-label`.
8. Cross-link 2–3 related pages.
9. Re-test the 3 breakpoints + nav active state.

## 16. Rules for MODIFYING existing code

- Make the smallest change that satisfies the request; don't redesign untouched parts.
- Header/footer/nav → edit `includes/` once. Global style → `style.css` tokens/classes. Global behavior → `main.js`. Per-page content → that page's `<main>` only.
- Preserve `data-page`, include divs, font links, and the script tag on every page.
- Never hard-code a hex when a token exists; never add a new font; never change the 4px radius or the palette without instruction.
- Keep business facts identical across all pages — change one, change all.

---

## 17. Do's and Don'ts

**Do:** use tokens + existing components · keep pages flat with bare-filename links · edit header/footer once in `includes/` · keep content depth + trust signals · use `.ph` placeholders w/ labels · lay out with flex/grid+`gap` · test 3 breakpoints + nav state.

**Don't:** add a framework/build/extra CSS file/per-page `<style>` or `<script>` · invent colors/fonts/bigger radius · use emoji or decorative SVG illustrations · move pages into subfolders or use absolute paths · duplicate header/footer into pages · open as `file://` and conclude the header is broken (serve over HTTP).

---

## 18. Quality checklist (run before completing any task)

- [ ] Served over HTTP → header + footer resolve (includes load).
- [ ] `body[data-page]` correct → right nav item active.
- [ ] Unique `<title>` + `<meta description>`; font links + stylesheet + `main.js` present.
- [ ] Only tokens for color; no stray hex; no new fonts; radius still 4px.
- [ ] Layout uses existing components; new patterns added to `style.css`, not inline/per-page.
- [ ] Responsive at ~1280 / ~900 / ~520px — no overflow, grids collapse, mobile menu works.
- [ ] Interactive: mega menu (hover+click+Esc), mobile panel, accordions, filters, form validation + success.
- [ ] Imagery = labelled `.ph` placeholders (or real images w/ `alt` + lazy-load).
- [ ] Internal links correct; related cross-links present.
- [ ] Business facts consistent everywhere.
- [ ] No console errors.
- [ ] Accessibility: heading order, icon buttons labelled, keyboard + focus intact.

---

## 19. Optional: contact form going live (cPanel)

The contact form validates and shows a client-side success state but does **not** send. To go live, add a `contact.php` mail handler (cPanel supports PHP natively) and point the form `action`/`method` at it. Keep the existing validation UX. This is the only place PHP enters the stack.
