Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@sboh1214
Copy link
Contributor

@sboh1214 sboh1214 commented Dec 7, 2025

Summary by CodeRabbit

  • New Features

    • SMTP-based email configuration added.
    • New sitemap page and several new UI components for lists, markdown, and directors table.
  • Refactor

    • UI migrated to Chakra UI — updated navigation, layouts, menus, and page components.
    • New centered loading/screen patterns and consistent layout primitives.
  • Chores

    • Platform/tooling updates (Node.js, dependencies, scripts).
    • Environment and deployment examples cleaned (removed legacy payment keys, updated env vars).

✏️ Tip: You can customize this high-level summary in your review settings.

@sboh1214 sboh1214 requested a review from Copilot December 7, 2025 12:45
@sboh1214 sboh1214 self-assigned this Dec 7, 2025
@sboh1214 sboh1214 added the enhancement New feature or request label Dec 7, 2025
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a major UI framework migration from Tailwind CSS + HeroUI to Chakra UI v3, along with updates to Node.js, React, Next.js, and Payload CMS. The migration restructures the project by moving source files to a src/ directory and reorganizing imports accordingly.

Key Changes:

  • Complete UI framework migration from HeroUI to Chakra UI v3
  • Updated project structure with src/ directory and path alias changes (@/*./src/*)
  • Updated dependencies: React 19, Next.js 16 (flagged), Payload CMS v3.67
  • Removed Tailwind CSS, PostCSS, and related configurations
  • Added new utility modules for centralized links, menus, and datetime handling

Reviewed changes

Copilot reviewed 53 out of 92 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tsconfig.json Updated path alias to ./src/*, changed JSX to react-jsx, added dev types
tailwind.config.ts Removed - Tailwind CSS no longer used
package.json Updated dependencies to Chakra UI, Next 16 (invalid version), React 19
Dockerfile Changed Node version to 24 (invalid version)
.github/workflows/ci.yml Updated Node version to 24 (invalid version)
eslint.config.mjs Simplified config, removed FlatCompat, added generated types ignore
payload.config.ts Added TypeScript output path configuration
src/utils/* New utility files for links, menus, datetime, and database collections
src/components/* Migrated all components from HeroUI/Tailwind to Chakra UI
src/app/(stdev)/* Updated all pages to use Chakra UI components
src/generated/payload-types.ts Added new payload-kv collection type
Comments suppressed due to low confidence (3)

src/components/layout/sns-link.tsx:87

  • Link with target="_blank" is missing rel="noopener noreferrer" attribute. This poses a security risk (reverse tabnapping) where the opened page can access the window.opener object and potentially redirect the parent page.

Add the security attributes:

<Link href={props.url} target="_blank" rel="noopener noreferrer">

src/components/layout/logo.tsx:12

  • Link with target="_blank" is missing rel="noopener noreferrer" attribute. This poses a security risk (reverse tabnapping) where the opened page can access the window.opener object and potentially redirect the parent page.

Add the security attributes:

<Link href={props.url} passHref target="_blank" rel="noopener noreferrer">

src/components/layout/sns-link.tsx:2

  • Unused import Text.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 16 to 36
function HamburgerIcon() {
return (
<svg style={{ width: '20px', height: '20px' }} viewBox="0 0 20 20">
<path
fill="currentColor"
d="M1,4 H18 V6 H1 V4 M1,9 H18 V11 H1 V7 M3,14 H18 V16 H1 V14"
/>
</svg>
)
}

function CloseIcon() {
return (
<svg width="40" height="40" viewBox="0 0 40 40">
<path
d="M 10,10 L 30,30 M 30,10 L 10,30"
stroke="black"
stroke-width="4"
/>
</svg>
)
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hamburger and close icon SVGs are missing accessibility attributes. Icons used as part of interactive controls should have appropriate ARIA attributes for screen readers. While the button has an aria-label, the SVGs themselves should have proper accessibility attributes.

Add role and aria-hidden attributes:

function HamburgerIcon() {
  return (
    <svg style={{ width: '20px', height: '20px' }} viewBox="0 0 20 20" role="img" aria-hidden="true">
      <path
        fill="currentColor"
        d="M1,4 H18 V6 H1 V4 M1,9 H18 V11 H1 V7 M3,14 H18 V16 H1 V14"
      />
    </svg>
  )
}

function CloseIcon() {
  return (
    <svg width="40" height="40" viewBox="0 0 40 40" role="img" aria-hidden="true">
      <path
        d="M 10,10 L 30,30 M 30,10 L 10,30"
        stroke="black"
        strokeWidth="4"
      />
    </svg>
  )
}

Copilot uses AI. Check for mistakes.
@coderabbitai
Copy link

coderabbitai bot commented Dec 7, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Migrates UI from HeroUI/Tailwind to Chakra UI, upgrades Node to 24 and core deps (Next/React), moves app into src/, replaces many root components with Chakra-based equivalents, removes Tailwind/PostCSS, adds SMTP and Payload/S3/email config, and updates Docker/CI/envs.

Changes

Cohort / File(s) Summary
Top-level config & CI
\.dockerignore, \.env.example, \.github/workflows/ci.yml, \.npmrc, Dockerfile
Node 22→24, added SMTP env vars, removed TOSS secrets, added prettier.config.mjs to .dockerignore, removed a public-hoist-pattern in .npmrc, Docker copy no longer includes .npmrc, CI formatting tweaks.
Package & manifests
package.json, tsconfig.json
Major dependency overhaul (Next/React/Chakra/Payload), new scripts (generate:types, prettier:*), packageManager/pnpm adjustments, path alias @/*src/*, jsxreact-jsx.
Linting & CSS tooling
eslint.config.mjs, postcss.config.mjs, tailwind.config.ts
ESLint refactored to spread eslint-config-next and added ignores; PostCSS and Tailwind config removed.
Payload & infra
payload.config.ts
Added S3 storage plugin, nodemailer email adapter (SMTP env vars), set typescript output to src/generated/payload-types.ts, switched DATABASE_URI→DATABASE_URL.
Removed legacy root files
Deleted many root files under app/, components/, utils/, and middleware.ts (e.g., app/(stdev)/* old layouts/pages, root components/*, utils/links.ts)
Removed HeroUI/Tailwind-based layouts, pages, components, middleware, and legacy links util.
New src/ app & providers
src/app/(stdev)/layout.tsx, src/app/(stdev)/page.tsx, src/app/(stdev)/providers.tsx, src/app/(stdev)/loading.tsx, src/app/(stdev)/globals.css
New src/ app using ChakraProvider, new institution page, Chakra spinner, and new global CSS (non-Tailwind).
New Chakra UI layouts & navigation
src/components/layout/*.tsx, src/components/center-screen.tsx, src/components/with-line.tsx, src/components/layout/sns-link.tsx
Added Chakra-based Navigation, Footer, LeftMenu, LeftMenuLayout, Logo, SnsLink, SubMenuSelect, CenterScreen, WithLine components (new implementations).
Recreated pages & sections under src/
src/app/(stdev)/intro/**, src/app/(stdev)/business/**, src/app/(stdev)/notices/**, src/app/(stdev)/info/**
Reintroduced intro, business, notices, info layouts/pages with Chakra primitives; recreated directors table, sitemap, and other pages under src/.
New components: lists, markdown, records, webpages
src/components/markdown/markdown-view.tsx, src/components/record-list.tsx, src/components/webpage-list.tsx
New server/client components for markdown rendering and list UIs using Chakra and react-markdown.
Utils & imports update
src/utils/links.ts, src/utils/menus.ts, src/utils/payload.ts, src/utils/...
New Links/HOST utility under src/, removed OtherMenu from menus, updated payload-types import path to src/generated.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas to focus:
    • package.json dependency changes and compatibility (Next/React/Payload/Chakra).
    • payload.config.ts (S3 config, nodemailer adapter, generated types path, DATABASE_URL).
    • Large UI migration: navigation, layouts, left-menu responsive behavior in src/components/layout/*.
    • Removed root files vs new src/ imports — search for stale/orphaned imports.
    • ESLint change and newly ignored generated file (./src/generated/payload-types.ts).

Poem

🐰 I hopped through code and swapped my tailwind vest,
Poured Chakra tea and set Node 24 to rest.
Secrets moved to mail, S3 hums a tune,
Files scurried to src beneath a silver moon.
I nibble deps and dream in JSX — happy patch, hoom!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: migration from HeroUI to Chakra UI, integration of Payload CMS, and dependency updates (Node, React, Next.js).
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chakra-payload-design

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sboh1214 sboh1214 marked this pull request as ready for review December 7, 2025 15:07
@sboh1214 sboh1214 requested a review from Copilot December 7, 2025 15:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 66 out of 98 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/components/layout/sns-link.tsx:2

  • Unused import Text.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (7)
src/components/markdown/markdown-view.tsx (1)

21-21: Missing rel="noopener noreferrer" on external links.

Using target="_blank" without rel="noopener noreferrer" exposes the page to reverse tabnapping attacks.

-        a: (props) => <a target="_blank" {...props} />,
+        a: (props) => <a target="_blank" rel="noopener noreferrer" {...props} />,
src/components/record-list.tsx (1)

36-36: Add security attributes to external link.

The target="_blank" attribute without rel="noopener noreferrer" poses a security risk (reverse tabnapping) where the opened page can access the window.opener object.

Apply this diff to add the required security attributes:

-            <Link href={record.file_url} target="_blank">
+            <Link href={record.file_url} target="_blank" rel="noopener noreferrer">
src/components/webpage-list.tsx (1)

35-35: Critical: Add security attributes to external link.

The Link component with target="_blank" is missing rel="noopener noreferrer", which poses a security risk (reverse tabnapping) where the opened page can access the window.opener object and potentially redirect the parent page.

Apply this fix:

-        <Link key={webpage.id} href={webpage.url} target="_blank">
+        <Link key={webpage.id} href={webpage.url} target="_blank" rel="noopener noreferrer">
src/components/layout/navbar.tsx (2)

33-33: Fix JSX attribute syntax error.

SVG attributes in JSX must use camelCase. The stroke-width attribute should be strokeWidth.

Apply this fix:

       <path
         d="M 10,10 L 30,30 M 30,10 L 10,30"
         stroke="black"
-        stroke-width="4"
+        strokeWidth="4"
       />

16-36: Add accessibility attributes to icon SVGs.

The hamburger and close icon SVGs are missing accessibility attributes. Icons used as interactive controls should have appropriate ARIA attributes for screen readers. While the button has an aria-label, the SVGs themselves should have proper accessibility attributes.

Apply this fix:

 function HamburgerIcon() {
   return (
-    <svg style={{ width: '20px', height: '20px' }} viewBox="0 0 20 20">
+    <svg style={{ width: '20px', height: '20px' }} viewBox="0 0 20 20" role="img" aria-hidden="true">
       <path
         fill="currentColor"
         d="M1,4 H18 V6 H1 V4 M1,9 H18 V11 H1 V7 M3,14 H18 V16 H1 V14"
       />
     </svg>
   )
 }

 function CloseIcon() {
   return (
-    <svg width="40" height="40" viewBox="0 0 40 40">
+    <svg width="40" height="40" viewBox="0 0 40 40" role="img" aria-hidden="true">
       <path
         d="M 10,10 L 30,30 M 30,10 L 10,30"
         stroke="black"
         strokeWidth="4"
       />
     </svg>
   )
 }
package.json (1)

8-8: Remove unnecessary --webpack flag.

The --webpack flag is unnecessary in Next.js 16. Next.js uses webpack by default, and this flag was only temporarily needed during the Turbopack transition. Modern versions of Next.js don't require or support this flag.

Apply this fix:

-    "build": "next build --webpack",
+    "build": "next build",
src/components/center-screen.tsx (1)

5-5: Unused Text import.

The Text component is imported but not used in this file. Remove it to keep imports clean.

-import { Box, Button, Heading, Separator, Stack, Text } from '@chakra-ui/react'
+import { Box, Button, Heading, Separator, Stack } from '@chakra-ui/react'
🧹 Nitpick comments (12)
src/components/with-line.tsx (1)

1-17: LGTM! Clean Chakra UI implementation.

The component works well for its intended purpose as a decorative heading with a vertical line. The implementation is clean and follows Chakra UI patterns correctly.

For enhanced reusability, consider making the heading level configurable (currently fixed at h2). This would allow the component to adapt to different sections of the page hierarchy:

 type Props = {
   children: ReactNode
+  level?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
 }
 
 export default function WithLine(props: Props) {
+  const { children, level = 'h2' } = props
   return (
     <Stack direction="row" align="stretch" gap={2} mt={8} mb={4}>
       <Box bg="teal.600" w="4px" borderRadius="full" my={1} />
-      <Heading as="h2" size="md" m={0}>
+      <Heading as={level} size="md" m={0}>
-        {props.children}
+        {children}
       </Heading>
     </Stack>
   )
 }
src/components/markdown/markdown-view.tsx (3)

14-14: Incorrect array nesting for remarkPlugins.

The double array [[remarkGfm]] is unnecessary. Plugin arrays should be flat unless passing options.

-      remarkPlugins={[[remarkGfm]]}
+      remarkPlugins={[remarkGfm]}

16-20: Redundant heading component overrides.

These heading renderers simply pass props through without any customization. Consider removing them unless they're placeholders for future styling.

      components={{
-        h1: (props) => <h1 {...props} />,
-        h2: (props) => <h2 {...props} />,
-        h3: (props) => <h3 {...props} />,
-        h4: (props) => <h4 {...props} />,
-        h5: (props) => <h5 {...props} />,
        a: (props) => <a target="_blank" rel="noopener noreferrer" {...props} />,

10-10: Consider handling missing markdown content.

If getMarkdownByTitle returns undefined (no document found), the component renders nothing silently. Depending on use case, consider adding a fallback or throwing an error for debugging.

  const data = await getMarkdownByTitle(props.title)
+
+  if (!data) {
+    return <p>Content not found for "{props.title}"</p>
+  }

Also applies to: 54-54

src/app/(stdev)/loading.tsx (1)

1-10: Loading UI is solid; consider a small accessibility tweak

The Chakra-based loading state looks correct and idiomatic for a Next.js loading.tsx client component. To make the spinner more accessible, consider giving assistive tech an explicit loading cue, e.g.:

-import { Center, Spinner } from '@chakra-ui/react'
+import { Center, Spinner, VisuallyHidden } from '@chakra-ui/react'

 export default function Loading() {
   return (
-    <Center h="100vh">
-      <Spinner size="lg" />
-    </Center>
+    <Center h="100vh" aria-busy="true">
+      <Spinner size="lg" />
+      <VisuallyHidden>Loading content</VisuallyHidden>
+    </Center>
   )
 }

This keeps the visual design the same while improving screen-reader experience.

src/app/(stdev)/globals.css (1)

1-52: Consider using Chakra UI's theming system instead of global CSS.

Since the project is migrating to Chakra UI, it's recommended to use Chakra's built-in theme configuration rather than global CSS. This approach:

  • Avoids specificity conflicts between global styles and component props
  • Provides a centralized, type-safe theming system
  • Ensures consistency across components

Consider defining these styles in a Chakra UI theme configuration file instead.

Example Chakra theme structure:

// theme.ts
import { extendTheme } from '@chakra-ui/react'

export const theme = extendTheme({
  styles: {
    global: {
      body: {
        fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
        lineHeight: 1.6,
        color: 'gray.800',
        bg: 'white',
      },
    },
  },
  fonts: {
    body: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
    heading: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
  },
  fontSizes: {
    // Define heading sizes here
  },
})
.env.example (1)

5-7: Consider alphabetizing environment variables within groups.

The static analysis tool suggests reordering keys alphabetically for consistency (SMTP_PASS before SMTP_USER, NEXT_PUBLIC_GA_ID before NEXT_PUBLIC_GTM_ID). While purely cosmetic, alphabetical ordering can improve readability in larger environment files.

Also applies to: 11-11

src/app/(stdev)/intro/directors/table.tsx (1)

7-121: Consider using Chakra UI's Table component for better semantics and accessibility.

While using Box with as="table" works, Chakra UI v3 provides a dedicated Table component that offers better semantics, built-in accessibility features, and responsive behavior. The current implementation may not properly expose table semantics to assistive technologies.

Apply this refactor to use Chakra UI's Table component:

-import { Box } from '@chakra-ui/react'
+import { Table } from '@chakra-ui/react'

 export default function DirectorsTable() {
   return (
-    <Box overflowX="auto">
-      <Box as="table" w="full" borderCollapse="collapse">
-        <Box as="thead" bg="#e5e7eb">
-          <Box as="tr">
-            <Box as="th" border="1px solid #d1d5db" p={2} textAlign="left">
+    <Table.Root>
+      <Table.Header>
+        <Table.Row>
+          <Table.ColumnHeader>
               성명 (직위)
-            </Box>
-            <Box as="th" border="1px solid #d1d5db" p={2} textAlign="left">
+          </Table.ColumnHeader>
+          <Table.ColumnHeader>
               임기
-            </Box>
-            <Box as="th" border="1px solid #d1d5db" p={2} textAlign="left">
+          </Table.ColumnHeader>
+          <Table.ColumnHeader>
               약력
-            </Box>
-          </Box>
-        </Box>
-        <Box as="tbody">
-          <Box as="tr" bg="#f5f5f5">
-            <Box as="td" border="1px solid #d1d5db" p={2}>
+          </Table.ColumnHeader>
+        </Table.Row>
+      </Table.Header>
+      <Table.Body>
+        <Table.Row>
+          <Table.Cell>
               한우영
               <br />
               (이사장)
-            </Box>
-            <Box as="td" border="1px solid #d1d5db" p={2}>
+          </Table.Cell>
+          <Table.Cell>
               2024. 10. 1. ~ 2028. 9. 30.
-            </Box>
+          </Table.Cell>
           {/* ... continue pattern for remaining cells and rows */}
