Restructure the repo into a pnpm + Turborepo monorepo: - apps/web: Nuxt 4 site, now server-rendered and reading all content from the API; pages cached with SWR and purged on content changes - apps/api: NestJS 12 + Prisma 7 + PostgreSQL. Auth with short-lived access tokens and rotating httpOnly refresh cookies, roles (ADMIN, EDITOR), catalog, editable site sections, media upload to S3-compatible storage (converted to WebP), contact messages, audit log - apps/admin: Vue 3 admin panel (Ant Design Vue, Pinia, Tailwind) for products, categories, site sections, messages, media and users - packages/shared: Zod schemas and types shared by API and admin Also: - seed script that loads the original 8 categories / 89 products and section content - Docker images for api (with a one-off migrate service), web, admin, and an nginx gateway for both domains - dev and production compose files, daily database backup service - API e2e tests Removes the committed static out/ build and the old root Dockerfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
2.3 KiB
TypeScript
78 lines
2.3 KiB
TypeScript
import tailwindcss from "@tailwindcss/vite";
|
|
import { siteConfig } from "./shared/config/site";
|
|
|
|
/** Pages are server-rendered and cached; the cache is dropped by the API after content changes. */
|
|
const PAGE_CACHE_SECONDS = 60;
|
|
|
|
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/IRANSansWebFaNum.woff2",
|
|
as: "font",
|
|
type: "font/woff2",
|
|
crossorigin: "",
|
|
},
|
|
{
|
|
rel: "preload",
|
|
href: "/fonts/IRANSansWebFaNum_Bold.woff2",
|
|
as: "font",
|
|
type: "font/woff2",
|
|
crossorigin: "",
|
|
},
|
|
{ rel: "icon", type: "image/svg+xml", href: siteConfig.favicon },
|
|
{ rel: "manifest", href: "/manifest.webmanifest" },
|
|
],
|
|
},
|
|
},
|
|
|
|
// overridable at runtime with NUXT_API_INTERNAL_URL, NUXT_REVALIDATE_SECRET, NUXT_PUBLIC_SITE_URL ...
|
|
runtimeConfig: {
|
|
/** API base URL used during server-side rendering (inside Docker: http://api:4000/api) */
|
|
apiInternalUrl: "http://localhost:4000/api",
|
|
/** shared secret the API sends to /_internal/revalidate */
|
|
revalidateSecret: "",
|
|
public: {
|
|
/** API base URL used by the browser (same origin, routed by nginx / the dev proxy) */
|
|
apiBase: "/api",
|
|
siteUrl: siteConfig.url,
|
|
},
|
|
},
|
|
|
|
routeRules: {
|
|
"/": { swr: PAGE_CACHE_SECONDS },
|
|
"/categories/**": { swr: PAGE_CACHE_SECONDS },
|
|
"/sitemap.xml": { swr: 3600 },
|
|
"/manifest.webmanifest": { swr: 3600 },
|
|
},
|
|
|
|
nitro: {
|
|
// in production nginx routes these paths; in dev the Nuxt server forwards them
|
|
devProxy: {
|
|
"/api": { target: "http://localhost:4000/api", changeOrigin: true },
|
|
"/media": { target: "http://localhost:9000/imen-media", changeOrigin: true },
|
|
},
|
|
},
|
|
|
|
vite: {
|
|
plugins: [tailwindcss()],
|
|
ssr: { noExternal: ["ant-design-vue", "@ant-design/icons-vue"] },
|
|
},
|
|
|
|
typescript: { strict: true },
|
|
});
|