feat : add front connected to backend - #5
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR introduces a comprehensive frontend redesign centered on a new Liquid Glass design system, server-based authentication with i18n support, and refactored pages using async server components. Key additions include an i18n routing layer, OAuth-like auth flows with JWT validation middleware, a reusable glass UI component library, and rebuilt home/login/course pages with role-aware navigation and localized content. ChangesFrontend Redesign & New Architecture
🎯 4 (Complex) | ⏱️ ~60 minutes
✨ Finishing Touches🧪 Generate unit tests (beta)
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 18
🧹 Nitpick comments (5)
apps/backend/src/main/java/com/codestar/backend/dto/InstanceBrandingDto.java (1)
3-3: ⚡ Quick winMake the TODO actionable and traceable.
Line 3 (
// TODO Logo) is too vague to execute reliably. Please include scope plus a ticket/reference (for example, expected logo source/validation rules), or replace it with a tracked issue link.If you want, I can draft a concrete TODO format (or an issue template) for this DTO.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/backend/src/main/java/com/codestar/backend/dto/InstanceBrandingDto.java` at line 3, Replace the vague "// TODO Logo" comment in the InstanceBrandingDto class with a concrete, actionable TODO that includes scope and traceability: specify the expected logo source (e.g., "SVG or PNG, max 2MB"), validation rules (dimensions, allowed formats, field name in DTO), and a ticket or issue reference (e.g., "ISSUE-1234" or hyperlink to tracked issue) so implementers know where to follow up; update the comment attached to InstanceBrandingDto to read like "TODO: Add logo field/validation — accept SVG/PNG up to 2MB, max 512x512px; validate MIME type; see ISSUE-XXXX for design/UX details."apps/frontend/app/actions/courses.ts (1)
10-19: ⚡ Quick winConsider logging errors before returning fallback.
The function silently swallows all errors and returns an empty array. This makes debugging API failures difficult in both development and production.
Add error logging:
} catch (error) { console.error("[getCourses] Failed to fetch courses:", error); return []; }This applies to
getCourseByIdas well (lines 21-30).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/frontend/app/actions/courses.ts` around lines 10 - 19, The catch blocks in getCourses and getCourseById silently swallow errors; update both functions to catch the error object (catch (error)) and log it before returning the fallback (e.g., console.error("[getCourses] Failed to fetch courses:", error) and console.error("[getCourseById] Failed to fetch course:", error)) so failures are visible while still returning the empty array or null fallback.apps/frontend/lib/types.ts (2)
34-48: 💤 Low valueConsider clarifying "BLOC" naming.
The
CourseBlockTypeunion includes"BLOC"among otherwise English identifiers. If this represents a specific block type concept, consider either:
- Using an English equivalent (e.g.,
"BLOCK","SECTION","PARAGRAPH")- Adding a comment explaining the French term
This improves consistency and reduces confusion for international contributors.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/frontend/lib/types.ts` around lines 34 - 48, The union type CourseBlockType contains a non-English member "BLOC"; update this for clarity by renaming "BLOC" to an English equivalent (e.g., "BLOCK" or "SECTION") and update any usages of CourseBlockType, or alternatively add a concise code comment above CourseBlockType explaining that "BLOC" is intentionally French and what it represents; ensure you change all references to the symbol CourseBlockType and the literal "BLOC" in the codebase to keep types and runtime values consistent.
73-82: ⚡ Quick winStrengthen logo type safety.
The
logofield uses{ kind: string; value: string }, which accepts any string pair. Consider defining a discriminated union to enforce valid combinations:logo: | { kind: "preset"; value: "star" | "sparkles" | "book" } | { kind: "emoji"; value: string } | { kind: "url"; value: string }This prevents invalid
kind/valuepairings and provides better autocomplete.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/frontend/lib/types.ts` around lines 73 - 82, Update the InstanceBranding interface's logo field to a discriminated union instead of the loose { kind: string; value: string } so TypeScript enforces valid kind/value pairs; replace logo on InstanceBranding with a union such as a preset variant (kind: "preset", value: one of the allowed preset names), an emoji variant (kind: "emoji", value: string) and a url variant (kind: "url", value: string) so code using InstanceBranding.logo gets proper type narrowing and autocomplete.apps/frontend/app/actions/instance.ts (1)
11-23: ⚡ Quick winConsider logging errors before returning fallback.
The function silently swallows all errors and returns
DEFAULT_INSTANCE. While the fallback ensures the app continues to function, logging the error would help identify backend issues:} catch (error) { console.error("[getInstanceBranding] Failed to fetch branding, using default:", error); return DEFAULT_INSTANCE; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/frontend/app/actions/instance.ts` around lines 11 - 23, The catch block in getInstanceBranding silently swallows errors; update the catch to accept the error (e.g., catch (error)) and log the failure before returning DEFAULT_INSTANCE so backend issues are visible. Use a clear contextual log such as console.error("[getInstanceBranding] Failed to fetch branding, using default:", error) (or your app logger) and keep the existing return DEFAULT_INSTANCE; leave apiFetch and DEFAULT_INSTANCE references unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/frontend/.gitignore`:
- Around line 33-35: The current .gitignore removed the broad env pattern
(leaving only ".env*.local" and ".env"), which fails to ignore files like
".env.production" and ".env.development"; replace those two lines with a single
broad pattern ".env*" (or add ".env*" above the existing entries) so all
environment files (including .env.production, .env.development, etc.) are
ignored and accidental secret commits are prevented.
In `@apps/frontend/app/actions/auth.ts`:
- Around line 122-126: getMe currently swallows all exceptions and returns null;
change the catch in getMe (the call to apiFetch<MeResponse>("/api/v1/auth/me"))
to only return null for expected auth failures (HTTP 401 or 403) by inspecting
the thrown error's status (or Response) and for any other errors (5xx, network
issues, timeouts) rethrow the error so they surface to the layout/error
boundary; ensure you reference the apiFetch call and MeResponse handling when
adding the conditional status check.
In `@apps/frontend/app/courses/`[id]/page.tsx:
- Around line 25-26: The current guard uses Number.isFinite which allows
decimals; change both occurrences that compute courseId (the const courseId =
Number(id) checks) to require an integer and positive value by validating with
Number.isInteger(courseId) && courseId > 0 instead of Number.isFinite(courseId)
|| courseId <= 0 so fractional IDs like 1.5 are rejected; update the
early-return logic surrounding the courseId variable in page.tsx where those two
guards appear.
In `@apps/frontend/app/login/login-shell.tsx`:
- Around line 422-430: The privacy/terms anchor tags in the login UI (the <a>
elements using className "underline hover:text-text-soft" and text from
tConsent("terms") and tConsent("privacy") in login-shell.tsx) currently use
href="#" placeholders; replace those placeholders with correct route/URL
constants (or generated routes) if the pages exist, or render them as
non-clickable elements (e.g., replace the <a> with a plain <span> or button-like
element that is not navigable) until the real pages are available, ensuring the
visible text and styling remain consistent and removing the dummy href="#"
behavior.
- Around line 240-256: The form currently only validates the invitation code
when requireCode = mode === "join", so signup submits invitationCode undefined;
update validation and rendering to accept an optional code in signup while still
requiring it for join: change the validate function so that when mode === "join"
it enforces presence (e.g., if (!s.code) e.code = tErrors("codeRequired")), but
when mode === "signup" it only validates format if s.code is provided (e.g., if
(s.code && !CODE_RE.test(s.code.toUpperCase())) e.code =
tErrors("codeInvalid")); ensure the form field that maps to FormState.code is
rendered for signup as optional so signUpAction(invitationCode) receives the
value.
In `@apps/frontend/app/page.tsx`:
- Around line 144-157: The header preview renders white text over a runtime
gradient built from branding.accent in apps/frontend/app/page.tsx (the inline
style setting background: `linear-gradient(135deg, ${branding.accent},
${branding.accent}99)`), which can yield insufficient contrast for the text
elements (the elements rendering {t("previewLabel")}, {branding.name}, and
{branding.tagline}). Update page.tsx to measure the computed contrast of
branding.accent (or its resolved gradient midpoint) at render time and, if
contrast with white is below 4.5:1, apply the stronger glass background variable
(--glass-bg-strong) or a darker overlay class instead of the default gradient;
ensure this logic targets the same container element that currently receives the
inline background and conditionally toggles the styles used by the
mono/display/text elements so the previewLabel, branding.name, and
branding.tagline meet WCAG AA contrast.
- Around line 207-210: The Link element currently removes the visible keyboard
focus indicator via the className "focus-visible:outline-none" which hides focus
for keyboard users; update the Link in page.tsx (the <Link
href={`/courses/${course.id}`} ... />) to restore an accessible focus style
instead of removing it — either remove "focus-visible:outline-none" or replace
it with a visible focus utility such as a focus-visible ring/outline (e.g.,
focus-visible:ring, focus-visible:ring-2, focus-visible:ring-offset-2,
focus-visible:ring-primary or similar) so the card link shows a clear keyboard
focus state while keeping existing aria-label and visual design.
In `@apps/frontend/app/sitemap.ts`:
- Around line 15-18: The sitemap currently includes the URL entry with url:
`${SITE_URL}/login` which conflicts with apps/frontend/app/robots.ts that
disallows /login; remove the `/login` entry from the sitemap (or make sitemap
generation conditional based on robots rules) so robots and sitemap remain
consistent—locate the object/array containing the `{ url: `${SITE_URL}/login`,
lastModified: now, changeFrequency: "monthly", priority: 0.3 }` entry in
apps/frontend/app/sitemap.ts and delete it (or wrap its creation in a check that
queries the same disallow rules used in robots.ts).
In `@apps/frontend/components/brand-mark.tsx`:
- Around line 67-75: The gradient id creation uses the raw accent string
(id={`mark-${accent.replace("#", "")}`}) which can produce invalid id/url()
tokens for non-hex or arbitrary strings; update the BrandMark component to
sanitize accent before building the id and fill (both the linearGradient id and
the path fill={`url(#...)`}) by stripping or replacing all non-alphanumeric
characters (e.g., keep [A-Za-z0-9_-]), and provide a deterministic fallback
(like "default") when the sanitized result is empty so the generated id is
always valid and the fill reference never breaks.
In `@apps/frontend/components/locale-switcher.tsx`:
- Around line 27-40: The radio group lacks keyboard arrow navigation and roving
tabindex; update the locale-switcher (LOCALES map rendering, active/current and
pending logic) to implement proper radio semantics by adding keyboard handling
and tabindex management: give each button a dynamic tabIndex (0 for the active
locale, -1 for others), add an onKeyDown on the button or the radiogroup to
handle ArrowLeft/ArrowUp and ArrowRight/ArrowDown to compute the next index from
LOCALES, move focus to that button, update the selected/current locale (invoke
the same handler used by onClick) and ensure aria-checked reflects the new
active state; alternatively, if you prefer simpler behavior, change the controls
to toggle buttons by replacing role="radio"/aria-checked with role="button" and
aria-pressed and keep click-only semantics (preserving disabled/pending).
In `@apps/frontend/components/site-footer.tsx`:
- Around line 38-46: The footer currently renders anchor tags with href="#" for
the items using t("legal"), t("privacy"), and t("contact") which are
non-functional; replace these placeholders by wiring each anchor to the correct
route or, if routes aren't available yet, render them as non-interactive text
(e.g., span) to avoid dead links. Locate the anchor elements in the
site-footer.tsx component that wrap t("legal"), t("privacy"), and t("contact")
and either change href="#" to the proper route paths (or wrap with your router
Link component if using Next/React Router) or replace the <a> elements with
non-clickable elements styled the same until real URLs are ready.
In `@apps/frontend/components/top-nav.tsx`:
- Around line 78-84: The Join CTA is hidden on mobile due to the "hidden
sm:inline-flex" utility on the GlassButton containing Link; remove or change
that class so the button is visible on small screens (e.g., make it
"inline-flex" or remove "hidden"), ensure the GlassButton/Link pair still uses
variant="ghost" size="sm" and add appropriate accessible attributes (aria-label
and visible focus styles) and sufficient contrast per WCAG AA so the join flow
is reachable on mobile and keyboard/screen-reader users.
In `@apps/frontend/components/ui/glass-button.tsx`:
- Around line 105-113: The component allows interaction when asChild is true
because non-button children (Slot/Link) ignore the disabled prop; update the
render logic in glass-button.tsx around Comp, asChild, Slot to actively disable
non-button elements when disabled || loading by adding aria-disabled={true},
tabIndex={-1} and preventing clicks: if asChild and Comp !== "button" spread
these attributes and attach an onClick wrapper (or merge with props.onClick)
that calls event.preventDefault() and event.stopPropagation() when
disabled/loading; keep aria-busy as-is and ensure className still reflects
disabled state so pointer events can also be suppressed via CSS if present.
In `@apps/frontend/components/user-menu.tsx`:
- Around line 27-30: In onDocClick, guard against non-HTMLElement event targets
before calling closest: check that e.target is an HTMLElement (e.g. using
instanceof HTMLElement) and only then call target.closest("[data-user-menu]");
if the check fails, safely return without calling closest and avoid changing
setOpen. This prevents runtime exceptions when e.target isn't an element.
In `@apps/frontend/lib/api.ts`:
- Around line 121-123: The function that currently does `if (!parsed) { return
undefined as T; }` should stop forcing `undefined` into a non-nullable generic;
change the function's return type from `T` (or `Promise<T>`) to allow
`undefined` explicitly (e.g. `T | undefined` or `Promise<T | undefined>`),
remove the `as T` assertion so it returns plain `undefined`, and update all call
sites to handle the `undefined` case (or alternatively update the function to
throw an error instead of returning `undefined` if that's preferred). Ensure you
update the function signature and any related types where the function is
declared (the function containing the `parsed` variable) and adjust callers to
handle the new `undefined` possibility.
In `@apps/frontend/lib/instance.ts`:
- Line 2: Update the inline comment "Static fallbackc for the instance
branding." to correct the typo by changing "fallbackc" to "fallback" so it reads
"Static fallback for the instance branding."; locate and edit the comment in
apps/frontend/lib/instance.ts where that exact phrase appears.
In `@apps/frontend/messages/en.json`:
- Around line 98-106: The user-facing message for the "backendStub" key inside
the "errors" object currently exposes internal hand-off/task IDs; replace that
string with neutral copy (e.g., "Service unavailable. Please try again later."
or "Unexpected server error. Please try again.") and keep any internal task/doc
references out of user strings—retain those details only in logs or developer
docs; update the "backendStub" value accordingly in the en.json errors object so
end users see a generic, non-internal message.
In `@apps/frontend/proxy.ts`:
- Around line 26-35: The code currently decodes JWTs in decodeJwtPayload and
then hasValidToken trusts the exp field without verifying the signature; update
decodeJwtPayload (and the similar logic around lines referenced) to parse the
JWT header to obtain alg, reject tokens with alg:"none", and verify the
signature cryptographically (e.g., HMAC SHA-256 verification with the server
secret for HS* or RSA/ECDSA verification with the configured public key for
RS*/ES*) before returning any payload; ensure verification fails for malformed
signatures and only then use exp in hasValidToken.
---
Nitpick comments:
In
`@apps/backend/src/main/java/com/codestar/backend/dto/InstanceBrandingDto.java`:
- Line 3: Replace the vague "// TODO Logo" comment in the InstanceBrandingDto
class with a concrete, actionable TODO that includes scope and traceability:
specify the expected logo source (e.g., "SVG or PNG, max 2MB"), validation rules
(dimensions, allowed formats, field name in DTO), and a ticket or issue
reference (e.g., "ISSUE-1234" or hyperlink to tracked issue) so implementers
know where to follow up; update the comment attached to InstanceBrandingDto to
read like "TODO: Add logo field/validation — accept SVG/PNG up to 2MB, max
512x512px; validate MIME type; see ISSUE-XXXX for design/UX details."
In `@apps/frontend/app/actions/courses.ts`:
- Around line 10-19: The catch blocks in getCourses and getCourseById silently
swallow errors; update both functions to catch the error object (catch (error))
and log it before returning the fallback (e.g., console.error("[getCourses]
Failed to fetch courses:", error) and console.error("[getCourseById] Failed to
fetch course:", error)) so failures are visible while still returning the empty
array or null fallback.
In `@apps/frontend/app/actions/instance.ts`:
- Around line 11-23: The catch block in getInstanceBranding silently swallows
errors; update the catch to accept the error (e.g., catch (error)) and log the
failure before returning DEFAULT_INSTANCE so backend issues are visible. Use a
clear contextual log such as console.error("[getInstanceBranding] Failed to
fetch branding, using default:", error) (or your app logger) and keep the
existing return DEFAULT_INSTANCE; leave apiFetch and DEFAULT_INSTANCE references
unchanged.
In `@apps/frontend/lib/types.ts`:
- Around line 34-48: The union type CourseBlockType contains a non-English
member "BLOC"; update this for clarity by renaming "BLOC" to an English
equivalent (e.g., "BLOCK" or "SECTION") and update any usages of
CourseBlockType, or alternatively add a concise code comment above
CourseBlockType explaining that "BLOC" is intentionally French and what it
represents; ensure you change all references to the symbol CourseBlockType and
the literal "BLOC" in the codebase to keep types and runtime values consistent.
- Around line 73-82: Update the InstanceBranding interface's logo field to a
discriminated union instead of the loose { kind: string; value: string } so
TypeScript enforces valid kind/value pairs; replace logo on InstanceBranding
with a union such as a preset variant (kind: "preset", value: one of the allowed
preset names), an emoji variant (kind: "emoji", value: string) and a url variant
(kind: "url", value: string) so code using InstanceBranding.logo gets proper
type narrowing and autocomplete.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e68ef429-3db9-4e4e-817d-0b43e2cf7260
⛔ Files ignored due to path filters (1)
apps/frontend/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (73)
.gitignoreapps/backend/src/main/java/com/codestar/backend/dto/InstanceBrandingDto.javaapps/backend/src/main/java/com/codestar/backend/security/GroupPermissionService.javaapps/frontend/.env.exampleapps/frontend/.gitignoreapps/frontend/CLAUDE.mdapps/frontend/app/actions/auth.tsapps/frontend/app/actions/courses.tsapps/frontend/app/actions/instance.tsapps/frontend/app/actions/locale.tsapps/frontend/app/courses/[id]/page.tsxapps/frontend/app/error.tsxapps/frontend/app/globals.cssapps/frontend/app/layout.tsxapps/frontend/app/login/login-shell.tsxapps/frontend/app/login/page.tsxapps/frontend/app/not-found.tsxapps/frontend/app/page.tsxapps/frontend/app/robots.tsapps/frontend/app/sitemap.tsapps/frontend/components/auth-provider.tsxapps/frontend/components/brand-mark.tsxapps/frontend/components/brand/section-label.tsxapps/frontend/components/brand/star-mark.tsxapps/frontend/components/brand/wordmark.tsxapps/frontend/components/branding-provider.tsxapps/frontend/components/home/deployment.tsxapps/frontend/components/home/features/block-editor-preview.tsxapps/frontend/components/home/features/index.tsxapps/frontend/components/home/features/leaderboard-preview.tsxapps/frontend/components/home/features/quiz-preview.tsxapps/frontend/components/home/features/roadmap-rail.tsxapps/frontend/components/home/hero.tsxapps/frontend/components/home/join-or-create.tsxapps/frontend/components/home/open-source.tsxapps/frontend/components/home/personas.tsxapps/frontend/components/home/site-footer.tsxapps/frontend/components/home/sovereignty.tsxapps/frontend/components/home/top-nav.tsxapps/frontend/components/locale-switcher.tsxapps/frontend/components/reveal-on-scroll.tsxapps/frontend/components/site-footer.tsxapps/frontend/components/top-nav.tsxapps/frontend/components/ui/badge.tsxapps/frontend/components/ui/button.tsxapps/frontend/components/ui/card.tsxapps/frontend/components/ui/glass-button.tsxapps/frontend/components/ui/glass-card.tsxapps/frontend/components/ui/glass-chip.tsxapps/frontend/components/ui/glass-input.tsxapps/frontend/components/ui/glass-nav.tsxapps/frontend/components/ui/glass.tsapps/frontend/components/ui/icon.tsxapps/frontend/components/ui/icons.tsxapps/frontend/components/ui/mesh-background.tsxapps/frontend/components/ui/tabs.tsxapps/frontend/components/user-menu.tsxapps/frontend/global.d.tsapps/frontend/i18n/request.tsapps/frontend/i18n/routing.tsapps/frontend/lib/api.tsapps/frontend/lib/icons.tsapps/frontend/lib/instance.tsapps/frontend/lib/reveal.tsapps/frontend/lib/roles.tsapps/frontend/lib/safe-redirect.tsapps/frontend/lib/site.tsapps/frontend/lib/types.tsapps/frontend/messages/en.jsonapps/frontend/messages/fr.jsonapps/frontend/next.config.tsapps/frontend/package.jsonapps/frontend/proxy.ts
💤 Files with no reviewable changes (25)
- apps/frontend/components/home/hero.tsx
- apps/frontend/components/home/personas.tsx
- apps/frontend/components/home/open-source.tsx
- apps/frontend/lib/reveal.ts
- apps/frontend/components/home/features/index.tsx
- apps/frontend/components/ui/button.tsx
- apps/frontend/components/home/join-or-create.tsx
- apps/frontend/components/home/features/leaderboard-preview.tsx
- apps/frontend/components/ui/card.tsx
- apps/frontend/components/ui/icon.tsx
- apps/frontend/components/home/site-footer.tsx
- apps/frontend/components/ui/badge.tsx
- apps/frontend/components/home/features/block-editor-preview.tsx
- apps/frontend/components/brand/section-label.tsx
- apps/frontend/components/ui/tabs.tsx
- apps/frontend/lib/icons.ts
- apps/frontend/components/home/top-nav.tsx
- apps/frontend/components/home/deployment.tsx
- apps/frontend/components/home/features/roadmap-rail.tsx
- apps/frontend/components/reveal-on-scroll.tsx
- apps/frontend/components/brand/wordmark.tsx
- apps/frontend/components/brand/star-mark.tsx
- apps/backend/src/main/java/com/codestar/backend/security/GroupPermissionService.java
- apps/frontend/components/home/features/quiz-preview.tsx
- apps/frontend/components/home/sovereignty.tsx
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/frontend/package.json`:
- Line 12: Update the Node engine constraint in package.json so it matches
Next.js 16.2.4's requirement: locate the "node" entry in the package.json
engines block and change its value from ">=20.3.0" to ">=20.9.0" (i.e., update
the "node" field).
In `@apps/frontend/proxy.ts`:
- Around line 25-34: In verifyToken, avoid calling jwtSecretKey() inside the try
so configuration/runtime errors aren't swallowed; instead call const key =
jwtSecretKey() before the try (letting it throw on missing/invalid config), then
run jwtVerify(token, key, ...) inside the try and in the catch only map
joseErrors.JWTExpired to "expired" and otherwise return "invalid" for
verification failures; ensure you reference verifyToken, jwtSecretKey, jwtVerify
and joseErrors.JWTExpired when making the change.
- Around line 60-93: The token check currently treats any non-"valid" status as
expired; update the verification logic in the block that calls
verifyToken(tokenValue) so it sets hasValidToken = true only when status ===
"valid", sets tokenExpired = true only when status === "expired", and leaves
both false for "invalid" (or other) statuses; adjust downstream behavior already
keyed off hasValidToken/tokenExpired (functions referenced: verifyToken,
hasValidToken, tokenExpired, isOnLogin, isPublic, clearAuthCookie) so
tampered/malformed tokens are not flagged with expired=1.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 78bd17ce-8b82-4840-b587-e2139fe31ae0
⛔ Files ignored due to path filters (1)
apps/frontend/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (14)
apps/frontend/.gitignoreapps/frontend/app/actions/auth.tsapps/frontend/app/courses/[id]/page.tsxapps/frontend/app/login/login-shell.tsxapps/frontend/app/sitemap.tsapps/frontend/components/brand-mark.tsxapps/frontend/components/user-menu.tsxapps/frontend/lib/api.tsapps/frontend/lib/instance.tsapps/frontend/messages/en.jsonapps/frontend/messages/fr.jsonapps/frontend/next.config.tsapps/frontend/package.jsonapps/frontend/proxy.ts
✅ Files skipped from review due to trivial changes (2)
- apps/frontend/messages/fr.json
- apps/frontend/.gitignore
🚧 Files skipped from review as they are similar to previous changes (9)
- apps/frontend/lib/instance.ts
- apps/frontend/app/sitemap.ts
- apps/frontend/next.config.ts
- apps/frontend/messages/en.json
- apps/frontend/components/brand-mark.tsx
- apps/frontend/lib/api.ts
- apps/frontend/app/login/login-shell.tsx
- apps/frontend/components/user-menu.tsx
- apps/frontend/app/actions/auth.ts
The follow-up PR of the #4 . It adds a frontend to test the backend. The design is in wip.
Summary by CodeRabbit
New Features
Improvements
Documentation