Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
24 changes: 19 additions & 5 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,21 +276,31 @@ 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
}
},
hub: {
db: 'sqlite',
db: {
dialect: 'sqlite',
applyMigrationsDuringBuild: false
},
kv: true,
cache: true
},
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@
"@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",
"@nuxt/ui": "^4.2.1",
"@nuxt/vite-builder": "https://pkg.pr.new/@nuxt/vite-builder@33682",
"@nuxthub/core": "npm:@nuxthub/core-nightly@0.10.0-20251210-113644-c25eff9",
"@nuxthub/core": "^0.10.3",
"@nuxtjs/html-validator": "^2.1.0",
"@nuxtjs/mcp-toolkit": "^0.5.2",
"@nuxtjs/mdc": "^0.19.1",
Expand Down
Loading
Loading