-        </Box>
-      </Box>
-    </Box>
+      </Table.Body>
+    </Table.Root>
   )
 }
src/components/layout/left-menu.tsx (1)

14-22: Unnecessary key prop on non-iterated element.

The key prop on line 15 is not needed since this Button is not rendered within a loop or array map. React's key prop is only required for elements in lists to help with reconciliation.

        <Button
-          key={props.menu.label}
          asChild
          variant="ghost"
          justifyContent="flex-start"
          fontWeight="bold"
        >
          <Link href={props.menu.href}>{props.menu.label}</Link>
        </Button>
src/components/layout/sub-menu-select.tsx (1)

17-35: Consider using Chakra UI's native Select component for consistency.

Since this PR migrates to Chakra UI, using a native <select> with inline styles is inconsistent with the framework's design system. Chakra UI's NativeSelect component would provide consistent styling and theming.

-import { Box } from '@chakra-ui/react'
+import { Box, NativeSelect } from '@chakra-ui/react'
-      <select
-        value={pathname}
-        onChange={(event: ChangeEvent<HTMLSelectElement>) =>
-          router.push(event.target.value)
-        }
-        style={{
-          width: '100%',
-          padding: '12px',
-          borderRadius: '8px',
-          border: '1px solid #e2e8f0',
-        }}
-      >
-        <option value={props.menu.href}>{props.menu.label}</option>
-        {props.menu.subMenus.map((subMenu) => (
-          <option key={subMenu.href} value={subMenu.href}>
-            {subMenu.label}
-          </option>
-        ))}
-      </select>
+      <NativeSelect.Root size="lg" width="100%">
+        <NativeSelect.Field
+          value={pathname}
+          onChange={(event: ChangeEvent<HTMLSelectElement>) =>
+            router.push(event.target.value)
+          }
+        >
+          <option value={props.menu.href}>{props.menu.label}</option>
+          {props.menu.subMenus.map((subMenu) => (
+            <option key={subMenu.href} value={subMenu.href}>
+              {subMenu.label}
+            </option>
+          ))}
+        </NativeSelect.Field>
+      </NativeSelect.Root>
payload.config.ts (2)

