celeroncoder / celeroncoder/ai-shelfbook
React Review Audit
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
**Score: 86/100** · 6 errors · 62 warnings
Copy as prompt
```text
Fix the following React Review diagnostics in my codebase.
## Errors (6)
1. [error] rules-of-hooks — components/upload-file.tsx:24
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
2. [error] alt-text — components/navbar.tsx:39
Missing `alt` attribute.
3. [error] rules-of-hooks — components/upload-cover.tsx:21
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
4. [error] alt-text — app/book/[id]/page.tsx:35
Missing `alt` attribute.
5. [error] jsx-key — components/books-grid.tsx:85
Missing "key" prop for element in iterator.
6. [error] alt-text — components/books-grid.tsx:94
Missing `alt` attribute.
## Warnings (62)
7. [warning] no-react19-deprecated-apis — components/ui/tooltip.tsx:14
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
8. [warning] heading-has-content — components/ui/card.tsx:36
Headings must have content and the content must be accessible by a screen reader.
9. [warning] no-react19-deprecated-apis — components/ui/card.tsx:5
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
10. [warning] no-react19-deprecated-apis — components/ui/card.tsx:20
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
11. [warning] no-react19-deprecated-apis — components/ui/card.tsx:32
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
12. [warning] no-react19-deprecated-apis — components/ui/card.tsx:44
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
13. [warning] no-react19-deprecated-apis — components/ui/card.tsx:56
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
14. [warning] no-react19-deprecated-apis — components/ui/card.tsx:64
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
15. [warning] no-react19-deprecated-apis — components/ui/label.tsx:13
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
16. [warning] no-react19-deprecated-apis — components/ui/button.tsx:43
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
17. [warning] no-react19-deprecated-apis — components/ui/input.tsx:8
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
18. [warning] server-after-nonblocking — lib/actions.ts:24
console.log() in server action — wrap in `after(() => console.log(...))` so it doesn't delay the user-visible response
19. [warning] no-react19-deprecated-apis — components/ui/form.tsx:43
useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`
20. [warning] no-react19-deprecated-apis — components/ui/form.tsx:44
useContext is superseded by `use()` on React 19+ — `use()` reads context conditionally inside hooks, branches, and loops; switch to `import { use } from 'react'`
21. [warning] no-react19-deprecated-apis — components/ui/form.tsx:73
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
22. [warning] no-react19-deprecated-apis — components/ui/form.tsx:87
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
23. [warning] no-react19-deprecated-apis — components/ui/form.tsx:104
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
24. [warning] no-react19-deprecated-apis — components/ui/form.tsx:126
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
25. [warning] no-react19-deprecated-apis — components/ui/form.tsx:143
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
26. [warning] design-no-three-period-ellipsis — components/upload-file.tsx:83
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
27. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:25
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
28. [warning] design-no-redundant-size-axes — components/ui/dropdown-menu.tsx:41
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
29. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:47
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
30. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:63
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
31. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:82
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
32. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:100
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
33. [warning] design-no-redundant-size-axes — components/ui/dropdown-menu.tsx:113
w-3.5 h-3.5 → use the shorthand size-3.5 (Tailwind v3.4+)
34. [warning] design-no-redundant-size-axes — components/ui/dropdown-menu.tsx:115
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
35. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:124
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
36. [warning] design-no-redundant-size-axes — components/ui/dropdown-menu.tsx:136
w-3.5 h-3.5 → use the shorthand size-3.5 (Tailwind v3.4+)
37. [warning] design-no-redundant-size-axes — components/ui/dropdown-menu.tsx:138
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
38. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:146
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
39. [warning] no-react19-deprecated-apis — components/ui/dropdown-menu.tsx:164
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
40. [warning] design-no-redundant-size-axes — components/navbar.tsx:28
w-6 h-6 → use the shorthand size-6 (Tailwind v3.4+)
41. [warning] design-no-bold-heading — components/navbar.tsx:29
font-bold on
crushes counter shapes at display sizes — use font-semibold (600) or font-medium (500)
42. [warning] nextjs-no-img-element — components/navbar.tsx:39
Use next/image instead of — provides automatic optimization, lazy loading, and responsive srcset
43. [warning] design-no-redundant-size-axes — components/navbar.tsx:39
w-6 h-6 → use the shorthand size-6 (Tailwind v3.4+)
44. [warning] nextjs-no-a-element — components/navbar.tsx:49
Use next/link instead of for internal links — enables client-side navigation and prefetching
45. [warning] design-no-redundant-size-axes — components/navbar.tsx:58
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
46. [warning] no-react19-deprecated-apis — components/ui/dialog.tsx:15
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
47. [warning] no-react19-deprecated-apis — components/ui/dialog.tsx:30
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
48. [warning] design-no-redundant-size-axes — components/ui/dialog.tsx:46
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
49. [warning] no-react19-deprecated-apis — components/ui/dialog.tsx:82
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
50. [warning] no-react19-deprecated-apis — components/ui/dialog.tsx:97
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
51. [warning] design-no-redundant-size-axes — components/mode-toggle.tsx:21
w-[1.2rem] h-[1.2rem] → use the shorthand size-[1.2rem] (Tailwind v3.4+)
52. [warning] design-no-redundant-size-axes — components/mode-toggle.tsx:22
w-[1.2rem] h-[1.2rem] → use the shorthand size-[1.2rem] (Tailwind v3.4+)
53. [warning] nextjs-missing-metadata — app/login/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
54. [warning] design-no-redundant-size-axes — components/downloads-left.tsx:17
w-8 h-8 → use the shorthand size-8 (Tailwind v3.4+)
55. [warning] nextjs-missing-metadata — app/create-account/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
56. [warning] nextjs-missing-metadata — app/book/[id]/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
57. [warning] nextjs-no-img-element — app/book/[id]/page.tsx:35
Use next/image instead of — provides automatic optimization, lazy loading, and responsive srcset
58. [warning] design-no-bold-heading — app/book/[id]/page.tsx:44
font-bold on
crushes counter shapes at display sizes — use font-semibold (600) or font-medium (500)
59. [warning] design-no-three-period-ellipsis — app/book/[id]/page.tsx:57
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
60. [warning] no-derived-useState — components/books-grid.tsx:29
useState initialized from prop "initialBookData" — if this value should stay in sync with the prop, derive it during render instead
61. [warning] design-no-space-on-flex-children — components/books-grid.tsx:63
space-x-2 on a flex/grid parent — use gap-x-2 instead. Per-sibling margins phantom-gap on conditional render and don't mirror in RTL
62. [warning] design-no-redundant-size-axes — components/books-grid.tsx:92
w-96 h-96 → use the shorthand size-96 (Tailwind v3.4+)
63. [warning] nextjs-no-img-element — components/books-grid.tsx:94
Use next/image instead of — provides automatic optimization, lazy loading, and responsive srcset
64. [warning] design-no-three-period-ellipsis — components/add-book.tsx:114
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
65. [warning] server-sequential-independent-await — app/api/auth/kindeSession/route.ts:10
Sequential `await` without a data dependency on the previous result — wrap the independent calls in `Promise.all([...])` so they race instead of waterfalling
66. [warning] server-sequential-independent-await — app/api/auth/kindeSession/route.ts:12
Sequential `await` without a data dependency on the previous result — wrap the independent calls in `Promise.all([...])` so they race instead of waterfalling
67. [warning] async-parallel — app/api/auth/kindeSession/route.ts:9
4 sequential await statements that appear independent — use Promise.all() for parallel execution
68. [warning] nextjs-missing-metadata — app/page.tsx:1
Page without metadata or generateMetadata export — hurts SEO
```
---
### ❌ Errors (6)
**`alt-text`**
Missing `alt` attribute.
> Must have `alt` prop, either with meaningful text, or an empty string for decorative images.
[`components/navbar.tsx:39`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L39)
[`app/book/[id]/page.tsx:35`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/book/[id]/page.tsx#L35)
[`components/books-grid.tsx:94`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L94)
**`rules-of-hooks`**
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render.
> Move the Hook call before the condition, or call it unconditionally and branch inside the Hook/effect instead.
[`components/upload-file.tsx:24`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/upload-file.tsx#L24)
[`components/upload-cover.tsx:21`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/upload-cover.tsx#L21)
**`jsx-key`**
Missing "key" prop for element in iterator.
> Add a "key" prop to the element in the iterator (https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key).
[`components/books-grid.tsx:85`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L85)
---
### ⚠️ Warnings (62)
**`no-react19-deprecated-apis`**
forwardRef is no longer needed on React 19+ — refs are regular props on function components; remove forwardRef and pass ref directly
> Pass `ref` as a regular prop on function components — `forwardRef` is no longer needed in React 19+. Replace `useContext(X)` with `use(X)` for branch-aware context reads. Only enabled on projects detected as React 19+.
[`components/ui/tooltip.tsx:14`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/tooltip.tsx#L14)
[`components/ui/card.tsx:5`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L5)
[`components/ui/card.tsx:20`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L20)
[`components/ui/card.tsx:32`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L32)
[`components/ui/card.tsx:44`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L44)
[`components/ui/card.tsx:56`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L56)
[`components/ui/card.tsx:64`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L64)
[`components/ui/label.tsx:13`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/label.tsx#L13)
[`components/ui/button.tsx:43`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/button.tsx#L43)
[`components/ui/input.tsx:8`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/input.tsx#L8)
[`components/ui/form.tsx:43`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L43)
[`components/ui/form.tsx:44`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L44)
[`components/ui/form.tsx:73`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L73)
[`components/ui/form.tsx:87`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L87)
[`components/ui/form.tsx:104`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L104)
[`components/ui/form.tsx:126`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L126)
[`components/ui/form.tsx:143`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/form.tsx#L143)
[`components/ui/dropdown-menu.tsx:25`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L25)
[`components/ui/dropdown-menu.tsx:47`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L47)
[`components/ui/dropdown-menu.tsx:63`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L63)
[`components/ui/dropdown-menu.tsx:82`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L82)
[`components/ui/dropdown-menu.tsx:100`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L100)
[`components/ui/dropdown-menu.tsx:124`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L124)
[`components/ui/dropdown-menu.tsx:146`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L146)
[`components/ui/dropdown-menu.tsx:164`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L164)
[`components/ui/dialog.tsx:15`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dialog.tsx#L15)
[`components/ui/dialog.tsx:30`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dialog.tsx#L30)
[`components/ui/dialog.tsx:82`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dialog.tsx#L82)
[`components/ui/dialog.tsx:97`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dialog.tsx#L97)
**`design-no-redundant-size-axes`**
w-4 h-4 → use the shorthand size-4 (Tailwind v3.4+)
> Collapse `w-N h-N` to `size-N` (Tailwind v3.4+) when both axes match
[`components/ui/dropdown-menu.tsx:41`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L41)
[`components/ui/dropdown-menu.tsx:113`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L113)
[`components/ui/dropdown-menu.tsx:115`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L115)
[`components/ui/dropdown-menu.tsx:136`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L136)
[`components/ui/dropdown-menu.tsx:138`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dropdown-menu.tsx#L138)
[`components/navbar.tsx:28`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L28)
[`components/navbar.tsx:39`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L39)
[`components/navbar.tsx:58`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L58)
[`components/ui/dialog.tsx:46`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/dialog.tsx#L46)
[`components/mode-toggle.tsx:21`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/mode-toggle.tsx#L21)
[`components/mode-toggle.tsx:22`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/mode-toggle.tsx#L22)
[`components/downloads-left.tsx:17`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/downloads-left.tsx#L17)
[`components/books-grid.tsx:92`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L92)
**`nextjs-missing-metadata`**
Page without metadata or generateMetadata export — hurts SEO
> Add `export const metadata = { title: '...', description: '...' }` or `export async function generateMetadata()`
[`app/login/page.tsx:1`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/login/page.tsx#L1)
[`app/create-account/page.tsx:1`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/create-account/page.tsx#L1)
[`app/book/[id]/page.tsx:1`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/book/[id]/page.tsx#L1)
[`app/page.tsx:1`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/page.tsx#L1)
**`design-no-three-period-ellipsis`**
Three-period ellipsis ("...") in JSX text — use the actual ellipsis character "…" (or `…`)
> Use the typographic ellipsis "…" (or `…`) instead of three periods — pairs with action-with-followup labels ("Rename…", "Loading…")
[`components/upload-file.tsx:83`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/upload-file.tsx#L83)
[`app/book/[id]/page.tsx:57`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/book/[id]/page.tsx#L57)
[`components/add-book.tsx:114`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/add-book.tsx#L114)
**`nextjs-no-img-element`**
Use next/image instead of <img> — provides automatic optimization, lazy loading, and responsive srcset
> `import Image from 'next/image'` — provides automatic WebP/AVIF, lazy loading, and responsive srcset
[`components/navbar.tsx:39`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L39)
[`app/book/[id]/page.tsx:35`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/book/[id]/page.tsx#L35)
[`components/books-grid.tsx:94`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L94)
**`design-no-bold-heading`**
font-bold on <h1> crushes counter shapes at display sizes — use font-semibold (600) or font-medium (500)
> Use `font-semibold` (600) or `font-medium` (500) on headings — 700+ crushes letter counter shapes at display sizes
[`components/navbar.tsx:29`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L29)
[`app/book/[id]/page.tsx:44`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/book/[id]/page.tsx#L44)
**`server-sequential-independent-await`**
Sequential `await` without a data dependency on the previous result — wrap the independent calls in `Promise.all([...])` so they race instead of waterfalling
> Wrap independent awaits in `Promise.all([...])` so they race instead of waterfalling — second call doesn't depend on the first
[`app/api/auth/kindeSession/route.ts:10`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/api/auth/kindeSession/route.ts#L10)
[`app/api/auth/kindeSession/route.ts:12`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/api/auth/kindeSession/route.ts#L12)
**`heading-has-content`**
Headings must have content and the content must be accessible by a screen reader.
> Provide screen reader accessible content when using heading elements.
[`components/ui/card.tsx:36`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/ui/card.tsx#L36)
**`server-after-nonblocking`**
console.log() in server action — wrap in `after(() => console.log(...))` so it doesn't delay the user-visible response
> `import { after } from 'next/server'` then wrap: `after(() => analytics.track(...))` — response isn't blocked
[`lib/actions.ts:24`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/lib/actions.ts#L24)
**`nextjs-no-a-element`**
Use next/link instead of <a> for internal links — enables client-side navigation and prefetching
> `import Link from 'next/link'` — enables client-side navigation, prefetching, and preserves scroll position
[`components/navbar.tsx:49`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/navbar.tsx#L49)
**`no-derived-useState`**
useState initialized from prop "initialBookData" — if this value should stay in sync with the prop, derive it during render instead
> Remove useState and compute the value inline: `const value = transform(propName)`
[`components/books-grid.tsx:29`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L29)
**`design-no-space-on-flex-children`**
space-x-2 on a flex/grid parent — use gap-x-2 instead. Per-sibling margins phantom-gap on conditional render and don't mirror in RTL
> Use `gap-*` on the flex/grid parent. `space-x-*` / `space-y-*` produce phantom gaps when a sibling is conditionally rendered, lose vertical spacing on wrapped lines, and don't mirror in RTL
[`components/books-grid.tsx:63`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/components/books-grid.tsx#L63)
**`async-parallel`**
4 sequential await statements that appear independent — use Promise.all() for parallel execution
> Use `const [a, b] = await Promise.all([fetchA(), fetchB()])` to run independent operations concurrently
[`app/api/auth/kindeSession/route.ts:9`](https://github.com/celeroncoder/ai-shelfbook/blob/5238a39233253ea7180e60223435e6f3dc9afd6a/app/api/auth/kindeSession/route.ts#L9)
---
Last scored May 14, 2026 at 9:39 AM UTC. Maintained by [React Review](https://github.com/millionco/react-review).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the six errors listed in components/upload-file.tsx, components/navbar.tsx, components/upload-cover.tsx, app/book/[id]/page.tsx, and components/books-grid.tsx, then review the warning locations across the listed components and app routes. Use the React Review diagnostics as the checklist; done means the six errors and 62 warnings are addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- nextjs, react, tailwindcss, typescript
- Domain
- accessibility, frontend, performance, web-dev
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100