Developer documentation for the labs.primalscheme.com frontend.
This is a SvelteKit static site that:
- fetches the upstream primer scheme catalog at runtime
- flattens nested scheme metadata into list rows
- provides full-text search + combinatorial filtering
- renders detailed scheme pages with
info.json, bedfile, and reference assets
- SvelteKit (client-side rendered)
- Vite
- Fuse.js (search)
- Plotly (detail page plots)
- Vitest (unit tests)
- Playwright (integration tests)
@sveltejs/adapter-static(GitHub Pages build output)
src/routes/+layout.js sets:
ssr = falseprerender = falsetrailingSlash = 'always'
The app runs as a client-side SPA and fetches scheme data from GitHub raw URLs in the browser.
- Fetch upstream catalog from:
index.jsonaliases.json
- Flatten nested
primerschemesobject viasrc/lib/flattenedSchemes.js. - Build dynamic facet options (collections, authors, species, amplicon sizes).
- Build Fuse index and execute query search.
- Apply filters:
- AND across facet groups
- OR within most facet groups
- collection filter currently behaves as AND across selected collections
- Sync state into URL params (
q, status flags, collections, sidebar facets,pageNum). - Paginate and render result rows via:
src/routes/ResultsRow.sveltesrc/routes/Pagination.svelte
- Fetch and flatten upstream
index.jsonagain. - Resolve route params to a single scheme record.
- Fetch:
- scheme
info.json - primer bed file
- reference FASTA
- scheme
- Render:
- metadata sections
- status pill
- default or advanced amplicon plots
- downloadable raw assets
Expected shape (simplified):
{
"primerschemes": {
"<schemeName>": {
"<ampliconSize>": {
"<version>": {
"schemename": "...",
"ampliconsize": 400,
"schemeversion": "1.0.0",
"status": "validated",
"authors": ["..."],
"species": ["..."],
"collections": ["..."],
"info_json_url": "https://...",
"primer_bed_url": "https://...",
"reference_fasta_url": "https://..."
}
}
}
}
}Map of alias -> canonical schemename.
src/
lib/
flattenedSchemes.js
flattenedSchemes.test.js
StatusPill.svelte
assets/css/
routes/
+layout.js
+layout.svelte
+page.svelte
ResultsRow.svelte
Pagination.svelte
detail/[schemename]/[ampliconsize]/[version]/
+page.svelte
DefaultAmpliconPlot.svelte
AdvancedPlot.svelte
tests/
test.js
.github/workflows/
deploy.yml
- Node.js 18+ (CI uses Node 18)
- npm
npm installnpm run devnpm run build
npm run previewnpm run dev- local dev servernpm run build- production static build tobuild/npm run preview- serve built output locallynpm run lint- Prettier + ESLintnpm run format- apply Prettiernpm run test- integration + unit testsnpm run test:integration- Playwright tests intests/npm run test:unit- Vitest tests insrc/**/*.test.*
src/lib/flattenedSchemes.test.js- validates flattening behavior and alias array initialization
tests/test.js- mocks upstream network calls
- covers:
- homepage render
- query URL encoding
- error states
- detail route resolution
- status/collection filter URL behavior
- pagination behavior
Styling is mostly component-scoped Svelte CSS plus shared styles:
src/lib/assets/css/main.csssrc/lib/assets/css/pills.css
Status badges use src/lib/StatusPill.svelte for consistency between list and detail pages.
Deployment workflow: .github/workflows/deploy.yml
- Trigger: push to
main - Build job:
- installs dependencies
- runs
npm run build - uploads
build/artifact
- Deploy job:
- publishes uploaded artifact with
actions/deploy-pages
- publishes uploaded artifact with
Svelte adapter config is in svelte.config.js and writes to build/.
Current model is fully client-side and scales with upstream JSON size:
- initial load time depends on fetching/parsing full upstream catalog
- search/filter work runs in browser memory
For larger catalogs, consider:
- precomputed flattened JSON
- map-based alias joining
- worker-based filtering/search
- server-side search endpoint
- Keep URL-param behavior stable for filter/query state.
- Run
npm run lint. - Run
npm run test:unit. - Run
npm run test:integrationwhen modifying route behavior. - Run
npm run buildbefore opening a PR.
Default mode (local preview web server managed by Playwright):
npm run test:integrationExternal mode (for restricted runners where binding localhost is blocked):
PLAYWRIGHT_BASE_URL=http://localhost:4173 npm run test:integration:externalDebug mode (verbose Playwright web server/API logs):
npm run test:integration:debugNotes:
test:integrationstartsvite previewonhttp://127.0.0.1:4173with fast-fail startup timeout.test:integration:externaldisables PlaywrightwebServerand requiresPLAYWRIGHT_BASE_URL.- Preflight checks fail fast when external mode is enabled without
PLAYWRIGHT_BASE_URL.