# Apex Admins — Locations Module (States → Cities → Towns)

**Version:** 1.0  
**Date:** 2026-07-10  
**Purpose:** SEO-first geographic landing pages for every Australian state, city, and town served by Apex Admins.

---

## 1. Goals

| Goal | Success criteria |
|------|------------------|
| **Navigation** | “Locations” in header with mega menu grouped by state → cities |
| **Hierarchy** | Every state, city, and town has its own indexable URL |
| **SEO** | Unique title/meta, canonical, JSON-LD (`LocalBusiness` + breadcrumbs), sitemap, internal linking |
| **UX** | Premium homepage-coherent design; hub explorer with clear hierarchy |
| **Content** | Location-specific copy via `LocationPageBuilder` (challenges, roles, FAQs, stats) |
| **Scale** | Seeder for all AU states + major cities + representative towns |

---

## 2. URL Architecture

```
/locations                              → National hub (all states)
/locations/{state}                      → State page (e.g. /locations/nsw)
/locations/{state}/{city}               → City page (e.g. /locations/nsw/sydney)
/locations/{state}/{city}/{town}        → Town page (e.g. /locations/nsw/sydney/parramatta)
```

**Route names:** `locations.index`, `locations.state`, `locations.city`, `locations.town`

**Slug rules:**
- State slugs: `nsw`, `vic`, `qld`, `sa`, `wa`, `tas`, `nt`, `act`
- City/town slugs: kebab-case, unique per parent (`parent_id` + `slug` composite unique)

---

## 3. Database Schema (Migration)

Extend `locations` table:

| Column | Type | Notes |
|--------|------|-------|
| `parent_id` | FK nullable → locations | Tree hierarchy |
| `type` | string | `state`, `city`, `town` |
| `excerpt` | text nullable | SEO meta fallback |
| `content` | longText nullable | Optional admin override |
| `status` | string default `published` | draft / published |
| `published_at` | timestamp nullable | Scheduling |

**Constraints:** Drop global unique on `slug`; add `unique(['parent_id', 'slug'])`.

**Model relationships:** `parent()`, `children()`, scopes `states()`, `cities()`, `towns()`, `published()`, `url()`.

---

## 4. Content Strategy (`LocationPageBuilder`)

Mirror `IndustryPageBuilder` pattern — static profiles with dynamic interpolation:

| Section | Purpose |
|---------|---------|
| Hero title/subtitle | “Remote Staffing in {City}, {State}” |
| Stats strip | Placements, savings, match time (location-personalised labels) |
| Intro | Local business context |
| Challenges | Hiring pain in this area |
| Solutions | How Apex Admins helps locally |
| Recommended roles | Links to `/hire/{slug}` |
| FAQs | Location SEO long-tail (“VA in Parramatta”) |
| Nearby | Sibling towns or cities (internal links) |
| CTA band | Book consultation |

Page type variants:
- **State:** overview + city grid + state-wide stats
- **City:** full detail sections + town grid
- **Town:** full detail sections + nearby towns

---

## 5. SEO Architecture

### Per-page meta (`LocationSeoService`)

- Title: `{Location} Remote Staffing — {Site}` or admin `seo_meta` override
- Description: unique per type with location name + service keywords
- Canonical: full nested URL
- OG image: location-relevant editorial photo

### JSON-LD

| Page | Schema types |
|------|--------------|
| Hub | `CollectionPage`, `ItemList` (states), `BreadcrumbList` |
| State | `CollectionPage`, `ItemList` (cities), `BreadcrumbList` |
| City/Town | `LocalBusiness` (areaServed), `BreadcrumbList`, `FAQPage` |

### Sitemap

- `/locations` hub
- All published state/city/town URLs with `lastmod`, priority by depth (state 0.7, city 0.65, town 0.6)

### Internal linking

- Hub → states → cities → towns (breadcrumbs + grids)
- Location pages → hire roles + industries
- Footer optional “Popular locations” links

---

## 6. Navigation

### `LocationNavCatalog`

- Mega menu categories = **Australian states** (8 groups)
- Items = **capital + major cities** per state (top 4–6)
- Hub link: “View all locations” → `/locations`
- Registered in `SharePublicData` as `navMegaMenus['locations']`

### Header

- Add `locations` to `$megaTypes` in `header.blade.php` and `mobile-nav.blade.php`
- Menu seeder: add `{ title: 'Locations', url: '/locations', icon: 'location' }`

### Mega menu UI

- Custom `location-mega-menu` OR extend mega panel with state columns
- Each state column: state link + city links beneath

---

## 7. Public Views

