React + TypeScript single-page application for Virtool, a bioinformatics platform.
| Task | Command |
|---|---|
| Dev server | npm run develop (Vite, port 5173) |
| Typecheck | npm run typecheck |
| Lint + format | npm run check |
| Lint only | npm run lint |
| Format only | npm run format |
| Test (watch) | npm run test |
| Test (single run) | npx vitest run |
| Test (filtered) | npx vitest run src/path/to/file |
| Storybook | npm run storybook (port 6006) |
| Build | npm run build |
- After changing route files in
src/routes/: runnpx @tanstack/router-cli generateto regeneratesrc/routeTree.gen.tsbefore running type checks. - Before committing:
npm run checkandnpm run typecheck. - After changing tests: run the specific test file with
npx vitest run <path>. - Full test suite only when asked or when changes are cross-cutting.
- Always fix all lint errors and warnings. The main branch is guaranteed to pass
npm run checkcleanly, so any issues are caused by your changes — never dismiss them as pre-existing.
Source lives in src/. Each top-level directory is a feature module:
src/account/- User account managementsrc/administration/- Admin settingssrc/analyses/- Analysis workflowssrc/app/- App shell, routing, theme, shared utilitiessrc/base/- Shared UI components (buttons, dialogs, forms, tables, etc.)src/forms/- Form components and patternssrc/groups/- User groupssrc/hmm/,src/indexes/,src/ml/- Bioinformatics featuressrc/otus/,src/sequences/,src/references/,src/samples/- Core data modelssrc/subtraction/- Subtraction managementsrc/labels/,src/jobs/,src/uploads/- Supporting featuressrc/nav/- Navigationsrc/server/- Express SSR serversrc/tests/- Test setup, fakes, and API mockssrc/types/- Shared type definitions
Every feature directory has a @name alias (e.g., @app/utils, @base/Button,
@samples/api). The catch-all @/* maps to src/*. Prefer specific aliases over
@/.
- React 19 with React Compiler (babel plugin)
- wouter for routing
- React Query (
@tanstack/react-query) for server state - zustand for client state
- react-hook-form + zod v4 for forms and validation
- superagent for API calls (via
@app/api.tsclient) - styled-components for CSS-in-JS (legacy, still in use)
- Tailwind CSS v4 for utility styles (preferred for new code)
- Radix UI primitives for accessible components
- CVA (
class-variance-authority) for component variants - Lucide React for icons
Zod v4 schemas can be passed directly to validateSearch — @tanstack/zod-adapter
is not needed. Use .default() and .catch() for defaults and fallbacks.
Use the superagent-based client in src/app/api.ts. Feature API functions live in
each module's api.ts. API errors have the shape error.response?.body.message.
- Use Tailwind utility classes for new code.
- Use the
cn()function from@app/utilsfor conditional classes (combinesclsxtailwind-merge).
- Don't use arbitrary Tailwind classes like
max-h-[210px]. - Existing styled-components are fine to maintain; prefer Tailwind for new work.
- Design tokens and theme are in
src/app/theme.ts. Check there before inventing colors or spacing values. - Tailwind theme customization is in
src/app/style.cssvia@theme.
Ongoing projects are documented in docs/projects/. These correspond to Linear
projects. If your task relates to a project, check that directory for constraints,
mappings, or decisions that apply to your work.
- Remove styled-components:
docs/projects/remove-styled-components.md
- Team: Virtool
- Team ID:
76cf3c46-c5d9-4df4-b457-0fc053d402f7 - Issue prefix:
VIR - Default label: Frontend
- Functions: Use function declarations, not arrow functions (
func-styleenforced). - Imports: Biome organizes imports automatically.
- Conditionals: Always use curly braces with
if/else. - Prefer
constoverlet.
Commit messages use Conventional Commits:
type(scope): description
Types: feat, fix, chore, refactor, test, docs.
- Title: lowercase, no period, under 72 characters.
- Scope is optional but preferred.
- Don't push or create PRs unless asked.
- Don't include a Test plan section in PR descriptions.
- Don't use
git -C <path>unless necessary. It triggers permission prompts that aren't worth the trouble. Run git commands from the working directory instead.
- Framework: Vitest with jsdom environment.
- Test location:
__tests__/directories alongside source files. - Test files:
ComponentName.test.tsxorfunctionName.test.ts. - Imports: Use explicit vitest imports (
import { describe, it, expect, vi } from "vitest"). - Setup:
src/tests/setup.tsxprovidesrenderWithProviders(),renderWithRouter(), andMemoryRouter. - Fixtures/fakes:
src/tests/fake/has factory functions for test data. - Assertions: Use explicit
expect()assertions, not snapshots. - User interaction: Use
@testing-library/user-eventoverfireEvent. - Queries: Prefer accessible queries (
getByRole,getByLabelText) overgetByTestId.