44-47: Empty string fallback for AWS credentials may cause confusing errors.

Falling back to empty strings for missing credentials will pass malformed credentials to AWS, resulting in cryptic authentication errors instead of a clear startup failure. Consider validating these at startup or removing the fallback.

        credentials: {
-          accessKeyId: process.env.AWS_ACCESS_KEY || '',
-          secretAccessKey: process.env.AWS_SECRET_KEY || '',
+          accessKeyId: process.env.AWS_ACCESS_KEY!,
+          secretAccessKey: process.env.AWS_SECRET_KEY!,
        },

Alternatively, add startup validation to fail fast with a clear message if these environment variables are missing.


65-76: Consider adding secure option for SMTP transport.

Port 587 typically uses STARTTLS. Explicitly setting secure: false documents the intent and ensures STARTTLS upgrade behavior.

    transportOptions: {
      host: process.env.SMTP_HOST,
      port: 587,
+      secure: false, // Use STARTTLS
      auth: {
        user: process.env.SMTP_USER,
        pass: process.env.SMTP_PASS,
      },
    },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50b9677 and 0703a97.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/generated/payload-types.ts is excluded by !**/generated/**
📒 Files selected for processing (67)
  • .dockerignore (1 hunks)
  • .env.example (1 hunks)
  • .github/workflows/ci.yml (3 hunks)
  • .npmrc (0 hunks)
  • Dockerfile (2 hunks)
  • app/(stdev)/globals.css (0 hunks)
  • app/(stdev)/home/business/layout.tsx (0 hunks)
  • app/(stdev)/home/intro/directors/table.tsx (0 hunks)
  • app/(stdev)/home/intro/layout.tsx (0 hunks)
  • app/(stdev)/home/notices/layout.tsx (0 hunks)
  • app/(stdev)/home/page.tsx (0 hunks)
  • app/(stdev)/info/layout.tsx (0 hunks)
  • app/(stdev)/info/sitemap/page.tsx (0 hunks)
  • app/(stdev)/loading.tsx (0 hunks)
  • app/(stdev)/page.tsx (0 hunks)
  • components/center-screen.tsx (0 hunks)
  • components/layout/footer.tsx (0 hunks)
  • components/layout/left-menu.tsx (0 hunks)
  • components/layout/navbar.tsx (0 hunks)
  • components/layout/sub-menu-select.tsx (0 hunks)
  • components/markdown/markdown-view.tsx (0 hunks)
  • components/record-list.tsx (0 hunks)
  • components/webpage-list.tsx (0 hunks)
  • components/with-line.tsx (0 hunks)
  • eslint.config.mjs (1 hunks)
  • middleware.ts (0 hunks)
  • package.json (1 hunks)
  • payload.config.ts (2 hunks)
  • postcss.config.mjs (0 hunks)
  • src/app/(stdev)/business/hackathon/page.tsx (3 hunks)
  • src/app/(stdev)/business/layout.tsx (1 hunks)
  • src/app/(stdev)/globals.css (1 hunks)
  • src/app/(stdev)/info/layout.tsx (1 hunks)
  • src/app/(stdev)/info/privacy/page.tsx (1 hunks)
  • src/app/(stdev)/info/sitemap/page.tsx (1 hunks)
  • src/app/(stdev)/info/terms/page.tsx (1 hunks)
  • src/app/(stdev)/intro/chart/page.tsx (1 hunks)
  • src/app/(stdev)/intro/directors/page.tsx (1 hunks)
  • src/app/(stdev)/intro/directors/table.tsx (1 hunks)
  • src/app/(stdev)/intro/history/page.tsx (1 hunks)
  • src/app/(stdev)/intro/layout.tsx (1 hunks)
  • src/app/(stdev)/intro/page.tsx (1 hunks)
  • src/app/(stdev)/layout.tsx (1 hunks)
  • src/app/(stdev)/loading.tsx (1 hunks)
  • src/app/(stdev)/notices/layout.tsx (1 hunks)
  • src/app/(stdev)/page.tsx (1 hunks)
  • src/app/(stdev)/providers.tsx (2 hunks)
  • src/app/(stdev)/sitemap.ts (0 hunks)
  • src/components/center-screen.tsx (1 hunks)
  • src/components/layout/basic-layout.tsx (2 hunks)
  • src/components/layout/footer.tsx (1 hunks)
  • src/components/layout/left-menu-layout.tsx (2 hunks)
  • src/components/layout/left-menu.tsx (1 hunks)
  • src/components/layout/logo.tsx (3 hunks)
  • src/components/layout/navbar.tsx (1 hunks)
  • src/components/layout/sns-link.tsx (3 hunks)
  • src/components/layout/sub-menu-select.tsx (1 hunks)
  • src/components/markdown/markdown-view.tsx (1 hunks)
  • src/components/record-list.tsx (1 hunks)
  • src/components/webpage-list.tsx (1 hunks)
  • src/components/with-line.tsx (1 hunks)
  • src/utils/links.ts (1 hunks)
  • src/utils/menus.ts (0 hunks)
  • src/utils/payload.ts (1 hunks)
  • tailwind.config.ts (0 hunks)
  • tsconfig.json (2 hunks)
  • utils/links.ts (0 hunks)
💤 Files with no reviewable changes (26)
  • app/(stdev)/loading.tsx
  • app/(stdev)/home/intro/directors/table.tsx
  • components/layout/sub-menu-select.tsx
  • components/layout/navbar.tsx
  • app/(stdev)/home/page.tsx
  • app/(stdev)/page.tsx
  • components/layout/left-menu.tsx
  • middleware.ts
  • app/(stdev)/home/notices/layout.tsx
  • components/center-screen.tsx
  • app/(stdev)/home/business/layout.tsx
  • app/(stdev)/globals.css
  • app/(stdev)/info/sitemap/page.tsx
  • components/record-list.tsx
  • app/(stdev)/info/layout.tsx
  • components/layout/footer.tsx
  • components/webpage-list.tsx
  • tailwind.config.ts
  • components/markdown/markdown-view.tsx
  • src/utils/menus.ts
  • components/with-line.tsx
  • postcss.config.mjs
  • .npmrc
  • app/(stdev)/home/intro/layout.tsx
  • src/app/(stdev)/sitemap.ts
  • utils/links.ts
🧰 Additional context used
🧬 Code graph analysis (15)
src/app/(stdev)/info/sitemap/page.tsx (1)
src/utils/menus.ts (5)
  • Menu (3-10)
  • IntroMenu (12-21)
  • BusinessMenu (23-32)
  • NoticesMenu (34-42)
  • InfoMenu (44-52)
src/components/layout/left-menu.tsx (1)
src/utils/menus.ts (1)
  • Menu (3-10)
src/app/(stdev)/page.tsx (1)
src/utils/payload.ts (1)
  • queryInstitutions (7-26)
src/components/layout/sub-menu-select.tsx (1)
src/utils/menus.ts (1)
  • Menu (3-10)
src/app/(stdev)/business/layout.tsx (4)
src/components/layout/navbar.tsx (1)
  • Navigation (74-154)
src/components/layout/left-menu-layout.tsx (1)
  • LeftMenuLayout (13-30)
src/utils/menus.ts (1)
  • BusinessMenu (23-32)
src/components/layout/footer.tsx (1)
  • Footer (21-110)
src/components/markdown/markdown-view.tsx (2)
src/utils/payload.ts (1)
  • getMarkdownByTitle (78-91)
src/generated/payload-types.ts (1)
  • Markdown (201-208)
src/components/webpage-list.tsx (1)
src/generated/payload-types.ts (1)
  • Webpage (226-236)
src/app/(stdev)/info/privacy/page.tsx (1)
src/components/markdown/markdown-view.tsx (1)
  • MarkdownView (9-57)
src/app/(stdev)/notices/layout.tsx (2)
src/components/layout/left-menu-layout.tsx (1)
  • LeftMenuLayout (13-30)
src/utils/menus.ts (1)
  • NoticesMenu (34-42)
src/app/(stdev)/info/layout.tsx (2)
src/components/layout/navbar.tsx (1)
  • Navigation (74-154)
src/components/layout/footer.tsx (1)
  • Footer (21-110)
src/components/layout/navbar.tsx (2)
src/utils/menus.ts (1)
  • Menu (3-10)
src/utils/links.ts (1)
  • Links (6-37)
src/components/layout/left-menu-layout.tsx (2)
src/components/layout/left-menu.tsx (1)
  • LeftMenu (10-39)
src/components/layout/sub-menu-select.tsx (1)
  • SubMenuSelect (11-38)
src/components/center-screen.tsx (1)
src/utils/links.ts (1)
  • Links (6-37)
src/app/(stdev)/intro/layout.tsx (4)
src/components/layout/navbar.tsx (1)
  • Navigation (74-154)
src/components/layout/left-menu-layout.tsx (1)
  • LeftMenuLayout (13-30)
src/utils/menus.ts (1)
  • IntroMenu (12-21)
src/components/layout/footer.tsx (1)
  • Footer (21-110)
src/components/layout/footer.tsx (3)
src/components/layout/sns-link.tsx (4)
  • SnsLink (85-99)
  • HomepageLogo (9-21)
  • InstagramLogo (23-35)
  • LinkedinLogo (37-49)
src/utils/links.ts (1)
  • Links (6-37)
src/components/layout/logo.tsx (1)
  • Logo (10-26)
🪛 dotenv-linter (4.0.0)
.env.example

[warning] 7-7: [UnorderedKey] The SMTP_PASS key should go before the SMTP_USER key

(UnorderedKey)


[warning] 11-11: [UnorderedKey] The NEXT_PUBLIC_GA_ID key should go before the NEXT_PUBLIC_GTM_ID key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Agent
  • GitHub Check: Build Docker Image
🔇 Additional comments (40)
tsconfig.json (3)

18-18: JSX runtime change aligns with React 19.x.

Updating from "preserve" to "react-jsx" is appropriate for React 19.x and modern automatic JSX transforms, eliminating the need to import React in every JSX file.


34-40: Include patterns support Next.js 16.x type generation.

The addition of .next/dev/types/**/*.ts to the include array is appropriate for Next.js 16.x development type checking.


