What it is
sites.google.com/online.island.edu.hk looks like a dead link — it 404s with an empty body. It is actually the namespace for every Google Site the school ever published. Google Sites has no directory listing and no public API, so this is the reconstruction: search index, Wayback archive and on-site links unioned, then 164 candidate paths probed one by one — 11 public sites carrying ~800 nav entries, 153 that bounce to a Google sign-in, and a 2009–2013 graveyard of student project sites.
Version history
Straight from the project’s own card data — what each version added.
Google index only — 12 slugs, no idea what was missing
Archive + on-site links unioned, every path probed — 164 paths, 11 public, 153 gated
Files on the site
What broke, and what I’d change
Not written yet. This is the part only I can write — what actually went wrong, and what I’d do differently. It lives in builds/reflections/island-gsites.md (see _TEMPLATE.md); as soon as that file has words in it, this section fills in on the next build.
Everything else on this page — the spec, the version history, the file counts — is generated from the project’s own build notes and files, so nothing here is guesswork.
Build spec
The project’s own build notes, rendered. Open the raw .md ↗
Show the spec
Build spec — Island School Google Sites: how many paths sit behind one URL
Ask (21 Oct 2026): "how many /. are behind this link https://sites.google.com/online.island.edu.hk" → then "can you put it in my portfolio".
Deliverable: demos/island-gsites-teardown.html (recon page + live 164-path inventory), demos/island-gsites-data.json / .csv (dataset), portfolio card.
0. Acceptance test (written before building)
- Functional — the page states the real answer (11 public, 153 gated, 164 paths, ~800 nav
- Layout bar — no horizontal page scroll at 390 / 768 / 1440; inventory table needs no
entries), renders all 164 paths in a filterable/searchable table, and ships the dataset as JSON + CSV. No path list is fetched at runtime: the data is inline.
horizontal scroll on a phone (fixed layout, title merged under the slug); tap targets ≥ 44 px; evidence table stacks into cards below 600 px; empty-search state is explicit; focus-visible ring on every control; 0 console errors.
1. What the URL actually is
sites.google.com/online.island.edu.hk → HTTP 404, 0 bytes. It is a namespace, not a site. Each Site occupies one path segment under it. Google Sites exposes no directory listing, no sitemap index, and no public API that lists a domain's Sites.
2. Discovery legs (in order, each one leaks what the last missed)
site:sites.google.com/online.island.edu.hk, paginated 30 pages via real Chrome + CDP; CAPTCHA at page 8 → crawler self-aborts |/online.island.edu.hk/ and legacy /a/online.island.edu.hk/ |island.edu.hk + sitemap + live Sites nav HTML → found is-experiential-learning |<title> |Classification rule: 200 + real <title> + Sites markup ⇒ public; redirect to accounts.google.com ⇒ gated. Then re-check all 11 public with plain curl (no cookie jar) so a cached response cannot fake a pass.
3. Numbers (re-derive, never inherit)
- 164 distinct paths = 11 public + 153 gated
- ~800 public nav entries (Maths 196, French 135, Spanish 97, Japanese 84, Chinese 83,
- 162 archive slugs; 12 index slugs; 0 credentials used
- Nav entries are nav links, not certified page totals — say so on the page
Elements 77, Higher Ed 56, IBCP 36, CAS 16, Quest Week 13, GP Cookbook 7)
4. Page structure (kept from the teardown family)
hero + stat strip → "the link is not a site" callout → method (4 legs + chain diagram) → live inventory table (search / filter / copy / download, empty state) → the 11 public sites → the 153 gated list + what "gated" does not prove → honest limitation → evidence table → what's next → footer (Method + Honesty notes).
5. Verification actually run
- Playwright at 390 / 768 / 1440:
document.documentElement.scrollWidth - innerWidth == 0, - filter: Public → 11 rows, Gated → 153 rows; search
french→ 2 rows (/islandschoolfrench, #invscrollWidth == clientWidth at 390 (fixed layout +.tsubsecond line)- dataset downloads: JSON 200 / 12,468 B, CSV 200 / 4,687 B
- screenshots read back at 390 / 1440 and graded (hero, inventory, evidence, 153-list)
164 rows, minTap = 44, 0 console errors
/french-speaking-practice); search zzzznope → empty state visible, table hidden
6. Pitfalls hit
overflow-wrap:anywhereon a slug column breaks words mid-syllable (/islandschoo lfrench);- A 4-column inventory on a 390 px screen: hide Title/Nav and render them as a muted second line
- CSS
content:"\00b7"inside a Python f-string rendered as literal007— use the real·. - Auto table layout takes its min width from the longest unbreakable slug, so
break-wordalone
break-word + table-layout:fixed gives clean breaks at hyphens with zero horizontal scroll.
under the path (.tsub) instead of letting the table scroll.
does not stop overflow; only table-layout:fixed + explicit column widths does.
7. Honesty
164 is what is visible from outside. A Site never published, linked, crawled or archived is invisible to all four legs; an exact count needs the school's Sites dashboard. No account, token or sign-in wall was touched.