Skip to content

Conversation

@lazycoderhaha
Copy link

@lazycoderhaha lazycoderhaha commented Oct 12, 2025

Summary by CodeRabbit

  • New Features

    • New Home page replaces Welcome on the homepage.
    • My CV page with an in-browser PDF viewer.
    • Global Back to Top button.
    • Language (vi/en) and theme switchers in the navbar; localization enabled.
  • Content

    • Added several articles and a project overview.
  • UI/Style

    • Dark mode and layout tweaks across posts/feel pages; navbar labels localized; blog route updated to “Post”.
  • Refactor

    • Renamed app configuration from “welcome” to “home”.
  • Documentation

    • README updated.
  • Chores

    • Added deployment config; updated site schema contact details.

@coderabbitai
Copy link

coderabbitai bot commented Oct 12, 2025

Walkthrough

Renames “welcome” config to “home,” enables i18n with new en/vi resources, adds a new Home page and BackToTop component, introduces a PDF viewer and My CV page, updates navbar with theme/lang switchers and routes, adds multiple content posts, adjusts styles/layouts, updates schema/util/types, and adds PM2 config.

Changes

Cohort / File(s) Summary of changes
Documentation
README.md
Replaced headings/links, updated features list formatting, adjusted spacing, and changed clone URL; minor formatting tweaks.
App config schema rename
app.config.ts, nuxt.schema.ts
Renamed welcome→home and disableInfoReplaceIndexInWelcomePage→disableInfoReplaceIndexInHomePage across types and defaults.
Internationalization enablement
nuxt.config.ts, i18n.config.ts, lang/en.json, lang/vn.json
Enabled @nuxtjs/i18n, wired vueI18n to local config, switched to external JSON messages, default locale vi, added new translation keys.
Navbar i18n and controls
components/layouts/Page/Navbar.vue, components/layouts/Page/NavbarDropdownLang/ThemeSwitcher.vue, components/layouts/Page/NavbarDropdownMode/ThemeSwitcher.vue
Localized labels and routes, added My CV link, introduced language and theme switchers (Listbox/select modes), layout spacing tweaks.
Home/Welcome & navigation
components/awesome/Home.vue, components/awesome/Welcome.vue, pages/index.vue, layouts/page.vue
Added new Home component with typing animation, links, timeline, projects; minor i18n/dark-mode tweaks in Welcome; index uses AwesomeHome; layout includes AwesomeBackToTop.
Back to Top component move
components/BackToTop.vue, components/awesome/BackToTop.vue
Removed old component; added new namespaced Awesome BackToTop with scroll listener and smooth scroll.
PDF viewer and My CV page
components/layouts/Page/PdfViewer.vue, pages/mycv.vue, package.json
Added pdfjs-dist viewer component and My CV page loading it client-side; added pdfjs-dist dependency.
Content additions (posts/stories/projects)
app/content/feel/*, app/content/post/authentication-vs-authorization.md, app/content/project/my-portfolio-and-blog.md
Added multiple markdown articles with front matter and static content.
Styling and presentation
assets/scss/app.scss, components/awesome/Content/Doc.vue, components/layouts/Page/Content.vue, pages/feel/index.vue, pages/post/index.vue
New CSS var and .hide-scrollbar; commented imports; min-height calc change; dark-mode class updates and minor style tweaks; removed paragraph color in blog content.
Routing/query tweak
pages/project/index.vue
Un-commented QueryBuilderParams path usage.
SEO/Schema updates
util/schema.json
Added alternate name and updated email in Organization schema.
Ecosystem/Deployment
ecosystem.config.cjs
Added PM2 ecosystem config (cluster mode, script path, PORT=4301; “einstances” field present).
Types loosening
utils/types.ts
Broadened AwesomeLayoutPageNavbarMenu.type to include any.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant U as User
  participant W as Window
  participant B as AwesomeBackToTop

  Note over B: On mount
  B->>W: addEventListener('scroll', handler)
  U->>W: Scroll
  W-->>B: pageYOffset
  alt pageYOffset > 10
    B->>B: Show button (block)
  else
    B->>B: Hide button (hidden)
  end
  U->>B: Click button
  B->>W: window.scrollTo({ top: 0, behavior: 'smooth' })
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant N as Navbar Lang ThemeSwitcher
  participant I as i18n (locale)

  U->>N: Open language dropdown
  N->>I: v-model locale (get current)
  U->>N: Select vi/en
  N->>I: Update locale
  I-->>N: Rerender with new labels
  I-->>UI: UI texts update via $t(...)
Loading
sequenceDiagram
  autonumber
  participant U as User
  participant P as /mycv Page
  participant V as PdfViewer
  participant PJ as pdfjs-dist

  U->>P: Navigate to /mycv
  P->>V: Async import (client-only)
  V->>PJ: Set workerSrc
  V->>PJ: getDocument(mycv.pdf)
  PJ-->>V: PDFDocumentProxy
  V->>V: viewer.setDocument(...)
  V-->>U: Render PDF pages
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

In twilight code I thump and type,
A bun of bytes with ears upright—
Home hops in, Welcome takes flight,
Words learn tongues by lunar light.
I scroll to stars, then leap to top,
My CV flips—page by page—nonstop.
Deploy, enjoy—hippity hop! 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title “Just the beginning” is vague and does not convey any information about the substantive changes in the pull request, such as configuration renaming, content additions, internationalization features, or UI component updates. Please update the title to a concise summary of the main changes, for example “Rename welcome to home config and add i18n support with new content pages and UI enhancements.”
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

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: 25

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/layouts/Page/Navbar.vue (1)

147-147: Configure /blog/post redirect
No /blog references detected; add a redirect in your router config so existing bookmarks and external links to /blog continue to work.

🧹 Nitpick comments (15)
components/layouts/Page/Content.vue (1)

4-4: Consider retaining the CSS variable for maintainability.

Replacing var(--layout-page-content-min-height) with a hardcoded calc(100vh - 120px) reduces flexibility and maintainability. If layout heights change, this value must be manually updated across the codebase.

If the CSS variable is no longer needed elsewhere, at minimum document the magic number 120px:

<!-- 120px = header height (e.g., 64px) + footer height (e.g., 56px) -->
<div
  class="max-w-6xl m-auto pt-[24px] lg:pt-[64px]"
  :style="{ 'min-height': 'calc(100vh - 120px)' }"
>

Alternatively, restore the CSS variable approach for better maintainability:

-    :style="{ 'min-height': 'calc(100vh - 120px)' }"
+    :style="{ 'min-height': 'var(--layout-page-content-min-height)' }"
components/awesome/BackToTop.vue (1)

15-15: Remove unused variable.

The nuxtApp variable is declared but never used in this component.

Apply this diff to remove it:

-const nuxtApp = useNuxtApp()
 const scrolltoTop = () => {
app/content/feel/3-cach-tro-nen-phien-ban-tot-nhat-cua-chinh-minh.md (1)

9-23: Use proper heading syntax for better document structure.

The section titles are currently styled with bold text (**text**) instead of using proper Markdown heading syntax. This affects document accessibility and semantic structure.

Apply this diff to use proper headings:

-**Sống đơn giản và thanh tao**
+## Sống đơn giản và thanh tao

 Ngày nay ít có ai thích thưởng trà và bàn thơ ca...

-**Hãy nói lời yêu thương**
+## Hãy nói lời yêu thương

 Bạn biết không cuộc đời này là vô thường...

-**Suy nghĩ tích cực**
+## Suy nghĩ tích cực

 Bạn đã bao giờ nghe câu nói...
components/layouts/Page/PdfViewer.vue (2)

20-20: Consider making PDF path configurable.

The PDF path is hardcoded to './mycv.pdf'. Making this a prop would improve component reusability.

Consider adding a prop:

+const props = defineProps({
+  pdfUrl: {
+    type: String,
+    default: './mycv.pdf'
+  }
+})
+
 const getPdf = async () => {
   const container = document.getElementById('pageContainer') as any
   const pdfViewer = new PDFViewer({
     container,
   })
-  const loadingTask = pdfjsLib.getDocument('./mycv.pdf')
+  const loadingTask = pdfjsLib.getDocument(props.pdfUrl)
   const pdf = await loadingTask.promise

36-37: Fix formatting issue.

Extra blank line detected by prettier.

Apply this diff:

   .canvasWrapper {
     width: 100%;
-
   }
 }
README.md (1)

34-34: Fix heading level progression.

The heading jumps from h2 (##) to h4 (####), skipping h3. This breaks proper document hierarchy.

Apply this diff:

-#### Using with Direct Clone
+### Using with Direct Clone
components/awesome/SVGComponent.vue (1)

1-32: Props size and color are defined but not used.

The component defines size and color props with defaults, but these props are never applied to the SVG element. Only className and label are actually used.

Either remove the unused props or apply them to the SVG:

Option 1: Remove unused props

 interface IconProps {
-  // Icon size in pixels
-  size?: number | string
-  // Tailwind color class (e.g. 'blue-500')
-  color?: string
   // Additional classes
   className?: string
   // Accessibility label
   label?: string
 }

 const props = withDefaults(defineProps<IconProps>(), {
-  size: 24,
-  color: '',
   className: '',
   label: '',
 })

Option 2: Apply props to the SVG

-<svg viewBox="0 0 24 24" :aria-label="props.label" :class="props.className">
+<svg 
+  viewBox="0 0 24 24" 
+  :aria-label="props.label" 
+  :class="[props.className, props.color]"
+  :width="props.size"
+  :height="props.size"
+>
app/content/project/my-portfolio-and-blog.md (2)

47-53: Fix markdownlint MD034: wrap bare URLs with links.

Convert bare URLs to proper Markdown links.


4-5: Prefer ISO date; verify hero image extension.

  • Use ISO-8601 for Content sorting/consistency.
  • Image path likely should be .webp (site uses webp elsewhere).

Please confirm /public/images/project-1.webp exists; otherwise keep .png.

components/awesome/Home.vue (3)

2-2: Avoid timer leaks; clear timeouts on unmount.

Store timeout IDs and clear them in onBeforeUnmount.

- import { ref } from 'vue'
+ import { ref, onBeforeUnmount } from 'vue'
-  setTimeout(loop, time)
+  timer = window.setTimeout(loop, time)
-setTimeout(() => {
-  currentPhrase.value = ''
-  loop()
-}, 3000)
+startTimer = window.setTimeout(() => {
+  currentPhrase.value = ''
+  loop()
+}, 3000)

Add near the bottom of the script:

let timer: number | undefined
let startTimer: number | undefined

onBeforeUnmount(() => {
  if (timer) clearTimeout(timer)
  if (startTimer) clearTimeout(startTimer)
})

Also applies to: 42-47


11-11: Make phrases reactive to locale changes.

Use a computed array so text updates after switching languages. Based on learnings.

- import { ref } from 'vue'
+ import { ref, computed } from 'vue'
-const phrases = [t('im') + ` Lê Vĩnh Tuyến`, t('iLearnIdeveloper')]
+const phrases = computed(() => [t('im') + ` Lê Vĩnh Tuyến`, t('iLearnIdeveloper')])
-  const currentPhraseText = phrases[currentPhraseIndex.value]
+  const currentPhraseText = phrases.value[currentPhraseIndex.value]

Also applies to: 16-16, 2-2


126-167: Anchor/rel hygiene for external links.

  • <NuxtLink> renders <a> by default; drop tag="a".
  • For target="_blank", ensure rel="noopener noreferrer" everywhere.

Example change:

-<NuxtLink tag="a" target="_blank" to="https://github.com/..." >
+<NuxtLink target="_blank" rel="noopener noreferrer" to="https://github.com/...">

Apply similarly across external links in this component.

Also applies to: 168-205, 714-756, 1245-1276, 1284-1317

app.config.ts (1)

2-2: Type-only import for NuxtApp.

Avoid emitting a runtime import.

-import { NuxtApp } from '#app'
+import type { NuxtApp } from '#app'
nuxt.config.ts (1)

82-84: Consider adding more i18n configuration options.

The current i18n configuration is functional, but you may want to consider adding additional options for better control:

  • defaultLocale: to explicitly set the fallback locale
  • locales: array defining available locales with their codes and ISO values
  • detectBrowserLanguage: for automatic locale detection
  • strategy: to control URL structure for different locales

Based on learnings, these options are commonly used in @nuxtjs/i18n v8 setups.

Example:

i18n: {
  vueI18n: './i18n.config.ts',
  defaultLocale: 'vi',
  locales: [
    { code: 'en', iso: 'en-US', name: 'English' },
    { code: 'vi', iso: 'vi-VN', name: 'Tiếng Việt' }
  ],
  detectBrowserLanguage: {
    useCookie: true,
    fallbackLocale: 'vi',
  }
},
components/layouts/Page/NavbarDropdownLang/ThemeSwitcher.vue (1)

10-19: Consider renaming availableThemes to reflect language options.

The variable name availableThemes is misleading since it contains language options (vi, en), not visual themes.

-const availableThemes = reactive([
+const availableLanguages = reactive([
   {
     key: 'vi',
     text: 'VN',
   },
   {
     key: 'en',
     text: 'EN',
   },
 ])

And update all references throughout the template accordingly.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 684ac2a and aceace6.

⛔ Files ignored due to path filters (12)
  • public/images/feel-10.png is excluded by !**/*.png
  • public/images/feel-11.png is excluded by !**/*.png
  • public/images/feel-8.png is excluded by !**/*.png
  • public/images/feel-9.png is excluded by !**/*.png
  • public/images/post-6.png is excluded by !**/*.png
  • public/images/toTop.png is excluded by !**/*.png
  • public/lang/fr.png is excluded by !**/*.png
  • public/lang/indo.png is excluded by !**/*.png
  • public/lang/us.png is excluded by !**/*.png
  • public/lang/vn.png is excluded by !**/*.png
  • public/mycv.pdf is excluded by !**/*.pdf
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (35)
  • README.md (1 hunks)
  • app.config.ts (4 hunks)
  • app/content/feel/3-cach-tro-nen-phien-ban-tot-nhat-cua-chinh-minh.md (1 hunks)
  • app/content/feel/me-oi-con-chenh-venh-mot-ti-thoi.md (1 hunks)
  • app/content/feel/nam-lay-giac-mo-cua-chinh-ban-than-minh.md (1 hunks)
  • app/content/feel/o-pho-thi-hay-ve-voi-que.md (1 hunks)
  • app/content/post/authentication-vs-authorization.md (1 hunks)
  • app/content/project/my-portfolio-and-blog.md (1 hunks)
  • assets/scss/app.scss (4 hunks)
  • components/BackToTop.vue (0 hunks)
  • components/awesome/BackToTop.vue (1 hunks)
  • components/awesome/Content/Doc.vue (1 hunks)
  • components/awesome/Home.vue (1 hunks)
  • components/awesome/SVGComponent.vue (1 hunks)
  • components/awesome/Welcome.vue (4 hunks)
  • components/layouts/Page/Content.vue (1 hunks)
  • components/layouts/Page/Navbar.vue (6 hunks)
  • components/layouts/Page/NavbarDropdownLang/ThemeSwitcher.vue (1 hunks)
  • components/layouts/Page/NavbarDropdownMode/ThemeSwitcher.vue (1 hunks)
  • components/layouts/Page/PdfViewer.vue (1 hunks)
  • ecosystem.config.cjs (1 hunks)
  • i18n.config.ts (1 hunks)
  • lang/en.json (1 hunks)
  • lang/vn.json (1 hunks)
  • layouts/page.vue (1 hunks)
  • nuxt.config.ts (3 hunks)
  • nuxt.schema.ts (1 hunks)
  • package.json (2 hunks)
  • pages/feel/index.vue (2 hunks)
  • pages/index.vue (1 hunks)
  • pages/mycv.vue (1 hunks)
  • pages/post/index.vue (2 hunks)
  • pages/project/index.vue (1 hunks)
  • util/schema.json (2 hunks)
  • utils/types.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • components/BackToTop.vue
