Analyser/Docs
Documentation menu

Pages

Every top-level HTML page in web/, what it's for, and any wiring specific to it. All pages share the same generated head tail and footer (see the shared-partials skill) and are boot()-ed by the same app.js entry point, with per-page behaviour guarded by element presence so a page with no matching DOM is an inert no-op for that feature.

On this page

index.html (/)#

The drop-and-analyse app - the whole point of the site. Structure:

  • A boot splash (#splash) that fades out once app.js's boot() runs, with a failsafe reveal if the module graph is slow.
  • The "quickdrop" zone: two layouts coexist in the markup, toggled by the quickdrop--hero class on the <section> - a three-card grid (photoDrop/audioDrop/videoDrop, each with its own accept filter) or a single "any file" hero dropzone (heroDrop) plus a Compare CTA linking to /compare. Both stay wired in boot().
  • Mic recording (audioRecord/heroRecord) and live spectrogram (audioLive/heroLive) buttons alongside the audio/hero zones.
  • The format-info overlay (#fmtOverlay), generated from formats.js's catalog by format-overlay.js - searchable, category-chip filtered.
  • Three result sections (#photo, #audio, #video), each with a section-meta aside (preview/histogram/OCR slots for photo, a preview slot for video) and an anr-results container filled by the matching renderer. A generic #unknownResults container above them catches every non-media kind.
  • #formatGuideCta - a post-analysis link into that extension's /formats/<ext> page, filled and revealed by handleFile().
  • The footer's "Recently analysed" panel (localStorage history) and the shared offline-tiers/dependencies footer block.
  • <script src="assets/js/core/navigate.js"> (classic script, runs before the module graph) then <script type="module" src="assets/js/core/app.js">, plus inline service-worker registration with auto-reload-once on controllerchange.
  • Rich SEO: Open Graph/Twitter meta, two JSON-LD blocks (WebApplication + WebSite with a SearchAction), and modulepreload hints for the hot-path core modules (deliberately excluding the long-tail renderers, which stay lazy).

about.html (/about)#

A single scrollable page of sections (each <section class="section" id="..."> with an #anchor), covering: #why (rationale), #where (offline/local-first), #what (#aboutFormats - the full format catalog table, generated by format-overlay.js's renderAboutFormats()), #how (usage instructions), #faq. Also carries its own copy of the format overlay (#fmtOverlay) so format search works here too.

compare.html (/compare)#

See "The /compare page" in the repo root CLAUDE.md for the full design. In brief: two "any file" dropzones (#cmpDropA/#cmpDropB), each wired by wireCompareZone() in boot() (app.js:983) to capture a File directly - not through the normal handleFile pipeline. Once both are set, handleCompare() (app.js:1011) runs; the actual merge logic lives in renderers/compare.js (see cross-cutting.md). The page-level drag/drop overlay is suppressed here: onComparePage() (app.js:1261, detected via document.getElementById('cmpDropA')) makes the global dragenter/dragover handlers skip showing #pageDrop, so only the two named zones light up on drag, and a stray drop outside them is swallowed rather than routed into the single-file pipeline (this page has no #photo/#audio/#video sections for it to land in). Results render into a shared #unknownResults container.

stats.html (/stats)#

Public analytics page. #statsRoot holds total files-analysed and visitors counts, a per-extension breakdown table (.stats-table / #statsExtBody, with a Show all toggle), a trend chart (#statsTrendsChart with mode buttons), and a leaderboard (#statsScoresList). All populated by setupStatsPage() (web/assets/js/core/stats-page.js, imported and called near the end of boot() - app.js:1668), which reads the Worker's /api/stats endpoint. See worker.md.

patch.html (/patch)#

The public changelog: one .patch-entry per commit (auto-generated content, not hand-authored per this doc's scope - see save.bat's version-bump flow in tooling.md). Also carries a "tl;dr" release-group digest toggle, wired by setupPatchTldr() (web/assets/js/core/patch-tldr.js, called unconditionally in boot() at app.js:1739 - a no-op on every other page).

privacy.html (/privacy)#

Three sections: "Your files never leave your device" (the core promise), "What the two counters do" (explaining the visit/analysed-file stats - see worker.md), and "The small print, kept small" (the actual policy text). Static content page; no special JS wiring beyond the shared boot/footer.

atari.html (/atari)#

An unlisted Asteroids easter-egg page reusing the stats page's markup pattern (#statsRoot, #statsScores for its own leaderboard). An #atariPlay button, guarded by presence and a _wired flag against double-binding on SPA re-navigation (app.js:1673-1679), lazily imports ../games/asteroids.js and calls launchAsteroids() only when clicked - the game code (web/assets/js/games/) never loads on any other page. A hidden #atariReset dev-only button clears cache and reloads.

test.html (/test)#

CLAUDE.md documents this as a deployed-but-unlisted (noindex, unlinked) style-guide reference page - every design token, font, animation, button, control, chip, card, message, popup, loader and viewer overlay the site uses, with an in-page theme toggle, its tokens/animations generated from analyser.css by tools/prerender-testpage.mjs. As of this writing the file does not exist in the working tree (verified: no web/test.html on disk) - could not confirm its current contents from source. Per project memory, this page is intentionally left untouched and not kept in sync with new UI components regardless of what CLAUDE.md's authoring guidance says.