| View | File |
|------|------|
| National hub | `pages/locations/index.blade.php` |
| State / City / Town detail | `pages/locations/detail.blade.php` (shared, `$page` array from builder) |
| Card partial | `pages/locations/_card.blade.php` |
| Hierarchy explorer | `pages/locations/_explorer.blade.php` (hub interactive UI) |

### Hub UI (advanced)

- Desktop: 3-column explorer (States | Cities | Towns) with live selection
- Mobile: accordion by state
- Search/filter input for towns (Alpine.js)
- Visual count badges per state

### Detail UI

- `detail-hero` + stats strip
- Editorial split (photo + intro)
- Challenge/solution benefit grids
- Recommended roles (`home-card-grid`)
- FAQ accordion (`home-faq--panel`)
- Child location grid (cities or towns)
- Contextual `cta-band`

---

## 8. Admin (Phase 2 — post-launch enhancement)

| Item | Priority |
|------|----------|
| Fix `$record` bug in edit | P0 (included in Phase 1) |
| Parent picker + type selector | P1 |
| Hierarchical admin list | P2 |
| Section override in admin | P2 |

Phase 1 uses seeder + PageBuilder; admin CRUD remains flat-compatible.

---

## 9. Data Seeder

**File:** `database/seeders/LocationHierarchySeeder.php`  
**Source:** `app/Support/AustraliaLocations.php`

| Level | Count (target) |
|-------|----------------|
| States/territories | 8 |
| Cities | ~45 (capitals + major regional centres) |
| Towns | ~180 (5–8 per city) |

Run via `DatabaseSeeder` or documented artisan command.

---

## 10. Implementation Phases

### Phase 1 — Foundation ✅
- [x] Migration: hierarchy columns
- [x] Update `Location` model (relationships, scopes, `publicUrl()`)
- [x] `AustraliaLocations.php` data file
- [x] `LocationHierarchySeeder`

### Phase 2 — Content & SEO services
- [x] `LocationPageBuilder`
- [x] `LocationSeoService`
- [x] `PageImages::forLocation()`

### Phase 3 — Routes & controllers
- [x] Nested routes in `web.php`
- [x] `LocationController`: index, state, city, town
- [x] Breadcrumb resolver walking tree

### Phase 4 — Public UI
- [x] Hub index with hierarchy explorer
- [x] Detail template (all levels)
- [x] Location CSS (`location-*` in `app.css`)

### Phase 5 — Navigation
- [x] `LocationNavCatalog`
- [x] `SharePublicData` registration
- [x] Header + mobile nav + menu seeder

### Phase 6 — SEO integration
- [x] Sitemap nested URLs + published filter
- [x] OG article tags N/A; LocalBusiness on detail
- [x] Fix admin edit SEO load bug

### Phase 7 — Verification
- [x] Seed & smoke-test URLs
- [x] Validate JSON-LD (Rich Results)
- [x] `npm run build` + `view:clear`

---

## 11. File Inventory (New / Modified)

### New
```
app/Support/AustraliaLocations.php
app/Support/LocationPageBuilder.php
app/Support/LocationNavCatalog.php
app/Modules/Locations/Services/LocationSeoService.php
app/Modules/Locations/Services/LocationQueryService.php
database/migrations/2026_07_10_000001_add_hierarchy_to_locations_table.php
database/seeders/LocationHierarchySeeder.php
resources/views/pages/locations/index.blade.php
resources/views/pages/locations/detail.blade.php
resources/views/pages/locations/_card.blade.php
resources/views/pages/locations/_explorer-state.blade.php
```

### Modified
```
app/Modules/Locations/Models/Location.php
app/Modules/Locations/Http/Controllers/Web/LocationController.php
app/Http/Middleware/SharePublicData.php
app/Modules/SEO/Services/SitemapService.php
app/Support/PageImages.php
routes/web.php
resources/views/components/header.blade.php
resources/views/components/mobile-nav.blade.php
resources/css/app.css
database/seeders/ContentSeeder.php (menu item)
```

---

## 12. SEO Copy Templates

**State title:** `{State} Remote Staffing & Virtual Assistants — Apex Admins`  
**City title:** `Hire Remote Staff in {City}, {State} — Apex Admins`  
**Town title:** `Virtual Assistants in {Town}, {City} — Apex Admins`

**Description pattern:** `Apex Admins helps {location} businesses hire vetted virtual assistants, marketers, and ops staff in AEST — shortlists in days, up to 60% savings.`

---

## 13. Success Metrics

- All seeded URLs return HTTP 200
- Unique `<title>` and `<meta description>` per page
- Valid `BreadcrumbList` + `LocalBusiness` in JSON-LD
- Locations appear in header mega menu
- Sitemap includes all location URLs
- Lighthouse SEO ≥ 95 on sample city page

---

*This document governs implementation order. Execute phases sequentially; mark checkboxes as completed during delivery.*