🧰 Additional context used
🪛 Biome (2.1.2)
ecosystem.config.cjs

[error] 1-2: A global variable should not be reassigned.

Assigning to a global variable can override essential functionality.

(lint/suspicious/noGlobalAssign)

🪛 ESLint
pages/mycv.vue

[error] 2-2: Replace ()·=>·import('@/components/layouts/page/PdfViewer.vue') with ⏎··()·=>·import('@/components/layouts/page/PdfViewer.vue'),⏎

(prettier/prettier)


[error] 10-10: Delete ····

(prettier/prettier)


[error] 11-11: Delete ··

(prettier/prettier)

components/layouts/Page/PdfViewer.vue

[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/namespace)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/order)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/default)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/named)


[error] 36-37: Delete

(prettier/prettier)

components/awesome/Home.vue

[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/namespace)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/order)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/named)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/default)

pages/post/index.vue

[error] 72-72: Delete ·

(prettier/prettier)


[error] 81-81: Delete ·

(prettier/prettier)

components/awesome/Welcome.vue

[error] 98-100: Replace ⏎················class="grid-cols-1·md:grid-cols-2·grid·md:flex"⏎·············· with ·class="grid-cols-1·md:grid-cols-2·grid·md:flex"

(prettier/prettier)

i18n.config.ts

