lunx.docs
DocsFrameworksNuxt

Nuxt Adapter

Nuxt 3 with file-based routing, server-side rendering, Nitro server engine, auto-imports, and universal data fetching using useFetch and useAsyncData.

Nuxt 3 · Nitro · Auto-imports
File-based routing

pages/ directory auto-generates routes. Nested directories create nested routes automatically.

Universal SSR

Pages render on the server first, then hydrate on the client — optimal TTFB and SEO.

Nitro server

server/api/ files become HTTP endpoints via the Nitro server engine. Deployed anywhere.

Auto-imports

Vue APIs, composables, and utils in composables/ and utils/ are auto-imported everywhere.

Data fetching

useFetch() and useAsyncData() handle SSR data fetching with caching and deduplication.

Pinia built-in

Pinia stores in stores/ are auto-imported and SSR-compatible with useState for hydration.

Setup

bash
npm create lunx-dev@latest my-nuxt-app -- --framework nuxt --ts
cd my-nuxt-app && npm install && npm run dev

Pages and layouts

htmlpages/index.vue
<script setup lang="ts">
// useFetch is auto-imported — no import statement needed
const { data: posts, pending, error } = await useFetch('/api/posts', {
  key:   'posts-index',
  lazy:  false,    // SSR: block page render until data is ready
})

// SEO meta
useSeoMeta({
  title:       'Blog — My Nuxt App',
  description: 'Read the latest posts',
  ogImage:     '/og-image.png',
})
</script>

<template>
  <div>
    <h1>Latest Posts</h1>
    <div v-if="pending">Loading...</div>
    <div v-else-if="error">Error: {{ error.message }}</div>
    <ul v-else>
      <li v-for="post in posts" :key="post.id">
        <NuxtLink :to="`/blog/${post.slug}`">{{ post.title }}</NuxtLink>
      </li>
    </ul>
  </div>
</template>

Server API routes

typescriptserver/api/posts/index.get.ts
import { defineEventHandler, getQuery } from 'h3'

export default defineEventHandler(async (event) => {
  const query = getQuery(event)
  const page  = Number(query.page ?? 1)
  const limit = Number(query.limit ?? 10)

  // Direct DB access — this runs server-side only
  const posts = await db.post.findMany({
    skip:    (page - 1) * limit,
    take:    limit,
    orderBy: { createdAt: 'desc' },
    select:  { id: true, title: true, slug: true, excerpt: true },
  })

  return { posts, page, limit }
})

Pinia store with SSR

typescriptstores/useCartStore.ts
// Auto-imported from stores/ — no import needed in components
export const useCartStore = defineStore('cart', () => {
  const items = ref<CartItem[]>([])
  const total = computed(() =>
    items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
  )

  function addItem(item: CartItem) {
    const existing = items.value.find(i => i.id === item.id)
    if (existing) existing.quantity++
    else items.value.push({ ...item, quantity: 1 })
  }

  function removeItem(id: string) {
    items.value = items.value.filter(i => i.id !== id)
  }

  return { items, total, addItem, removeItem }
})
nuxt.config.ts is still used
Lunx manages the build pipeline, but Nuxt module configuration still lives in nuxt.config.ts. Use lunx.config.ts for build-level settings (plugins, security, server) and nuxt.config.ts for Nuxt modules and app config.