2026-05-19 — NCBI-aligned BLAST results UX¶
Motivation¶
Researchers transitioning from NCBI Web BLAST to ElasticBLAST kept asking "where are the hits?" because the result entry-point was a file-list page, not an alignments table. The page also used software-engineering vocabulary ("Job", "Duplicate", "Analytics") instead of the BLAST-domain language they expected ("Search", "Edit search", "Descriptions"). This change ports the NCBI Web BLAST information architecture to the elb-dashboard so a researcher can navigate the same way they always have.
User-facing change¶
/blast/jobs/:jobIdis now a single tabbed page in NCBI's tab order:
| Tab | Equivalent on NCBI | New in this PR |
|---|---|---|
| Descriptions | "Sequences producing significant alignments" | only the page restructure — table itself existed under /analytics |
| Graphic Summary | identical | YES — new component, query ruler with NCBI score-binned bars |
| Alignments | identical | only the page restructure |
| Taxonomy | "Reports → Organism" | YES — frontend rollup of sscinames / staxids |
| Files | (ElasticBLAST-only) | moved here from the old root-level Results card |
| Run details | (ElasticBLAST-only) | moved here from the old root-level cards |
The legacy /blast/jobs/:id/analytics route still resolves — it now
redirects to ?tab=descriptions for bookmark compatibility.
-
Active tab is encoded in
?tab=...so deep-links and the browser back/forward buttons keep working. -
Job header now matches NCBI's 7-line metadata grid (Search ID, Submitted, Program, Database, Query ID, Molecule type, Description, Query length, E-value cutoff, Cluster, Region). The previous header hid the program/database behind a sub-card.
-
Duplicatebutton renamed to Edit search (NCBI's term), promoted to primary.Export configrenamed to Save settings. A new Download all combo dropdown next to "Submitted" exports every shard's hits as CSV / TSV / JSON. -
Filter bar now offers from-to range inputs for Identity %, HSP cover, Max E. An explicit Apply / Reset pair plus an active-filter chip row mirrors NCBI's "Filter Results" panel — no more refetching on every keystroke. Page-size selector (10 / 50 / 100 / 250) added.
-
Descriptions table gains row checkboxes + select-all with a sticky action bar (
N selected · Download selection (FASTA) · Send to MSA Viewer · Clear). The MSA Viewer action opens NCBI's MSA Viewer with the selected accessions pre-loaded. -
Per-hit Accession links now deep-link to NCBI nuccore (
ncbi.nlm.nih.gov/nuccore/<acc>) instead of a generic search URL. -
Graphic Summary applies the canonical NCBI score color palette (<40 black, 40-50 blue, 50-80 green, 80-200 magenta, ≥200 red) with the same legend NCBI uses.
-
Alignments cards now show the NCBI stat line —
Identities 462/462 (100%),Gaps N/total (pct), Strand: Plus/Plus or Plus/Minus — instead of percent-only. -
Copy / terminology:
- Nav "Jobs" → Recent searches
- Page title "ElasticBLAST Jobs" → Recent BLAST searches
Cancel Job/Delete BLAST Job→Cancel search/Delete BLAST searchLoading BLAST jobs…→Loading BLAST searches…No hits found→ No significant similarity foundNo BLAST result files (.out) found in results/<id>/→ No significant similarity found. BLAST returned no hits for this query/database combination.-
No results available — the job failed at the X step→ Search failed during the X step. Open the Run details tab for diagnostics. -
Sticky tab bar at the top of the result page so tabs stay reachable when scrolling a long hit list.
API / IaC diff summary¶
- No backend changes. Backend already exposes
/api/blast/jobs/{id}/results/aggregate,/api/blast/jobs/{id}/results/alignments,/api/blast/jobs/{id}/results/export. The Taxonomy tab does a frontend rollup ofsscinames/staxidsreturned by alignments; if a server-side rollup is needed later, the UI shape underTaxonomyPanel.rollupByOrganismmatches what an endpoint should return. - No IaC changes.
Files touched¶
New components (all under web/src/pages/blastResults/):
BlastResultsTabs.tsx— sticky tab bar + URL <-> tab mappinganalytics/helpers.ts— shared formatters + NCBI score-color paletteanalytics/useBlastAnalyticsState.ts— queries, filter state, selectionanalytics/DegradedBanner.tsxanalytics/ResultFilterBar.tsx— range inputs + Apply/Reset + chipsanalytics/BlastHitsTable.tsx— bulk select + nuccore linksanalytics/AlignmentViewer.tsx— strand + identity fractionsanalytics/OverviewPanel.tsxanalytics/GraphicSummaryPanel.tsx(NEW — query ruler)analytics/TaxonomyPanel.tsx(NEW — organism rollup)analytics/DescriptionsTabBody.tsxanalytics/AlignmentsTabBody.tsx
Modified:
web/src/pages/BlastResults.tsx— tab orchestratorweb/src/pages/BlastAnalytics.tsx— 1381-line page → 20-line redirectweb/src/pages/blastResults/BlastJobHeader.tsx— NCBI 7-line + Edit search + Download allweb/src/pages/blastResults/BlastJobMetrics.tsx— points to?tab=descriptionsweb/src/pages/blastResults/BlastResultsTable.tsx— empty-state copyweb/src/pages/blastResults/ResultsBody.tsx— empty-state copyweb/src/components/Layout.tsx— nav label "Jobs" → "Recent searches"web/src/pages/BlastJobs/JobsHeader.tsx— title "ElasticBLAST Jobs" → "Recent BLAST searches"web/src/pages/BlastJobs/JobsEmptyState.tsx— empty-state copyweb/src/pages/BlastJobs/BlastJobs.tsx— confirm + loading copy
Validation evidence¶
npm run build— green (1 build, 6.82 s)npx eslint --max-warnings 0(scoped to touched files) — exit 0uv run pytest -q api/tests— 670 pass; 2 fails are pre-existing uncommitted WIP intest_external_blast_api.pyfor the not-yet- implementedexternal_degradedresponse field. No backend code in this change.- Dev server (
http://127.0.0.1:8090) —GET /returns 200,GET /blast/jobsreturns 200.
Intentionally deferred (not in scope)¶
The following items from the original UX gap analysis were skipped because they require backend work or are P2-only polish:
- Multi-HSP subject grouping in the Descriptions table (needs backend grouping logic).
- Total-score column (max + sum of HSPs per subject — needs backend aggregate change).
- Column-header click sort (current dropdown still functional).
- Filter sidebar layout (current top bar with range + Apply matches the same intent — promoted to sidebar would need a responsive split layout).
- Server-side Taxonomy tree with full lineage (current frontend rollup is page-local).
- Citation popover + Help / How-to-read dropdown.
?tab=alignmentsdeep-link from a Graphic Summary hit-bar click.