Adopt Biome for frontend formatting and linting (#327)#345
Merged
Conversation
The TypeScript style rules (no semicolons, double quotes) were unenforced under ESLint. Biome covers both linting and formatting in a single tool with a stricter recommended ruleset, including a11y rules that ESLint never had. - Add server/frontend/biome.json (recommended rules, double quotes, semicolons asNeeded, organize imports, tailwindDirectives CSS parser) - Replace `pnpm lint` with `biome check --write .`; add lint:check for write-free CI verification - Drop ESLint config and plugins from devDependencies - Add `git diff --exit-code` tail to scripts/lint-frontend.sh so CI fails when biome would change checked-in files Refs #327
Run `biome check --write .` and resolve the lint errors that were not auto-fixable. - Reformat 26 files (semicolons, quotes, import ordering) - Add type="button" to 17 button elements (a11y/useButtonType) - Modal backdrops: replace clickable <div> overlay with <button> (a11y/useSemanticElements + useKeyWithClickEvents + noStaticElementInteractions in FilteredListModal, KnowledgeUnitModal) - Recent Activity: replace <table> with role="button" rows by <ul> of <li><button> grid items (a11y/useSemanticElements) - API Keys filter group: <div role="group"> -> <fieldset> (a11y/useSemanticElements) - Replace 3 non-null assertions with explicit null checks (style/noNonNullAssertion) - headers["Authorization"] -> headers.Authorization (complexity/useLiteralKeys) Closes #327
Contributor
There was a problem hiding this comment.
Pull request overview
Adopts Biome as the frontend’s unified formatter + linter (replacing ESLint) and applies the resulting formatting/lint/a11y fixes across the frontend codebase.
Changes:
- Replace ESLint with Biome, add
biome.json, and updatepnpmscripts/lockfile accordingly. - Apply Biome formatting (imports/quotes/semicolons) across TS/TSX files and address newly surfaced lint rules.
- Improve accessibility semantics in several UI surfaces (button types, modal backdrops, and “Recent Activity” interactions).
Reviewed changes
Copilot reviewed 30 out of 31 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| server/frontend/vite.config.ts | Biome-driven import ordering and formatting updates. |
| server/frontend/src/utils.ts | Formatting-only changes (semicolon removal). |
| server/frontend/src/types.ts | Formatting-only changes to type declarations. |
| server/frontend/src/test-setup.ts | Formatting-only changes in test setup + localStorage mock. |
| server/frontend/src/pages/ReviewPage.tsx | Formatting + add type="button" and minor JSX restructuring. |
| server/frontend/src/pages/LoginPage.tsx | Formatting-only changes. |
| server/frontend/src/pages/DashboardPage.tsx | Formatting + a11y refactor of Recent Activity interactions and type="button" additions. |
| server/frontend/src/pages/ApiKeysPage.tsx | Formatting + semantic a11y improvements (fieldset, button types) and JSX wrapping. |
| server/frontend/src/pages/ApiKeysPage.test.tsx | Formatting + make tests more explicit/defensive around element lookups. |
| server/frontend/src/main.tsx | Replace non-null assertion with explicit root element null guard. |
| server/frontend/src/hooks/useCardDrag.ts | Formatting-only changes (plus ASI-safe leading semicolon insertion). |
| server/frontend/src/components/StatusBadge.tsx | Formatting-only changes. |
| server/frontend/src/components/ReviewCard.tsx | Import ordering + formatting and JSX wrapping. |
| server/frontend/src/components/ReviewActions.tsx | Formatting + add type="button" and expand inline control flow. |
| server/frontend/src/components/ProtectedRoute.tsx | Import ordering + formatting-only changes. |
| server/frontend/src/components/Layout.tsx | Formatting + add type="button" and minor promise formatting. |
| server/frontend/src/components/KnowledgeUnitModal.tsx | Formatting + modal backdrop refactor to semantic element/button. |
| server/frontend/src/components/FilteredListModal.tsx | Formatting + modal backdrop refactor to semantic element/button. |
| server/frontend/src/components/DragIndicators.tsx | Formatting-only changes and JSX wrapping for style objects. |
| server/frontend/src/components/DomainTags.tsx | Formatting-only changes. |
| server/frontend/src/components/ConfidenceBadge.tsx | Formatting-only changes (explicit JSX whitespace). |
| server/frontend/src/auth.tsx | Import ordering + formatting-only changes. |
| server/frontend/src/auth.test.tsx | Formatting-only changes and minor line wrapping. |
| server/frontend/src/api.ts | Formatting + minor refactor (headers.Authorization property access). |
| server/frontend/src/api.test.ts | Formatting-only changes. |
| server/frontend/src/App.tsx | Import ordering + formatting-only changes. |
| server/frontend/pnpm-lock.yaml | Add Biome packages; remove ESLint/TS-eslint related dependencies. |
| server/frontend/package.json | Replace lint script with Biome, add lint:check, drop ESLint deps, add Biome dep. |
| server/frontend/eslint.config.js | Remove ESLint configuration. |
| server/frontend/biome.json | Add Biome configuration (recommended rules + formatter preferences). |
| scripts/lint-frontend.sh | Update frontend lint script to run Biome (via pnpm lint) and fail on dirty tree. |
Files not reviewed (1)
- server/frontend/pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Modal backdrops (FilteredListModal, KnowledgeUnitModal): mark the
click-to-close <button> overlay as tabIndex={-1} and aria-hidden so
it stays out of the tab order and isn't announced as a separate
control by assistive tech, while keeping the click target.
- scripts/lint-frontend.sh: run `pnpm lint` (autofix) before
`pnpm tsc -b` so type-check sees the fixed source, and gate
`git diff --exit-code` to CI only so locally the script doesn't
fail on Biome's autofix output.
khaledosman
approved these changes
May 1, 2026
khaledosman
left a comment
There was a problem hiding this comment.
can we enable the react-compiler aswell as any related lint rules to it?
khaledosman
reviewed
May 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adopts Biome as the single linter+formatter for the frontend, replacing ESLint. The TypeScript style rules in
.claude/rules/typescript.md(no semicolons, double quotes) were aspirational under ESLint; Biome makes them enforced.Two commits:
chore(frontend): adopt Biome, replace ESLint; config-only swap.style(frontend): apply Biome formatting and fix lint violations; the autofixed reformat plus manual fixes for a11y and other lint errors that ESLint never caught.What changed
Config
server/frontend/biome.json: recommended rules, double quotes,semicolons: asNeeded, organize imports,tailwindDirectivesCSS parser.pnpm lintnow runsbiome check --write .;lint:checkadded for write-free CI verification.scripts/lint-frontend.shnow ends withgit diff --exit-codeso CI fails when Biome would change checked-in files.Source fixes
type="button"added to 17<button>elements (a11y/useButtonType).FilteredListModalandKnowledgeUnitModalrefactored from clickable<div>overlays to<button>overlays (a11y/useSemanticElements,useKeyWithClickEvents,noStaticElementInteractions).DashboardPagerefactored from a<table>withrole="button"rows to a<ul>of<li><button>grid items (a11y/useSemanticElements).<div role="group">inApiKeysPagefilter row replaced with<fieldset>.style/noNonNullAssertion).headers["Authorization"]rewritten asheaders.Authorization(complexity/useLiteralKeys).Test plan
pnpm exec biome check .clean (33 files, 0 errors)pnpm tsc -bpassespnpm testpasses (11/11)bash scripts/lint-frontend.shruns end-to-end withgit diff --exit-codecleanCloses #327