[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/namespace)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/order)


[error] 1-1: Resolve error: File './app/.nuxt/tsconfig.json' not found.
at resolveExtends (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:6816)
at _parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:7781)
at parseTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:8798)
at Object.getTsconfig (/home/jailuser/git/node_modules/get-tsconfig/dist/index.cjs:7:9346)
at /home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:258:36
at Array.map ()
at initMappers (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:252:26)
at Object.resolve (/home/jailuser/git/node_modules/eslint-import-resolver-typescript/lib/index.cjs:124:3)
at withResolver (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:180:23)
at fullResolve (/home/jailuser/git/node_modules/eslint-module-utils/resolve.js:201:22)

(import/default)

🪛 markdownlint-cli2 (0.18.1)
app/content/project/my-portfolio-and-blog.md

47-47: Bare URL used

(MD034, no-bare-urls)


49-49: Bare URL used

(MD034, no-bare-urls)


51-51: Bare URL used

(MD034, no-bare-urls)


53-53: Bare URL used

(MD034, no-bare-urls)

README.md

34-34: Heading levels should only increment by one level at a time
Expected: h3; Actual: h4

(MD001, heading-increment)

app/content/feel/3-cach-tro-nen-phien-ban-tot-nhat-cua-chinh-minh.md

9-9: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


