A Next.js 16 bioinformatics platform for genomics, metagenomics, and viral research, built on the BV-BRC (Bacterial and Viral Bioinformatics Resource Center) backend.
- Node.js v24 — required by Vitest 4 / rolldown. Use nvm:
nvm install 24 nvm use 24
- pnpm — the project's package manager:
npm install -g pnpm
pnpm installcp .example.env .env.localFill in .env.local with the appropriate values:
| Variable | Description |
|---|---|
USER_URL |
BV-BRC User Service URL |
USER_AUTH_URL |
BV-BRC Authentication Service URL |
USER_REGISTER_URL |
BV-BRC Registration Service URL |
USER_VERIFICATION_URL |
BV-BRC Email Verification Service URL |
USER_PASSWORD_RESET_URL |
BV-BRC Password Reset Service URL |
APP_BASE_URL |
This tier's public origin, declared on sign-up and jobs (required) |
APP_SERVICE_URL |
BV-BRC AppService — JSON-RPC endpoint for job submission |
INTERNAL_API_ORIGIN |
Trusted origin for server-side calls to this Next.js application |
DATA_SERVICE_URL |
BV-BRC Data Service URL |
NEXT_PUBLIC_DATA_API |
Public-facing data API endpoint |
SHOCK_ORIGINS |
Comma-separated Shock file storage node URLs |
DEFAULT_REALM |
Realm used when a BV-BRC token does not include one (default: bvbrc) |
All variables except
NEXT_PUBLIC_DATA_APIare server-side only and never exposed to the browser.
pnpm devOpen http://localhost:3019 in your browser.
pnpm dev # Start dev server with Turbopack on port 3019
pnpm build # Production build
pnpm start # Start production server
pnpm lint # ESLint
pnpm test # Vitest (run once)
pnpm test:watch # Vitest (watch mode)
pnpm test:coverage # Vitest with V8 coverage report| Route | Description |
|---|---|
/ |
Public home page — search, news, statistics |
/workspace/[username]/home/[[...path]] |
File browser for user workspaces |
/services/(category)/... |
Bioinformatics service submission forms (genomics, metagenomics, phylogenomics, protein-tools, utilities, viral-tools) |
/search/ |
Global search |
/jobs/ |
Job monitoring |
/api/auth/... |
Retained auth mutations and profile operations; current-user reads and sign-out are server APIs |
/api/services/... |
Proxied service API routes |
/api/workspace/... |
Proxied workspace API routes |
Authentication is a server-first integration with the BV-BRC identity service.
- Server Components call
getCurrentUser()and pass a browser-safe user to<AuthBoundary>; there is no browser session fetch or token inAuthUser. src/lib/auth/server/session.tsowns the HttpOnlybvbrc_token,bvbrc_user_id, and optionalbvbrc_realmcookies. They expire four hours after an identity-changing write and do not roll on reads.- Protected pages are optimistically gated by
src/proxy.ts; authoritative checks usegetCurrentUser()orwithAuth()server-side. - Browser mutations use named functions in
src/lib/auth/client.ts. Explicit sign-out uses a redirecting Server Action that clears cookies before navigation.
All backend calls use JSON-RPC 2.0 over HTTP POST, implemented in src/lib/jsonrpc-client.ts. Service wrappers:
AppService(src/lib/app-service.ts) — job management: enumerate, query, kill, and submit jobs viaAppService.start_app2.WorkspaceApiClient(src/lib/services/workspace/client.ts) — workspace CRUD operations.
- shadcn/ui (New York style, Slate base) built on
@base-ui/reactprimitives — components live insrc/components/ui/. - Tailwind CSS v4 with CSS variable theming and named themes in
src/app/globals.css. lucide-reactfor icons.sonnerfor toast notifications.
- TanStack Query for all async client-side state.
- TanStack Table for the workspace file listing (with virtual scrolling via TanStack Virtual).
- TanStack Form + Zod for service submission forms.
Tests use Vitest 4 with jsdom and Mock Service Worker (MSW) for API mocking.
- Test files live in
__tests__/directories next to the source they cover. - Globals (
describe,it,expect,vi) are available without importing. - Run
pnpm test:coverageto generate a V8 coverage report.
Before committing, always run:
pnpm lint
pnpm build
pnpm testThree GitHub Actions CI workflows run automatically on every PR targeting main: lint, build, and test. All must pass before merging.
- camelCase everywhere — all variables and constants, including module-level exports. No
SCREAMING_SNAKE_CASE(except OS-level env var names). - Module-level constants and types used by a service page belong in that service's
*-form-utils.tsfile, not inline in the component. - Do not commit without review — run the three pre-commit checks above and manually inspect the diff before committing.