# Entity → Schema Type Map (source-to-schema, pre-launch)

Maps the source/entity kinds collected in steps 1–2 to schema.org types, and lists the
Google rich-result requirements each type must satisfy. Required/recommended columns are
kept in sync with `16-seo-schema-validator/scripts/schema_rules.json` so drafts pass the gate.

## Type map

| Source / entity | Type | Google required | Key recommended | Cardinality |
|-----------------|------|-----------------|-----------------|-------------|
| Corporate/legal (DART, official About) | `Organization` | `name`, `url` | `logo`, `sameAs`, `address`, `contactPoint` | 1 per legal entity |
| Per-language site | `WebSite` | `name`, `url` | `inLanguage`, `publisher` | 1 per language |
| Hotel property | `Hotel` | `name`, `address` | `telephone`, `priceRange`, `geo`, `image`, `brand` | 1 per property × language |
| Executive / person | `Person` | `name` | `jobTitle`, `worksFor`, `sameAs`, `url` | 1 per person |
| Recruitment posting | `JobPosting` | `title`, `description`, `datePosted`, `hiringOrganization`, `jobLocation` | `validThrough`, `employmentType`, `baseSalary` | 1 per open role |
| Official video | `VideoObject` | `name`, `description`, `thumbnailUrl`, `uploadDate` | `duration`, `contentUrl`, `embedUrl` | 1 per featured video |
| FAQ / press-kit Q&A | `FAQPage` | `mainEntity` (Question→Answer) | `inLanguage`, `url` | 1 per FAQ page |
| Site navigation | `BreadcrumbList` | `itemListElement` | — | 1 per page |

Note: `JobPosting` and `VideoObject` were added to the validator rule set for this workflow,
since recruitment sites and the official YouTube channel are listed source types.

## Address requirement nuance (avoid false P0)

`PostalAddress` requires only `addressLocality` + `addressCountry` as the context-safe minimum.
`streetAddress` is **recommended** (P2), because it is expected for `Hotel`/`LocalBusiness` NAP
but NOT required by Google for `JobPosting.jobLocation` (city/region/country suffices). For
hotels, the L4 NAP-consistency check still enforces a complete, identical street address across
all pages of a property — so the street address signal is not lost where it matters.

## Brand-tier rule (Shilla)

- The Shilla, Shilla Monogram → `Hotel`
- Shilla Stay → `Hotel` (preferred; it is lodging, not a generic LocalBusiness)
- Always set `brand.name` (e.g. "The Shilla", "Shilla Monogram", "Shilla Stay") and link
  `parentOrganization.@id` back to the single `Organization` node.

## @id entity graph (critical for pre-launch coherence)

Author stable `@id` URIs and cross-reference them so search engines read the portfolio as one
connected entity graph rather than disconnected snippets:

```
Organization  @id = https://www.shillahotels.com/#org
   ▲ parentOrganization        ▲ publisher          ▲ hiringOrganization   ▲ worksFor / publisher
   │                           │                     │                      │
Hotel (per property)      WebSite (per lang)     JobPosting             Person / VideoObject
```

Rules
- One `Organization` node, one `@id`, referenced by every other node via `@id`.
- `@id` must be an absolute, stable URI (the provisional production URL + a `#fragment`).
- Every `@id` referenced must also be defined somewhere in the dataset (the validator's L4
  checks for dangling `@id` references).

## When NOT to author schema
- Authenticated/transactional pages (mypage, login, booking cart) → no schema.
- Thin or duplicate pages → no schema until content exists.
- Any entity whose facts are still `conflict`/`PENDING` → resolve first (builder excludes them).