15-15: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


21-21: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

app/content/post/authentication-vs-authorization.md

37-37: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)


62-62: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🔇 Additional comments (20)
package.json (1)

77-77: Consider the trade-offs of pinning the exact Nuxt version.

Changing from ^3.8.0 to 3.8.0 removes the ability to receive patch updates automatically. While this provides build stability, it means security patches and bug fixes in 3.8.x releases won't be automatically adopted.

If strict version control is required, consider documenting this decision. Otherwise, restore the caret to allow patch updates:

-    "nuxt": "3.8.0",
+    "nuxt": "^3.8.0",
components/awesome/Content/Doc.vue (1)

15-18: LGTM!

The dark mode styling addition properly handles text contrast in both light and dark themes.

app/content/feel/nam-lay-giac-mo-cua-chinh-ban-than-minh.md (1)

1-23: LGTM!

New content file added with proper front matter structure.

util/schema.json (1)

27-27: LGTM!

Schema updates align with portfolio content additions and reflect updated contact information.

Also applies to: 54-54

components/awesome/Welcome.vue (2)

657-657: LGTM!

Dark mode styling enhancements properly handle theme switching.

Also applies to: 1203-1203


691-691: Verify i18n keys exist in translation files
Ensure 'journey' and 'projects' keys are defined in all JSON files under lang/ and public/lang/.

pages/feel/index.vue (1)

71-116: LGTM! Dark mode styling enhancements.

The dark mode classes are consistently applied across the article container, links, and text elements, improving the UI experience in dark mode.

app/content/feel/me-oi-con-chenh-venh-mot-ti-thoi.md (1)

1-39: LGTM! Well-structured narrative content.

The content file is properly formatted with appropriate front matter and engaging narrative text.

app.config.ts (1)

96-107: Config rename looks consistent.

home block and disableInfoReplaceIndexInHomePage align across interface and defaults. LGTM.

Also applies to: 116-117

pages/index.vue (1)

10-10: Swap to AwesomeHome is correct.

Component auto-import should resolve from components/awesome/Home.vue. LGTM.

layouts/page.vue (1)

8-8: LGTM!

The addition of the <AwesomeBackToTop /> component is well-placed after the footer, providing a consistent navigation enhancement across pages.

nuxt.schema.ts (1)

23-25: LGTM!

The rename from welcome to home is consistent and the corresponding flag name has been updated appropriately.

lang/vn.json (1)

1-13: LGTM!

The Vietnamese translation file is well-structured with all necessary keys defined. The translations appear appropriate for the Vietnamese locale.

app/content/feel/o-pho-thi-hay-ve-voi-que.md (1)

1-15: LGTM!

The markdown file is properly structured with valid front matter and appropriate Vietnamese content.

i18n.config.ts (2)

1-2: LGTM!

The import statements correctly reference the newly added English and Vietnamese translation files.


5-5: LGTM!

The default locale change to Vietnamese ('vi') aligns with the PR's focus on Vietnamese content and translations.

pages/post/index.vue (1)

77-77: LGTM!

The dark mode styling additions provide consistent theming across the post index page with appropriate color choices for text and backgrounds.

Also applies to: 96-98, 101-101, 106-106

nuxt.config.ts (1)

67-67: LGTM!

The @nuxtjs/i18n module is correctly added to enable internationalization support. Based on learnings, this is the appropriate v8.x module for Nuxt 3 integration.

components/layouts/Page/Navbar.vue (2)

2-16: LGTM: i18n integration implemented correctly.

The i18n integration follows best practices:

  • Proper use of useI18n() composable from @nuxtjs/i18n
  • Consistent use of $t() for translations in the template
  • Locale-aware menu labels for "My CV" and "My Story"

This aligns well with the i18n configuration and language resources added in this PR.

Based on learnings.

Also applies to: 123-123, 139-139, 227-227, 241-241


114-125: LGTM: New CV menu item with proper i18n and routing.

The new "My CV" menu item is well-implemented with:

  • Proper i18n binding using $t('myCV')
  • Active state styling based on route name
  • Consistent structure with other menu items


# AuthN vs AuthZ: Key Differences and How They Work Together

### Verification vs. Permission
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

Fix heading hierarchy violations.

The document jumps from h1 (#) directly to h3 (###) at lines 37 and 62, which violates proper heading structure. Headings should increment by one level at a time for accessibility and document structure.

Apply this diff to fix the heading levels:

-### Verification vs. Permission
+## Verification vs. Permission
 Authentication confirms a user's identity ("Who are you?") while authorization focuses on their permissions ("What are you allowed to do?").
 
-### Sequential Process
+## Sequential Process
 Authentication always precedes authorization, as the system must verify a user's identity before determining their permissions.
 
-### Integrated Security Approach
+## Integrated Security Approach

and

-### Scalability and Flexibility
+## Scalability and Flexibility
 An authorization system should scale with your application, handling increased traffic and growing permissions without performance loss. Flexibility is equally important, allowing easy permission adjustments as application requirements evolve.
 
-### Security Best Practices
+## Security Best Practices

Based on static analysis.

Also applies to: 62-62

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

37-37: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🤖 Prompt for AI Agents
In app/content/post/authentication-vs-authorization.md around lines 37 and 62
the document jumps from an h1 (#) directly to h3 (###); change those h3 headings
to h2 (##) so headings increment by one level at a time and the document
hierarchy is preserved.

Comment on lines +55 to +58
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
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

Hide scrollbar for WebKit browsers too.

.hide-scrollbar only disables scrollbars in Firefox/Edge; Chrome/Safari still show them because there is no ::-webkit-scrollbar override. Add the WebKit pseudo-element to finish the utility.

 .hide-scrollbar {
   -ms-overflow-style: none; /* IE and Edge */
   scrollbar-width: none; /* Firefox */
 }
+.hide-scrollbar::-webkit-scrollbar {
+  display: none; /* Chrome, Safari */
+}
📝 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
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.hide-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
.hide-scrollbar::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
🤖 Prompt for AI Agents
In assets/scss/app.scss around lines 55 to 58, the .hide-scrollbar utility
disables scrollbars for IE/Edge and Firefox but not for WebKit browsers; add a
WebKit pseudo-element rule to hide scrollbars in Chrome/Safari by adding a
.hide-scrollbar::-webkit-scrollbar selector that hides the scrollbar (e.g., set
display: none or width/height: 0) so the utility covers WebKit as well.

Comment on lines +23 to +36
onMounted(() => {
const topBtn = document.querySelector('#topButton') as any
window.onscroll = () => {
if (window.pageYOffset > 10) {
// unhide
topBtn.classList.add('block')
topBtn.classList.remove('hidden')
} else {
// hide
topBtn.classList.remove('block')
topBtn.classList.add('hidden')
}
}
})
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

Memory leak: scroll listener not cleaned up.

The scroll listener (window.onscroll) is attached in onMounted but never removed when the component unmounts, causing a memory leak. Additionally, directly assigning to window.onscroll overwrites any existing listener.

Apply this diff to properly clean up the listener:

 onMounted(() => {
   const topBtn = document.querySelector('#topButton') as any
-  window.onscroll = () => {
+  const handleScroll = () => {
     if (window.pageYOffset > 10) {
       // unhide
       topBtn.classList.add('block')
       topBtn.classList.remove('hidden')
     } else {
       // hide
       topBtn.classList.remove('block')
       topBtn.classList.add('hidden')
     }
   }
+  window.addEventListener('scroll', handleScroll)
+  
+  // Cleanup
+  onBeforeUnmount(() => {
+    window.removeEventListener('scroll', handleScroll)
+  })
 })
📝 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
onMounted(() => {
const topBtn = document.querySelector('#topButton') as any
window.onscroll = () => {
if (window.pageYOffset > 10) {
// unhide
topBtn.classList.add('block')
topBtn.classList.remove('hidden')
} else {
// hide
topBtn.classList.remove('block')
topBtn.classList.add('hidden')
}
}
})
onMounted(() => {
const topBtn = document.querySelector('#topButton') as any
const handleScroll = () => {
if (window.pageYOffset > 10) {
// unhide
topBtn.classList.add('block')
topBtn.classList.remove('hidden')
} else {
// hide
topBtn.classList.remove('block')
topBtn.classList.add('hidden')
}
}
window.addEventListener('scroll', handleScroll)
// Cleanup
onBeforeUnmount(() => {
window.removeEventListener('scroll', handleScroll)
})
})
🤖 Prompt for AI Agents
In components/awesome/BackToTop.vue around lines 23 to 36, the component assigns
window.onscroll in onMounted which overwrites other handlers and is never
removed—causing a memory leak; change this to register a named scroll handler
with window.addEventListener('scroll', onScroll) where onScroll is a const that
queries the #topButton (guarding for null) and toggles 'block'/'hidden' classes,
then remove the listener in onUnmounted using
window.removeEventListener('scroll', onScroll); this preserves other scroll
listeners and ensures proper cleanup on unmount.

Comment on lines +39 to +45
#pagetop {
z-index: 1000000;
img {
border-radius: 50%;
background-color: #ffffff;
}
}
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

CSS selector mismatch.

The CSS targets #pagetop but the button's id is #topButton. The styles won't apply to the intended element.

Apply this diff to fix the selector:

-#pagetop {
+#topButton {
   z-index: 1000000;
   img {
🤖 Prompt for AI Agents
In components/awesome/BackToTop.vue around lines 39 to 45, the CSS targets
#pagetop but the button uses id #topButton, so the styles are not applied;
update the selector to #topButton (preserving the nested img rules: z-index, img
border-radius and background-color) so the styling applies to the actual
element.

Comment on lines +39 to +41
const spedUp = Math.random() * (80 - 50) + 150
const normalSpeed = Math.random() * (300 - 250) + 50
const time = isDeleting.value ? spedUp : normalSpeed
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

Typing speed math reversed (deleting slower than typing).

Fix ranges so deleting is faster and naming matches behavior.

-  const spedUp = Math.random() * (80 - 50) + 150
-  const normalSpeed = Math.random() * (300 - 250) + 50
+  const spedUp = Math.random() * (80 - 50) + 50        // ~50–80ms
+  const normalSpeed = Math.random() * (300 - 250) + 250 // ~250–300ms
📝 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
const spedUp = Math.random() * (80 - 50) + 150
const normalSpeed = Math.random() * (300 - 250) + 50
const time = isDeleting.value ? spedUp : normalSpeed
const spedUp = Math.random() * (80 - 50) + 50 // ~50–80ms
const normalSpeed = Math.random() * (300 - 250) + 250 // ~250–300ms
const time = isDeleting.value ? spedUp : normalSpeed
🤖 Prompt for AI Agents
In components/awesome/Home.vue around lines 39–41, the speed math is reversed so
deleting is slower than typing; rename variables to reflect behavior and swap
ranges: create deleteSpeed = Math.random() * (80 - 50) + 50 (50–80ms) and
typeSpeed = Math.random() * (300 - 150) + 150 (150–300ms), then set time =
isDeleting.value ? deleteSpeed : typeSpeed so deleting is faster and naming
matches.

@@ -0,0 +1,17 @@
<script lang="ts" setup>
const LayoutPagePdfViewer = defineAsyncComponent(() => import('@/components/layouts/page/PdfViewer.vue'))
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

Verify the component import path casing.

The import uses '@/components/layouts/page/PdfViewer.vue' (lowercase page). Ensure this matches the actual file system path, as most other layout components in this PR use PascalCase directory names (e.g., Page not page).

Run this script to verify the correct path:


🏁 Script executed:

#!/bin/bash
# Find the PdfViewer component to confirm correct path
fd -t f "PdfViewer.vue" components/

Length of output: 37


Update import path casing in pages/mycv.vue

Change the import from

import('@/components/layouts/page/PdfViewer.vue')

to

import('@/components/layouts/Page/PdfViewer.vue')

to match the actual directory name.

🧰 Tools
🪛 ESLint

[error] 2-2: Replace ()·=>·import('@/components/layouts/page/PdfViewer.vue') with ⏎··()·=>·import('@/components/layouts/page/PdfViewer.vue'),⏎

(prettier/prettier)

🤖 Prompt for AI Agents
In pages/mycv.vue around line 2, the asynchronous import uses the wrong
directory casing ('layouts/page/PdfViewer.vue'); update the import path to match
the actual directory name by changing it to 'layouts/Page/PdfViewer.vue' so the
module resolver can find the component.

⚠️ Potential issue | 🟡 Minor

Fix formatting to comply with project standards.

The import statement formatting doesn't match the project's Prettier configuration.

Apply this diff:

-const LayoutPagePdfViewer = defineAsyncComponent(() => import('@/components/layouts/page/PdfViewer.vue'))
+const LayoutPagePdfViewer = defineAsyncComponent(
+  () => import('@/components/layouts/page/PdfViewer.vue'),
+)

Based on static analysis.

📝 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
const LayoutPagePdfViewer = defineAsyncComponent(() => import('@/components/layouts/page/PdfViewer.vue'))
const LayoutPagePdfViewer = defineAsyncComponent(
() => import('@/components/layouts/page/PdfViewer.vue'),
)
🧰 Tools
🪛 ESLint

[error] 2-2: Replace ()·=>·import('@/components/layouts/page/PdfViewer.vue') with ⏎··()·=>·import('@/components/layouts/page/PdfViewer.vue'),⏎

(prettier/prettier)

🤖 Prompt for AI Agents
In pages/mycv.vue around line 2, the async component import line is not
formatted to project Prettier standards; reformat the statement (e.g., ensure
proper spacing/parentheses and add the missing trailing semicolon) or run the
project's Prettier formatter on the file so the line becomes compliant with the
repo style.

Comment on lines +9 to +11
<client-only>
<LayoutPagePdfViewer />
</client-only>
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

Fix indentation for consistent formatting.

The client-only block has inconsistent indentation.

Apply this diff:

       <LayoutPageSection>
         <client-only>
-              <LayoutPagePdfViewer />
-          </client-only>
+          <LayoutPagePdfViewer />
+        </client-only>
       </LayoutPageSection>

Based on static analysis.

📝 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
<client-only>
<LayoutPagePdfViewer />
</client-only>
<LayoutPageSection>
<client-only>
<LayoutPagePdfViewer />
</client-only>
</LayoutPageSection>
🧰 Tools
🪛 ESLint

[error] 10-10: Delete ····

(prettier/prettier)


[error] 11-11: Delete ··

(prettier/prettier)

🤖 Prompt for AI Agents
In pages/mycv.vue around lines 9 to 11, the <client-only> block is indented
inconsistently; fix it by aligning the <client-only> start tag, its child
<LayoutPagePdfViewer /> and the closing </client-only> so their indentation
matches the surrounding template structure (use the same number of spaces/tabs
used in adjacent blocks) to maintain consistent formatting.

<div class="min-h-[calc(100vh+1rem)]">
<div
class="grid gap-8 sm:grid-cols-2 sm:gap-12 lg:grid-cols-2 xl:grid-cols-2 xl:gap-16"
class="grid gap-8 sm:grid-cols-2 sm:gap-12 lg:grid-cols-2 xl:grid-cols-2 xl:gap-16 "
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

Remove trailing spaces.

Lines 72 and 81 have trailing spaces that should be removed for code cleanliness.

As per coding guidelines.

Also applies to: 81-81

🧰 Tools
🪛 ESLint

[error] 72-72: Delete ·

(prettier/prettier)

🤖 Prompt for AI Agents
In pages/post/index.vue around lines 72 and 81, there are trailing spaces at the
end of the class attribute strings; remove the trailing spaces so the class
values end immediately after the last character (no extra whitespace), and
save/format the file (or run the project linter/formatter) to ensure no other
trailing spaces remain.

})
// query
// const query: QueryBuilderParams = { path: '/post' }
const query: QueryBuilderParams = { path: '/post' }
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

Remove or utilize the unused query variable.

The query constant is defined but never used in the component. The template uses ContentList path="/project" instead of referencing this query variable.

If this was intended to be used, apply it to the ContentList component:

-    <LayoutPageSection>
-      <ContentList path="/project">
+    <LayoutPageSection>
+      <ContentList v-bind="query">

Otherwise, remove the unused variable:

-// query
-const query: QueryBuilderParams = { path: '/post' }

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

🤖 Prompt for AI Agents
In pages/project/index.vue around line 59, the constant `query` is declared but
never used; either remove the unused `const query: QueryBuilderParams = { path:
'/post' }` or pass it into the ContentList component (e.g., replace the
hardcoded path prop with the query object or add a prop to accept the query) so
the variable is actually consumed; update the template to use the query or
delete the declaration and run linting to confirm no unused variable remains.


export interface AwesomeLayoutPageNavbarMenu {
type?: 'link' | 'button' | 'dropdown'
type?: 'link' | 'button' | 'dropdown' | any
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

Remove | any to preserve type safety.

Adding | any to the type union defeats the purpose of TypeScript's type system and allows any value, removing compile-time safety guarantees.

If additional menu types are needed, add them explicitly to the union:

-  type?: 'link' | 'button' | 'dropdown' | any
+  type?: 'link' | 'button' | 'dropdown' | 'divider' | 'custom'

Or if the type truly needs to be flexible, use string instead:

-  type?: 'link' | 'button' | 'dropdown' | any
+  type?: 'link' | 'button' | 'dropdown' | string

This maintains some type safety while allowing extensibility.

📝 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
type?: 'link' | 'button' | 'dropdown' | any
type?: 'link' | 'button' | 'dropdown' | 'divider' | 'custom'
🤖 Prompt for AI Agents
In utils/types.ts around line 11, the union type "type?: 'link' | 'button' |
'dropdown' | any" removes type safety by including "any"; replace the "| any"
with explicit additional literal unions for any new menu kinds or with "string"
if you need open extensibility (e.g., add new literals like 'checkbox'|'radio'
or change to string) and update any dependent code to use the chosen narrower
type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants