celeroncoder / celeroncoder/ai-shelfbook

React Review Audit

Open
#1 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.