Files
imen_pishghaman/nuxt.config.ts
T
S. EsmaeiliandClaude Opus 4.6 e31ef5a21f feat: migrate landing from Next.js to Nuxt 4 (Vue 3)
Full 1:1 migration preserving all visuals, animations and behavior:
- Nuxt 4 + Vue 3 (script setup, TypeScript strict) with SSG output
- Tailwind CSS v4 with @tailwindcss/vite
- Ant Design Vue 4 (dark theme, RTL, Persian locale) for design system
- Pinia for state management (ui + contact stores)
- motion-v (framer-motion port) for all animations
- lucide-vue-next for icons
- SEO improvements: og:image, canonical fix, real 404 page, JSON-LD services
- JS bundle reduced from 302KB to 239KB gzip
- Docker/nginx deployment preserved (out/ -> nginx)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-10-06 16:28:05 +03:30

71 lines
2.2 KiB
TypeScript

import { fileURLToPath } from "node:url";
import tailwindcss from "@tailwindcss/vite";
import { siteConfig } from "./shared/config/site";
/** Unmatched path rendered through error.vue at build time and saved as out/404.html */
const NOT_FOUND_ROUTE = "/__not-found";
export default defineNuxtConfig({
compatibilityDate: "2026-10-01",
ssr: true,
devtools: { enabled: false },
modules: ["@pinia/nuxt"],
css: ["~/assets/css/main.css", "~/assets/css/antd-overrides.css"],
app: {
head: {
htmlAttrs: { lang: siteConfig.lang, dir: siteConfig.dir },
bodyAttrs: {
class: "relative min-h-screen bg-bg font-sans text-ink antialiased",
},
charset: "utf-8",
viewport: "width=device-width, initial-scale=1",
link: [
{
rel: "preload",
href: "/fonts/Vazirmatn-Variable.woff2",
as: "font",
type: "font/woff2",
crossorigin: "",
},
{
rel: "preload",
href: "/fonts/IBMPlexMono-Regular.woff2",
as: "font",
type: "font/woff2",
crossorigin: "",
},
{ rel: "icon", type: "image/svg+xml", href: siteConfig.favicon },
{ rel: "manifest", href: "/manifest.webmanifest" },
],
},
},
vite: {
plugins: [tailwindcss()],
ssr: { noExternal: ["ant-design-vue", "@ant-design/icons-vue"] },
},
// Static export (`npm run build` → ./out), served by nginx in Docker — same flow as the Next build.
nitro: {
output: { publicDir: fileURLToPath(new URL("./out", import.meta.url)) },
prerender: {
crawlLinks: false,
routes: ["/", "/robots.txt", "/sitemap.xml", "/manifest.webmanifest", NOT_FOUND_ROUTE],
},
hooks: {
// Nuxt's own /404.html is an empty SPA shell. Replace it with a server-rendered error.vue
// (real content + noindex in the static HTML) produced by prerendering an unmatched route.
"prerender:generate"(route) {
if (route.route === "/404.html") route.skip = true;
if (route.route === NOT_FOUND_ROUTE && route.error?.statusCode === 404) {
route.error = undefined;
route.fileName = "/404.html";
}
},
},
},
typescript: { strict: true },
});