import Link from "next/link"; import BrowseHeader from "@/components/BrowseHeader"; import PhraseConsole from "@/components/PhraseConsole"; import ShortlistBar from "@/components/ShortlistBar"; import { episodeIds, isEpisode, isFillerQuery, parsePhraseQuery, searchPhrases, MAX_TERMS, PAGE_SIZE, type PhraseResult, } from "@/lib/phrases"; import { listShortlists, readShortlist } from "@/lib/shortlist"; export const dynamic = "force-dynamic"; // THE PHRASE CONSOLE: every occurrence of a word or phrase across 300 episodes // of word-level ASR, with the timestamp that addresses both the sound and the // picture. // // A STATIC segment under app/browse/, so it wins over app/browse/[song]/ -- // which would otherwise catch /browse/find, fail readSong() and 404. The same // trap /browse/decisions documents, and the e2e suite asserts it here too, // because when this regresses the page still renders perfectly in isolation // and only the URL stops working. // // SEARCH IS `?q=` AND SERVER-RENDERED, over a plain