26-31: Path aliases are correctly configured and actively used throughout the codebase.

The @/* alias has been successfully updated to "./src/*" and is actively used in 27+ import statements across components, utilities, and app routes. All imports correctly resolve to their respective modules within the src/ directory.

The @payload-config alias pointing to ./payload.config.ts is consistently used across 7 Payload-related files, including api routes, layouts, and admin pages. No resolution issues detected.

Both requirements are satisfied:

  1. All imports using the @/* pattern correctly resolve to the new ./src/* path
  2. The @payload-config alias is consistently used in Payload-related configuration files
src/app/(stdev)/info/privacy/page.tsx (1)

2-2: Clean migration to Chakra UI.

The import and Box component usage are correct. The props maxW="4xl" and mx="auto" provide the same layout behavior as the previous Tailwind implementation (max-width container, horizontally centered).

Also applies to: 6-8

src/app/(stdev)/info/terms/page.tsx (1)

2-8: Chakra Box wrapper correctly replaces Tailwind container

The new Box import and wrapper with maxW="4xl" and mx="auto" preserve the original max‑width and centering behavior while aligning with the Chakra migration; no issues from this change.

src/app/(stdev)/info/sitemap/page.tsx (3)

1-9: Clean imports aligned with Chakra UI migration.

The imports correctly bring in the necessary Chakra UI components and menu utilities. The absence of OtherMenu aligns with its removal from the codebase as mentioned in the PR summary.


15-34: Well-structured component with good accessibility practices.

The SitemapMenu component correctly uses Chakra UI components and follows accessibility best practices with semantic HTML (<ul>, <li>, proper heading hierarchy). The optional chaining on Line 24 provides good defensive coding against undefined subMenus.


36-50: LGTM! Clean implementation of the sitemap page.

The async function without await on Line 36 is standard practice in Next.js App Router server components. The responsive layout using Chakra UI's Stack component with responsive direction props is well-implemented and provides a good user experience across different screen sizes.

src/components/markdown/markdown-view.tsx (1)

34-45: Hardcoded colors may not support dark mode.

The inline background colors (#e5e7eb, #f5f5f5) are light-mode specific. Since the PR migrates to Chakra UI, consider using Chakra's color mode tokens or useColorModeValue for dark mode compatibility.

If dark mode support is required, refactor to use Chakra's semantic tokens:

import { useColorModeValue } from '@chakra-ui/react'

// Then in component:
const theadBg = useColorModeValue('gray.200', 'gray.700')
const rowBg = useColorModeValue('gray.100', 'gray.800')

Note: This would require converting the async server component to a client component, or extracting the table styling to a separate client component.

src/components/record-list.tsx (4)

1-3: LGTM!

The imports are appropriate and the 'use client' directive is correctly placed for this interactive component.


5-12: LGTM!

The Props type definition is clear and well-structured.


14-24: LGTM!

The empty state is handled gracefully with appropriate user feedback.


27-35: LGTM!

The list rendering logic is clean and makes good use of Chakra UI components for layout and styling. The use of record.id as the key is appropriate.

Also applies to: 37-45

.dockerignore (1)

5-5: LGTM!

Appropriately excludes the Prettier configuration from the Docker build context, consistent with the ESLint config exclusion.

src/app/(stdev)/intro/history/page.tsx (1)

1-1: LGTM!

Clean migration from Tailwind spacer to Chakra UI Box. The height conversion from h-8 (2rem) to h="2rem" is correct.

Also applies to: 8-8

src/components/layout/logo.tsx (1)

1-1: LGTM!

Proper migration from Tailwind to Chakra UI. All property conversions are accurate (h-12→3rem, w-56→14rem, relative→position="relative").

Also applies to: 13-23

src/components/layout/basic-layout.tsx (1)

1-1: LGTM!

Clean migration to Chakra UI Box with appropriate responsive layout props. The centered container with responsive padding is implemented correctly.

Also applies to: 10-12

src/app/(stdev)/intro/directors/page.tsx (1)

1-1: LGTM!

Proper migration to Chakra UI Heading components. The semantic HTML is preserved with the as prop, and appropriate size and spacing props are applied.

Also applies to: 7-18

.env.example (1)

5-7: LGTM!

SMTP environment variables added appropriately for email functionality. Placeholder values are correctly used in the example file.

src/app/(stdev)/business/hackathon/page.tsx (1)

3-40: LGTM! Clean migration to Chakra UI Heading components.

The migration from static h3 elements to Chakra UI Heading components is consistent and follows a clear pattern. The styling properties (size, color, spacing) are appropriate for section headings.

Dockerfile (2)

17-20: LGTM! TOSS secret mount removal aligns with PR objectives.

The removal of TOSS payment-related secret mounts is consistent with the PR's objective to remove payment integration.


1-1: Node.js 24 is fully compatible with Next.js 16.0.7 and all current dependencies.

Next.js 16.0.7 requires Node.js ≥ 20.9.0, so Node.js 24 is well-supported. All dependencies in package.json (sharp 0.34.5, @payloadcms packages 3.67.0, and others) are modern versions with Node.js 24 compatibility. This upgrade is safe to proceed with.

src/components/layout/sns-link.tsx (1)

80-80: Type restriction is appropriate for the Button-based rendering.

The change from ReactNode to ReactElement<unknown, string | JSXElementConstructor<any>> is more restrictive but aligns well with the new Button-based rendering approach, ensuring that only valid React elements (not strings or numbers) are passed as logos.

eslint.config.mjs (1)

1-13: LGTM! Modern ESLint flat config approach.

The migration from FlatCompat to directly spreading eslintConfigNext is cleaner and aligns with ESLint v9 best practices. The addition of ignores for the generated Payload types file is appropriate.

src/utils/payload.ts (1)

5-5: LGTM!

The import path update to @/generated/payload-types correctly aligns with the Payload configuration changes that generate types to the src/generated directory.

src/app/(stdev)/intro/chart/page.tsx (1)

2-2: LGTM!

The migration from Tailwind spacers to Chakra UI Box components is correctly implemented. The spacing remains equivalent (Tailwind's h-12 = 3rem).

Also applies to: 8-8, 15-15

src/app/(stdev)/layout.tsx (1)

32-32: LGTM!

The conversion from Tailwind's min-h-screen to inline minHeight: '100vh' is functionally equivalent and aligns with the PR's Tailwind removal strategy.

src/app/(stdev)/notices/layout.tsx (1)

1-22: LGTM!

The NoticesLayout follows the established pattern for section layouts, correctly composing Navigation, LeftMenuLayout with NoticesMenu, and Footer within a Chakra UI flex container.

src/app/(stdev)/info/layout.tsx (1)

4-4: LGTM!

The migration to Chakra UI Box components preserves the layout structure while adopting the new UI framework. The flex layout and spacing are correctly implemented.

Also applies to: 12-18

src/app/(stdev)/intro/page.tsx (1)

1-1: LGTM!

The migration to Chakra UI primitives (Box, Heading) is correctly implemented, preserving the content and layout structure while adopting the new UI framework.

Also applies to: 6-41

src/app/(stdev)/business/layout.tsx (1)

1-22: LGTM!

The BusinessLayout correctly follows the established pattern for section layouts, composing Navigation, LeftMenuLayout with BusinessMenu, and Footer within a Chakra UI flex container. The implementation is consistent with other layout components in the codebase.

src/app/(stdev)/intro/layout.tsx (1)

12-22: LGTM!

The layout structure is well-organized with proper flex column layout, full viewport height, and consistent use of Chakra UI components. The composition of Navigation, LeftMenuLayout with IntroMenu, and Footer follows the established pattern seen in other layout files.

src/app/(stdev)/providers.tsx (1)

21-25: Clean migration to ChakraProvider.

The replacement of HeroUIProvider with ChakraProvider using defaultSystem is correct for Chakra UI v3. The minH="100vh" on the Box preserves the full-height layout behavior from the previous implementation.

src/components/layout/left-menu-layout.tsx (1)

16-27: Proper responsive implementation with Chakra UI.

The responsive display logic correctly toggles between LeftMenu (desktop) and SubMenuSelect (mobile) using Chakra UI's responsive object syntax. The fixed positioning for the sidebar navigation is appropriate.

src/components/center-screen.tsx (1)

12-36: Well-structured centered card component.

The implementation follows Chakra UI patterns correctly. The flex-based centering, card styling, and button with asChild pattern for Next.js Link integration are all appropriate. The teal color scheme is consistent with other components like the navbar.

src/components/layout/left-menu.tsx (1)

23-37: LGTM!

The submenu rendering with mapped Button components using the asChild pattern is well-implemented. The Stack with separator provides clean visual structure.

src/components/layout/sub-menu-select.tsx (1)

11-14: LGTM!

The navigation logic using usePathname for the controlled value and router.push on change is clean and correct.

src/components/layout/footer.tsx (1)

21-109: LGTM!

The footer component is well-structured with proper Chakra UI usage, responsive design via direction={{ base: 'column', lg: 'row' }}, and clean organization of company info and links.

payload.config.ts (1)

2-4: LGTM!

The ESM-compatible __dirname derivation using fileURLToPath(import.meta.url) is the correct pattern, and the TypeScript output configuration is properly resolved.

Also applies to: 19-19, 62-64

src/utils/links.ts (1)

6-37: LGTM!

Centralized route management with the Links class provides good maintainability and type safety for navigation throughout the application.

Comment on lines 56 to 58
ssl: {
rejectUnauthorized: false, // Allow self-signed certificates
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Security concern: SSL certificate validation disabled.

Setting rejectUnauthorized: false disables certificate validation, making the connection vulnerable to man-in-the-middle attacks. If this is required for a managed database with self-signed certs, consider environment-specific configuration.

      ssl: {
-        rejectUnauthorized: false, // Allow self-signed certificates
+        rejectUnauthorized: process.env.NODE_ENV === 'production',
      },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ssl: {
rejectUnauthorized: false, // Allow self-signed certificates
},
ssl: {
rejectUnauthorized: process.env.NODE_ENV === 'production',
},
🤖 Prompt for AI Agents
In payload.config.ts around lines 56 to 58, the code disables TLS certificate
validation by setting rejectUnauthorized: false; remove this insecure default
and make certificate validation configurable: read an environment variable
(e.g., NODE_ENV or DB_ALLOW_SELF_SIGNED) to only disable validation in
non-production, or better yet accept a CA certificate path/contents from env and
configure the SSL options with that CA so validation succeeds for self-signed
certs; ensure production always enforces rejectUnauthorized: true and document
the env variables used.

Comment on lines +7 to +8
export default async function Page() {
const institutions = await queryInstitutions()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for data fetching.

The queryInstitutions() call has no error handling. If the database query fails, the entire page will crash.

Consider wrapping the fetch in a try-catch or using error boundaries:

 export default async function Page() {
-  const institutions = await queryInstitutions()
+  let institutions = []
+  try {
+    institutions = await queryInstitutions()
+  } catch (error) {
+    console.error('Failed to fetch institutions:', error)
+    // Optionally return an error UI or empty state
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default async function Page() {
const institutions = await queryInstitutions()
export default async function Page() {
let institutions = []
try {
institutions = await queryInstitutions()
} catch (error) {
console.error('Failed to fetch institutions:', error)
// Optionally return an error UI or empty state
}
🤖 Prompt for AI Agents
In src/app/(stdev)/page.tsx around lines 7-8, the call to queryInstitutions()
lacks error handling and will crash the page if the DB query fails; wrap the
await queryInstitutions() call in a try-catch, log the caught error
(console.error or your app logger) and either return a safe fallback UI (e.g., a
minimal message/component indicating data load failure) or rethrow a wrapped
Error to let the app’s error boundary handle it; ensure the catch does not
swallow useful error details and avoid exposing sensitive info to users.

Comment on lines +42 to +52
{institutions.map((institution, index) => (
<Flex key={index} align="center" justify="center">
<NextImage
src={institution.imageUrl || ''}
alt={`Logo ${index + 1}`}
width={120}
height={60}
style={{ objectFit: 'contain' }}
/>
</Flex>
))}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Handle missing or empty imageUrl to prevent runtime errors.

If institution.imageUrl is null, undefined, or empty, NextImage will receive an empty string as src, which will cause a runtime error.

Consider filtering out institutions without valid imageUrls or providing a fallback image:

-              <SimpleGrid columns={{ base: 3, md: 4, lg: 6 }} gap={6}>
-                {institutions.map((institution, index) => (
+              <SimpleGrid columns={{ base: 3, md: 4, lg: 6 }} gap={6}>
+                {institutions.filter(inst => inst.imageUrl).map((institution, index) => (
                   <Flex key={index} align="center" justify="center">
                     <NextImage
-                      src={institution.imageUrl || ''}
+                      src={institution.imageUrl}
-                      alt={`Logo ${index + 1}`}
+                      alt={institution.imageAlt || `Logo ${index + 1}`}
                       width={120}
                       height={60}
                       style={{ objectFit: 'contain' }}
                     />
                   </Flex>
                 ))}
               </SimpleGrid>

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/app/(stdev)/page.tsx around lines 42 to 52, the code passes
institution.imageUrl (which may be null/undefined/empty) directly to NextImage
causing runtime errors; update the rendering to only render institutions with a
valid non-empty imageUrl or provide a fallback image URL: filter institutions
before mapping (or add a conditional inside the map) so NextImage always gets a
non-empty string, or replace empty values with a configured fallback/src
placeholder and ensure alt text remains descriptive.

<Flex key={index} align="center" justify="center">
<NextImage
src={institution.imageUrl || ''}
alt={`Logo ${index + 1}`}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use the actual imageAlt from institution data.

The queryInstitutions() function returns imageAlt for each institution, but the code generates a generic alt text instead. Using the actual alt text would improve accessibility.

Apply this change:

-                      alt={`Logo ${index + 1}`}
+                      alt={institution.imageAlt || `Logo ${index + 1}`}
🤖 Prompt for AI Agents
In src/app/(stdev)/page.tsx around line 46, the image alt attribute currently
uses a generic string (`alt={`Logo ${index + 1}`}`) instead of the
institution-provided alt text; replace the generic alt with the
institution.imageAlt value (falling back to a sensible default like an empty
string or institution.name if imageAlt is missing) so the <img> uses the actual
imageAlt returned by queryInstitutions().

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/components/markdown/markdown-view.tsx (2)

16-20: Remove redundant heading renderers.

The h1–h5 renderers are pass-through components with no customization. They can be safely removed to reduce code clutter.

Apply this diff:

       components={{
-        h1: (props) => <h1 {...props} />,
-        h2: (props) => <h2 {...props} />,
-        h3: (props) => <h3 {...props} />,
-        h4: (props) => <h4 {...props} />,
-        h5: (props) => <h5 {...props} />,
         a: (props) => (

36-61: Consider using Chakra UI components for table styling.

Since this PR migrates the UI to Chakra UI, consider using Chakra's Table, Thead, Tbody, Tr, Th, and Td components instead of inline styles. This would:

  • Integrate with the Chakra theme system (colors, spacing)
  • Provide consistent styling across the application
  • Reduce hard-coded color values like #e5e7eb, #f5f5f5, #d1d5db

Additionally, the tr renderer on line 55 applies background color to all table rows, including those in thead, which may not be intended.

Example using Chakra components:

import { Table, Thead, Tbody, Tr, Th, Td } from '@chakra-ui/react'

// In components mapping:
table: (props) => <Table variant="simple" {...props} />,
thead: (props) => <Thead {...props} />,
tbody: (props) => <Tbody {...props} />,
tr: (props) => <Tr {...props} />,
th: (props) => <Th {...props} />,
td: (props) => <Td {...props} />,
README.md (1)

23-23: Fix capitalization of GitHub.

Per style conventions, use "GitHub" (capital 'H' and uppercase 'B').

-Github 레포지토리 설정에서
+GitHub 레포지토리 설정에서
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0703a97 and 7007b9a.

📒 Files selected for processing (10)
  • README.md (2 hunks)
  • package.json (1 hunks)
  • src/components/center-screen.tsx (1 hunks)
  • src/components/layout/logo.tsx (3 hunks)
  • src/components/layout/navbar.tsx (1 hunks)
  • src/components/layout/sns-link.tsx (3 hunks)
  • src/components/markdown/markdown-view.tsx (1 hunks)
  • src/components/record-list.tsx (1 hunks)
  • src/components/webpage-list.tsx (1 hunks)
  • src/utils/links.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/components/record-list.tsx
  • src/components/layout/logo.tsx
  • src/utils/links.ts
  • src/components/webpage-list.tsx
  • src/components/layout/navbar.tsx
  • src/components/center-screen.tsx
  • src/components/layout/sns-link.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/markdown/markdown-view.tsx (2)
src/utils/payload.ts (1)
  • getMarkdownByTitle (78-91)
src/generated/payload-types.ts (1)
  • Markdown (201-208)
🪛 LanguageTool
README.md

[uncategorized] ~23-~23: The official name of this software platform is spelled with a capital “H”.
Context: ...alhost:3000)로 이동합니다. ## How to deploy Github 레포지토리 설정에서 `Actions secrets and variabl...

(GITHUB)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build Docker Image
  • GitHub Check: Build Next.js
🔇 Additional comments (2)
src/components/markdown/markdown-view.tsx (1)

21-23: LGTM – Security attributes correctly applied.

The anchor tag now includes rel="noopener noreferrer", which addresses the security concern raised in the previous review.

package.json (1)

8-8: > Likely an incorrect or invalid review comment.

Comment on lines 16 to +36
"dependencies": {
"@channel.io/channel-web-sdk-loader": "^2.0.0",
"@heroui/react": "^2.8.2",
"@next/third-parties": "^15.5.2",
"@payloadcms/db-postgres": "^3.54.0",
"@payloadcms/next": "^3.54.0",
"@payloadcms/payload-cloud": "^3.54.0",
"@payloadcms/richtext-lexical": "^3.54.0",
"@payloadcms/storage-s3": "^3.54.0",
"@tosspayments/tosspayments-sdk": "^2.3.7",
"dayjs": "^1.11.18",
"framer-motion": "^12.23.12",
"graphql": "^16.11.0",
"next": "15.5.2",
"payload": "3.54.0",
"react": "19.1.1",
"react-dom": "19.1.1",
"@aws-sdk/client-s3": "^3.946.0",
"@chakra-ui/react": "^3.30.0",
"@channel.io/channel-web-sdk-loader": "^2.0.2",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@next/third-parties": "16.0.7",
"@payloadcms/db-postgres": "^3.67.0",
"@payloadcms/email-nodemailer": "^3.67.0",
"@payloadcms/next": "^3.67.0",
"@payloadcms/richtext-lexical": "^3.67.0",
"@payloadcms/storage-s3": "^3.67.0",
"dayjs": "^1.11.19",
"graphql": "^16.12.0",
"next": "16.0.7",
"payload": "^3.67.0",
"react": "^19.2.1",
"react-dom": "^19.2.1",
"react-markdown": "^10.1.0",
"remark-gfm": "^4.0.1",
"sharp": "0.34.3"
"sharp": "^0.34.5"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

Chakra UI 3.30.0 React 19 compatibility support

💡 Result:

Short answer: No — Chakra UI v3.30.0 does not officially advertise React 19 support. Issues reporting breakages on React 19 exist and the release notes for v3.30 do not mention React 19 compatibility. If you need stability, stick with React 18 until official support is added. [1][2][3]

Sources

  • React 19 support issue on Chakra UI repo. [1]
  • Chakra UI v3.30 release blog (v3.30.0). [2]
  • Chakra v2 upgrade notes stating Chakra targeted React 18. [3]

🌐 Web query:

Payload CMS 3.67.0 Next.js 16 compatibility requirements

💡 Result:

Short answer: Payload v3.67.0 does not officially require or declare Next.js 16 support — the release bumps its Next peer dependency to 15.4.8 (so Next 15.x is the tested target). If you need Next 16, it’s currently not officially required/supported in v3.67.0 (you can try it but expect potential breaks and follow the related GitHub discussions/PRs). [1][2]

Sources

  • Payload v3.67.0 release notes (deps: bump next to 15.4.8). [1]
  • Payload blog post noting Next.js peer-version/security guidance (recommend patched Next 15.x). [2]

References
[1] Payload CMS v3.67.0 release on GitHub — deps: bump next to 15.4.8.
[2] Payload blog post: “A quick note on the latest Next.js security patch” (Peer-dependency guidance).


🏁 Script executed:

# Check the actual package versions and their peer dependencies
cd /tmp && cat > check_deps.js << 'EOF'
// We'll check npm registry data for these packages
const packages = [
  { name: '@chakra-ui/react', version: '3.30.0' },
  { name: 'payload', version: '3.67.0' },
  { name: 'next', version: '16.0.7' },
  { name: 'react', version: '19.2.1' }
];

console.log('Checking npm registry for package compatibility...');
console.log('This would typically involve checking peerDependencies and release notes.');
EOF
node check_deps.js

Repository: stdev-corp/stdev

Length of output: 184


🏁 Script executed:

# Look for any lockfile or package-lock that might show resolved versions
find /repo -name "package-lock.json" -o -name "yarn.lock" -o -name "pnpm-lock.yaml" 2>/dev/null | head -5

Repository: stdev-corp/stdev

Length of output: 42


⚠️ CRITICAL: Unresolved dependency compatibility issues from prior review.

This PR still contains critical incompatibility issues:

  1. Chakra UI 3.30.0 does not officially support React 19.2.1 — Reported breakages exist; v3.30.0 release notes do not mention React 19 compatibility.

  2. Payload CMS 3.67.0 does not officially support Next.js 16.0.7 — Payload v3.67.0 targets Next.js 15.x; Next.js 16 compatibility is unsupported and untested.

For production stability, you must either:

  • Option A (Recommended): Downgrade to compatible versions:

    • React 18.x (latest 18 patch)
    • Next.js 15.x (latest 15 patch)
    • Chakra UI remains at 3.30.0
    • Payload remains at 3.67.0
  • Option B: Thoroughly test the React 19 + Next.js 16 + Chakra UI + Payload combination before deployment, including:

    • All Chakra UI components (especially popovers, modals, overlays)
    • Payload CMS RSC/cache behavior and database adapters
    • Turbopack integration
    • Full E2E and visual regression testing

Then monitor upstream repositories for official support announcements and be prepared to patch quickly if critical issues surface.

Please clarify your resolution: are you downgrading to compatible versions, or committing to thorough testing and accepting the production risk?

🤖 Prompt for AI Agents
In package.json around lines 16 to 36 the current dependency set (React 19.2.1
and Next.js 16.0.7) is incompatible with Chakra UI 3.30.0 and Payload 3.67.0;
either downgrade to a known-compatible set or commit to heavy testing and
monitoring. To fix: Option A (recommended) change React to the latest 18.x and
Next.js to the latest 15.x, run npm/yarn install to update lockfile and run full
app/unit/integration tests and CI; Option B (accepted risk) keep current
versions but add a documented testing plan in the PR (component-level tests for
Chakra overlays/modals/popovers, Payload CMS RSC/cache and DB adapter tests,
Turbopack compatibility checks, full E2E + visual regression), run those tests
and add an explicit risk acknowledgment and monitoring plan for upstream fixes.
Ensure package.json, lockfile and CI configs are updated accordingly and report
which option you choose in the PR description.

Comment on lines +9 to +10
export default async function MarkdownView(props: Props) {
const data = await getMarkdownByTitle(props.title)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Handle the case when markdown is not found.

If getMarkdownByTitle returns undefined (e.g., when no markdown with the given title exists), the component will render an empty Markdown element without user feedback. Consider adding explicit error handling or a fallback UI.

Apply this diff to handle missing data:

 export default async function MarkdownView(props: Props) {
   const data = await getMarkdownByTitle(props.title)
+
+  if (!data) {
+    return <div>Markdown content "{props.title}" not found.</div>
+  }

   return (
     <Markdown

Then update line 64 to remove the optional chaining:

-      {data?.content}
+      {data.content}
🤖 Prompt for AI Agents
In src/components/markdown/markdown-view.tsx around lines 9-10,
getMarkdownByTitle may return undefined so the component must handle missing
data: check the result after awaiting getMarkdownByTitle and if it's undefined
return a fallback UI (e.g., a small message or null placeholder) or
throw/redirect as appropriate for the app; ensure subsequent code assumes data
is present and update line 64 to remove the optional chaining (use data.content
or data.body depending on the field) since the guard guarantees data is defined.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
README.md (1)

43-43: ✓ Previous critical issue resolved.

The PAYLOAD_SECRET has been correctly updated from a hardcoded value to a generic example placeholder, addressing the security concern from the previous review.

🧹 Nitpick comments (1)
README.md (1)

23-23: Minor: Standardize GitHub branding.

Line 23 references "Github" but the official branding uses "GitHub" (capital H).

Apply this diff:

- Github 레포지토리 설정에서 `Actions secrets and variables` 페이지로 이동한 후 `Repository secrets`에 아래 값을 입력합니다.
+ GitHub 레포지토리 설정에서 `Actions secrets and variables` 페이지로 이동한 후 `Repository secrets`에 아래 값을 입력합니다.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7007b9a and 2c3d577.

📒 Files selected for processing (1)
  • README.md (2 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~23-~23: The official name of this software platform is spelled with a capital “H”.
Context: ...alhost:3000)로 이동합니다. ## How to deploy Github 레포지토리 설정에서 `Actions secrets and variabl...

(GITHUB)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build Docker Image
🔇 Additional comments (2)
README.md (2)

20-20: Verify the protocol change from HTTPS to HTTP.

The development URL was changed from https://localhost:3000 to http://localhost:3000. Please confirm this is intentional—local development on HTTP is typical, but if this document intends to reflect production or staging guidance, HTTPS should be used.


26-48: Approved: Updated environment and deployment documentation.

The Docker Compose section and repository secrets guidance have been correctly updated with:

  • Placeholder values for NEXT_PUBLIC_* keys
  • New SMTP configuration variables
  • PAYLOAD_SECRET with placeholder instead of hardcoded value
  • Correct DATABASE_URL format

All example values follow good documentation practices by using generic placeholders.

@sboh1214 sboh1214 merged commit c85fd57 into main Dec 7, 2025
4 checks passed
@sboh1214 sboh1214 deleted the chakra-payload-design branch December 7, 2025 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants