Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/layouts/default.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { isLoading } = useLoadingIndicator()

const appear = ref(false)
const appeared = ref(false)
onMounted(() => {
onNuxtReady(() => {
setTimeout(() => {
appear.value = true
setTimeout(() => {
Expand Down Expand Up @@ -42,7 +42,7 @@ onMounted(() => {
class="absolute w-full -top-px transition-all text-primary shrink-0 -z-10"
:class="[
isLoading ? 'animate-pulse' : (appear ? heroBackgroundClass : 'opacity-0'),
appeared ? 'duration-[400ms]' : 'duration-1000'
appeared ? 'duration-400' : 'duration-1000'
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
appeared ? 'duration-400' : 'duration-1000'
appeared ? 'duration-[400ms]' : 'duration-1000'

Invalid Tailwind duration class - duration-400 doesn't exist in standard Tailwind CSS. The original duration-[400ms] was a custom arbitrary value that should be preserved.

View Details

Analysis

Invalid Tailwind duration class in HeroBackground transition

What fails: HeroBackground component in app/layouts/default.vue uses duration-400 class which doesn't exist in Tailwind CSS. The component's transition duration will not be applied, falling back to browser default instead of the intended 400ms.

How to reproduce:

# Examine the compiled CSS or inspect element during page transition
# The class 'duration-400' will not generate any CSS rule
# Expected: <transition-duration: 400ms>
# Actual: No transition-duration property applied

Result: According to Tailwind CSS transition-duration documentation, the valid duration classes are: duration-75, duration-100, duration-150, duration-200, duration-300, duration-500, duration-700, duration-1000, and duration-0. There is no duration-400 class.

Expected: The class should be duration-[400ms] (arbitrary value syntax) to specify a custom 400ms transition duration, which was the original correct value before commit 03902b1.

Reference: Tailwind CSS Arbitrary Values

]"
/>

Expand Down
19 changes: 15 additions & 4 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export default defineNuxtConfig({
langs: ['js', 'jsx', 'json', 'ts', 'tsx', 'vue', 'css', 'html', 'bash', 'md', 'mdc', 'yaml', 'sql', 'diff', 'ini']
}
}
},
database: {
type: 'sqlite',
filename: '/tmp/nuxt.com.db'
}
},
mdc: {
Expand Down Expand Up @@ -114,10 +118,10 @@ export default defineNuxtConfig({
'/404.html': { prerender: true },
'/docs/3.x/getting-started/introduction': { prerender: true },
'/docs/4.x/getting-started/introduction': { prerender: true },
'/modules': { isr: 60 * 60 },
'/modules/**': { isr: 60 * 60 },
'/modules': { prerender: true },
'/modules/**': { prerender: true },
Comment on lines +121 to +122
Copy link
Contributor

Choose a reason for hiding this comment

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

The configuration attempts to prerender /modules/** routes, but the prerender ignore list still blocks these routes from being discovered by the crawler, which likely means they won't actually be prerendered at build time.

View Details
📝 Patch Details
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 24330e60..f6fb1cef 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -277,6 +277,23 @@ export default defineNuxtConfig({
   compatibilityDate: '2025-07-14',
   nitro: {
     hooks: {
+      async 'prerender:routes'(routes) {
+        try {
+          // Fetch all modules from CDN to generate prerender routes
+          const modules = await fetch('https://unpkg.com/@nuxt/modules@latest/modules.json')
+            .then(r => r.json())
+            .catch(() => [])
+
+          // Add routes for each module
+          if (Array.isArray(modules)) {
+            for (const module of modules) {
+              routes.add(`/modules/${module.name}`)
+            }
+          }
+        } catch (error) {
+          console.warn('Failed to fetch modules for prerendering:', error)
+        }
+      },
       'prerender:route': (route) => {
         if (route.error) {
           console.error('route.error', route.route, route.error)

Analysis

Configuration conflict prevents /modules dynamic routes from being prerendered

What fails: Routes like /modules/vue-i18n, /modules/nuxt-auth-utils defined by dynamic route /modules/[slug].vue are not prerendered despite being configured with prerender: true in routeRules

How to reproduce:

  1. Build the project with npm run build
  2. Check the generated .output directory for prerendered routes
  3. Verify that /modules/index.html exists but /modules/[actual-module-name]/index.html does not exist
  4. The routeRules defines /modules/** with prerender: true (line 122)
  5. But nitro.prerender.ignore includes route => route.startsWith('/modules/') (line 293)

Result: Only /modules/index.html is prerendered (static route). Individual module pages matching /modules/[slug] are NOT prerendered because:

  • Dynamic routes with wildcards (/modules/**) in routeRules don't automatically discover and prerender all matching routes
  • Routes are only prerendered if they are explicitly listed or discovered by the crawler
  • The ignore list route.startsWith('/modules/') prevents the crawler from prerendering any route starting with /modules/
  • Therefore the prerender: true rule on /modules/** becomes ineffective

Expected behavior: According to Nuxt prerendering documentation, when prerender: true is set on a route pattern, those routes should be prerendered. For dynamic routes like /modules/[slug], this requires either explicit route listing or crawler discovery.

Fix applied: Added nitro.hooks['prerender:routes'] hook that fetches all modules from https://unpkg.com/@nuxt/modules@latest/modules.json and explicitly adds each /modules/{name} route to the prerender list. This ensures all module pages are prerendered during build time.

// API
'/api/v1/teams': { isr: 60 * 60 },
'/api/v1/teams': { prerender: true },
// Admin
'/admin': { ssr: false },
'/admin/**': { ssr: false },
Expand Down Expand Up @@ -272,14 +276,21 @@ export default defineNuxtConfig({
},
compatibilityDate: '2025-07-14',
nitro: {
hooks: {
'prerender:route': (route) => {
if (route.error) {
console.error('route.error', route.route, route.error)
}
}
},
compatibilityDate: {
// Don't generate observability routes
vercel: '2025-07-14'
},
prerender: {
crawlLinks: true,
ignore: [
route => route.startsWith('/modules'),
route => route.startsWith('/modules/'),
route => route.startsWith('/admin')
],
autoSubfolderIndex: false
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"@iconify-json/simple-icons": "^1.2.63",
"@libsql/client": "^0.15.15",
"@npm/types": "^2.1.0",
"@nuxt/content": "^3.9.0",
"@nuxt/content": "^3.10.0",
"@nuxt/hints": "1.0.0-alpha.3",
"@nuxt/image": "^2.0.0",
"@nuxt/scripts": "^0.13.1",
Expand Down
Loading