disclosure-bureau/web/components/search-panel.tsx

293 lines
11 KiB
TypeScript
Raw Normal View History

/**
* SearchPanel full hybrid_search page with form controls and rich result cards.
*
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
* Magazine palette (gold + cream), localised copy, no developer jargon. The
* advanced filters (chunk type, exact doc-id) are tucked behind a toggle so
* the default state is one clean search input. Each result card shows the
* bbox-cropped image plus snippet so the reader sees a piece of the original
* page, not just the text.
*
* Syncs URL params so results are shareable.
*/
"use client";
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
import { Search as SearchIcon, SlidersHorizontal } from "lucide-react";
W0+W1+W1.2: security hardening, observability, autocomplete, glitchtip, forgejo CI W0 — security hardening (5 fixes verified live on disclosure.top) - middleware: gate /api/admin/* same as /admin/* (F1) - imgproxy: tighten LOCAL_FILESYSTEM_ROOT from / to /var/lib/storage (F2) - studio: real basic-auth label (bcrypt hash, middleware reference) (F3) - relations: ENABLE ROW LEVEL SECURITY + public SELECT policy (F4) - migration 0003: fold is_searchable + hybrid_search update into canonical (TD#2) W1 — observability + resilience + autocomplete - studio: HOSTNAME=0.0.0.0 so Next.js binds on loopback for healthcheck - compose: PG_POOL_MAX=20, CLAUDE_CODE_OAUTH_TOKEN gated by separate env - claude-code.ts: subprocess timeout configurable (CLAUDE_CODE_TIMEOUT_MS) - openrouter.ts: retry with exponential backoff + Retry-After + in-memory circuit breaker (promotes FALLBACK after CB_THRESHOLD failures) - lib/logger.ts: pino logger (NDJSON prod / pretty dev) + withRequest helper - middleware: mints correlation_id, stamps x-correlation-id response header, emits structured http_request log per /api/* call - messages/route.ts: switch to structured logger - 60_meili_index.py: push documents + chunks into Meilisearch - /api/search/autocomplete: parallel meili search (docs + chunks), 5-8ms p50 - search-autocomplete.tsx: debounced dropdown wired into search-panel W1.2 — Glitchtip + Forgejo self-hosted - compose: glitchtip-redis + glitchtip-web + glitchtip-worker (v4.2) - compose: forgejo + forgejo-runner (server v9, runner v6) with group_add=988 - @sentry/nextjs SDK wired (instrumentation.ts + sentry.{client,server}.config.ts) - /api/admin/throw smoke endpoint (gated by W0-F1 middleware) - Synthetic event ingestion verified at glitchtip.disclosure.top - forgejo.disclosure.top up, repo discadmin/disclosure-bureau created, runner registered (labels: ubuntu-latest, docker) - .forgejo/workflows/ci.yml: typecheck + lint + build + npm audit + python syntax + compose validation Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 21:18:42 +00:00
import { SearchAutocomplete } from "./search-autocomplete";
interface Hit {
chunk_id: string;
doc_id: string;
page: number;
type: string;
bbox: { x: number; y: number; w: number; h: number } | null;
classification: string | null;
snippet: string;
score: number;
href: string;
}
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
const COPY = {
"pt-br": {
placeholder: "ex.: objetos esféricos sobre Kansas, MJ-12, Tic-Tac do Nimitz…",
search: "Buscar",
searching: "Buscando…",
advanced: "Filtros avançados",
type_label: "Tipo de trecho",
type_any: "qualquer",
doc_label: "Restringir a um documento",
doc_placeholder: "doc-id exato (opcional)",
empty: "Nenhum resultado para essa busca.",
error_prefix: "Busca indisponível: ",
types_map: {
paragraph: "parágrafo",
heading: "título",
image: "imagem",
stamp: "carimbo",
signature: "assinatura",
table_marker: "tabela",
address_block: "endereço",
form_field: "formulário",
classification_marking: "marcação de classificação",
redaction: "redação",
} as Record<string, string>,
},
en: {
placeholder: "e.g. spherical objects over Kansas, MJ-12, Nimitz Tic-Tac…",
search: "Search",
searching: "Searching…",
advanced: "Advanced filters",
type_label: "Passage type",
type_any: "any",
doc_label: "Limit to one document",
doc_placeholder: "exact doc-id (optional)",
empty: "No results for this search.",
error_prefix: "Search unavailable: ",
types_map: {
paragraph: "paragraph",
heading: "heading",
image: "image",
stamp: "stamp",
signature: "signature",
table_marker: "table",
address_block: "address block",
form_field: "form field",
classification_marking: "classification marking",
redaction: "redaction",
} as Record<string, string>,
},
} as const;
export function SearchPanel({
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
locale = "pt-br",
initialQ,
initialLang,
initialType,
initialDocId,
}: {
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
locale?: "pt-br" | "en";
initialQ: string;
initialLang: "pt" | "en";
initialType: string;
initialDocId: string;
}) {
const router = useRouter();
const params = useSearchParams();
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
const t = COPY[locale];
const [q, setQ] = useState(initialQ);
const [type, setType] = useState(initialType);
const [docId, setDocId] = useState(initialDocId);
const [hits, setHits] = useState<Hit[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
const [advancedOpen, setAdvancedOpen] = useState(Boolean(initialType || initialDocId));
// Initial fetch if URL had params
useEffect(() => {
if (initialQ) doSearch(initialQ, initialLang, initialType, initialDocId);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
async function doSearch(qStr: string, l: "pt" | "en", typ: string, d: string) {
if (!qStr.trim()) return;
setLoading(true);
setError(null);
const sp = new URLSearchParams({ q: qStr, lang: l, top_k: "25" });
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
if (typ) sp.set("type", typ);
if (d) sp.set("doc_id", d);
try {
const r = await fetch(`/api/search/hybrid?${sp}`);
if (!r.ok) {
const j = await r.json().catch(() => ({}));
setError(j.message ?? `HTTP ${r.status}`);
setHits([]);
return;
}
const j = (await r.json()) as { hits?: Hit[] };
setHits(j.hits ?? []);
} catch (e) {
setError((e as Error).message);
setHits([]);
} finally {
setLoading(false);
}
}
function submit(e: React.FormEvent) {
e.preventDefault();
const sp = new URLSearchParams(params.toString());
sp.set("q", q);
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
sp.set("lang", initialLang);
if (type) sp.set("type", type);
else sp.delete("type");
if (docId) sp.set("doc_id", docId);
else sp.delete("doc_id");
router.replace(`/search?${sp}`);
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
doSearch(q, initialLang, type, docId);
}
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
const PASSAGE_TYPES = [
"paragraph", "heading", "image", "stamp", "signature",
"table_marker", "address_block", "form_field",
"classification_marking", "redaction",
];
return (
<div>
<form
onSubmit={submit}
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
className="mb-10 rounded-2xl border border-[rgba(224,192,128,0.20)] bg-[rgba(224,192,128,0.03)] p-4 md:p-5"
>
W0+W1+W1.2: security hardening, observability, autocomplete, glitchtip, forgejo CI W0 — security hardening (5 fixes verified live on disclosure.top) - middleware: gate /api/admin/* same as /admin/* (F1) - imgproxy: tighten LOCAL_FILESYSTEM_ROOT from / to /var/lib/storage (F2) - studio: real basic-auth label (bcrypt hash, middleware reference) (F3) - relations: ENABLE ROW LEVEL SECURITY + public SELECT policy (F4) - migration 0003: fold is_searchable + hybrid_search update into canonical (TD#2) W1 — observability + resilience + autocomplete - studio: HOSTNAME=0.0.0.0 so Next.js binds on loopback for healthcheck - compose: PG_POOL_MAX=20, CLAUDE_CODE_OAUTH_TOKEN gated by separate env - claude-code.ts: subprocess timeout configurable (CLAUDE_CODE_TIMEOUT_MS) - openrouter.ts: retry with exponential backoff + Retry-After + in-memory circuit breaker (promotes FALLBACK after CB_THRESHOLD failures) - lib/logger.ts: pino logger (NDJSON prod / pretty dev) + withRequest helper - middleware: mints correlation_id, stamps x-correlation-id response header, emits structured http_request log per /api/* call - messages/route.ts: switch to structured logger - 60_meili_index.py: push documents + chunks into Meilisearch - /api/search/autocomplete: parallel meili search (docs + chunks), 5-8ms p50 - search-autocomplete.tsx: debounced dropdown wired into search-panel W1.2 — Glitchtip + Forgejo self-hosted - compose: glitchtip-redis + glitchtip-web + glitchtip-worker (v4.2) - compose: forgejo + forgejo-runner (server v9, runner v6) with group_add=988 - @sentry/nextjs SDK wired (instrumentation.ts + sentry.{client,server}.config.ts) - /api/admin/throw smoke endpoint (gated by W0-F1 middleware) - Synthetic event ingestion verified at glitchtip.disclosure.top - forgejo.disclosure.top up, repo discadmin/disclosure-bureau created, runner registered (labels: ubuntu-latest, docker) - .forgejo/workflows/ci.yml: typecheck + lint + build + npm audit + python syntax + compose validation Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 21:18:42 +00:00
<div className="relative">
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<div className="flex items-stretch gap-2">
<div className="relative flex-1">
<span className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-[#9aa6b8]">
<SearchIcon size={16} aria-hidden="true" />
</span>
<input
value={q}
onChange={(e) => setQ(e.target.value)}
placeholder={t.placeholder}
aria-label={t.search}
className="w-full bg-[#0a0e1a] border border-[rgba(224,192,128,0.25)] focus:border-[#e0c080] rounded-full pl-10 pr-4 py-3 font-display text-[15px] md:text-[16px] text-[#e7ecf3] placeholder:text-[#5a6678] outline-none transition-colors"
autoFocus
/>
<SearchAutocomplete query={q} onPick={() => setQ("")} />
</div>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<button
type="submit"
disabled={!q.trim() || loading}
className="px-5 md:px-6 py-3 font-mono text-[12px] uppercase tracking-widest border border-[#e0c080] text-[#0a0e1a] bg-[#e0c080] hover:bg-[#f0d4a0] rounded-full transition-colors disabled:opacity-40 disabled:cursor-not-allowed"
>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
{loading ? t.searching : t.search}
</button>
</div>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
</div>
<div className="mt-3 flex items-center justify-between">
<button
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
type="button"
onClick={() => setAdvancedOpen((v) => !v)}
aria-expanded={advancedOpen}
className="inline-flex items-center gap-1.5 text-[11px] font-mono uppercase tracking-wider text-[#9aa6b8] hover:text-[#e0c080] transition-colors"
>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<SlidersHorizontal size={12} aria-hidden="true" />
<span>{t.advanced}</span>
<span aria-hidden="true">{advancedOpen ? "" : "+"}</span>
</button>
</div>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
{advancedOpen && (
<div className="mt-4 grid md:grid-cols-2 gap-4 pt-4 border-t border-[rgba(224,192,128,0.15)]">
<div>
<label className="font-mono text-[10px] uppercase tracking-widest text-[#9aa6b8] block mb-1.5">
{t.type_label}
</label>
<select
value={type}
onChange={(e) => setType(e.target.value)}
className="w-full bg-[#0a0e1a] border border-[rgba(224,192,128,0.25)] focus:border-[#e0c080] rounded px-3 py-2 font-mono text-[12px] text-[#e7ecf3] outline-none"
>
<option value="">{t.type_any}</option>
{PASSAGE_TYPES.map((typeKey) => (
<option key={typeKey} value={typeKey}>
{t.types_map[typeKey] ?? typeKey}
</option>
))}
</select>
</div>
<div>
<label className="font-mono text-[10px] uppercase tracking-widest text-[#9aa6b8] block mb-1.5">
{t.doc_label}
</label>
<input
value={docId}
onChange={(e) => setDocId(e.target.value)}
placeholder={t.doc_placeholder}
className="w-full bg-[#0a0e1a] border border-[rgba(224,192,128,0.25)] focus:border-[#e0c080] rounded px-3 py-2 font-mono text-[12px] text-[#e7ecf3] placeholder:text-[#5a6678] outline-none"
/>
</div>
</div>
)}
</form>
{error && (
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<div className="mb-6 p-3 border border-[rgba(255,107,107,0.30)] bg-[rgba(255,107,107,0.05)] rounded font-mono text-[12px] text-[#ff6b6b]">
{t.error_prefix}{error}
</div>
)}
<div className="space-y-3">
{hits.map((h) => {
const cropUrl = h.bbox
? `/api/crop?doc=${encodeURIComponent(h.doc_id)}&page=${h.page}` +
`&x=${h.bbox.x}&y=${h.bbox.y}&w=${h.bbox.w}&h=${h.bbox.h}&w_px=320`
: null;
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
const typeLabel = t.types_map[h.type] ?? h.type;
return (
<Link
key={`${h.doc_id}-${h.chunk_id}`}
href={h.href}
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
className="block p-4 bg-[#0d1220] border border-[rgba(224,192,128,0.18)] hover:border-[#e0c080] rounded-xl transition-colors flex gap-4"
>
{cropUrl && (
<Image
src={cropUrl}
alt=""
width={160}
height={100}
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
className="block w-40 h-24 object-cover bg-black rounded-md flex-shrink-0"
unoptimized
/>
)}
<div className="min-w-0 flex-1">
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<div className="flex items-center gap-2 text-[10px] font-mono uppercase tracking-wider mb-1.5">
<span className="text-[#e0c080]">p{h.page}</span>
<span className="text-[#5a6678]" aria-hidden="true">·</span>
<span className="text-[#9aa6b8]">{typeLabel}</span>
{h.classification && (
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<>
<span className="text-[#5a6678]" aria-hidden="true">·</span>
<span className="text-[#ff9696]">{h.classification}</span>
</>
)}
</div>
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<p className="text-[#e7ecf3] text-[14px] leading-relaxed line-clamp-3 mb-1.5">{h.snippet}</p>
<div className="text-[10px] font-mono text-[#5a6678] truncate">{h.doc_id}</div>
</div>
</Link>
);
})}
</div>
{!loading && !error && initialQ && hits.length === 0 && (
ux(search): redesign /search from dev-tool to magazine The audit's most ostensive gap: /search rendered as a green-on-black terminal panel with a tech-jargon eyebrow ("HYBRID SEARCH · BM25 + BGE-M3 DENSE + CROSS-ENCODER RERANK"), no global navbar, and a floating locale toggle disconnected from the rest of the site. Readers landing here saw a different product. Page (app/search/page.tsx): - Render SiteHeader at the top (same primary nav as home; "Search" now picks up the gold active-page indicator). - Magazine hero: eyebrow + serif headline ("Find a passage, a witness, a date." / "Encontre uma passagem, uma testemunha, uma data.") + lead. - generateMetadata() reads getLocale() so the tab title localises too. Panel (search-panel.tsx): - Drop matrix-green palette; switch to magazine gold/cream. - Rounded input with magnifier icon, gold solid submit pill. - Plain-language placeholder, no developer terms. - "Advanced filters" toggle: passage-type + exact doc-id behind a collapsible — default state is one clean search box. - Localise passage-type labels (paragraph → parágrafo, heading → título, classification_marking → marcação de classificação, etc). - Result card palette switched to gold/cream + clearer page · type · classification line; raw retrieval score removed from the UI (debug noise for users). - Locale toggle inside the form gone — the navbar carries it now. Follow-ups noted (not in this commit): - SearchAutocomplete dropdown still uses the old terminal palette. - Navbar wraps on narrow mobile widths and the rightmost links overflow. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 20:58:41 +00:00
<div className="text-center text-[#5a6678] font-mono text-[13px] py-12">
{t.empty}
</div>
)}
</div>
);
}