// https://nuxt.com/docs/api/configuration/nuxt-config import fs from 'node:fs' import path from 'node:path' import tailwindcss from '@tailwindcss/vite' export default defineNuxtConfig({ compatibilityDate: '2024-04-03', ssr: false, modules: [ '@nuxtjs/color-mode', 'nuxt-security', '@vueuse/nuxt', 'radix-vue/nuxt', '@nuxtjs/sitemap', ], css: ['~/assets/css/main.css'], app: { pageTransition: false, layoutTransition: false }, components: [ { path: '~/components', pathPrefix: false, }, ], nitro: { preset: 'bun', experimental: { tasks: true, websocket: true, }, watchOptions: { usePolling: true, }, rollupConfig: { external: ['bun'] }, }, runtimeConfig: { session: { maxAge: 60*60*24*31, password: '699c46bd-9aaa-4364-ad01-510ee4fe7013', }, database: 'db.sqlite', mail: { host: '', port: '', user: '', passwd: '', } }, routeRules: { '/api/auth/session': { security: { rateLimiter: { headers: true, interval: 100, tokensPerInterval: 3 }, } }, '/api/auth/login': { security: { rateLimiter: { headers: true, interval: 1000, tokensPerInterval: 1 }, } }, '/api/auth/register': { security: { rateLimiter: { headers: true, interval: 1000, tokensPerInterval: 1 }, } }, '/api/file/**': { security: { rateLimiter: false, } } }, security: { rateLimiter: { headers: true, interval: 1000, tokensPerInterval: 10 }, headers: { contentSecurityPolicy: { "img-src": "'self' data: blob:", "base-uri": "localhost:*" } }, xssValidator: { escapeHtml: false, }, }, sitemap: { exclude: ['/admin/**', '/explore/edit', '/user/**', '/character/**', '/campaign/**'], sources: ['/api/__sitemap__/urls'] }, experimental: { componentIslands: { selectiveClient: true, }, defaults: { nuxtLink: { prefetchOn: { interaction: false, visibility: false, } } } }, devServer: { https: { key: fs.readFileSync(path.resolve(__dirname, 'localhost+1-key.pem')).toString('utf-8'), cert: fs.readFileSync(path.resolve(__dirname, 'localhost+1.pem')).toString('utf-8'), } }, vite: { plugins: [ tailwindcss(), ], server: { hmr: { protocol: 'wss', host: 'localhost', port: 3000, clientPort: 3000, path: '/ws' }, }, optimizeDeps: { include: [ '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element', '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item', '@atlaskit/pragmatic-drag-and-drop/combine', '@atlaskit/pragmatic-drag-and-drop/element/adapter', '@codemirror/autocomplete', '@codemirror/commands', '@codemirror/lang-markdown', '@codemirror/language', '@codemirror/search', '@codemirror/state', '@codemirror/view', '@floating-ui/dom', '@iconify/vue', '@lezer/common', '@lezer/highlight', 'hast-util-heading', 'hast-util-heading-rank', 'hast-util-select', 'iconify-icon', 'lodash.capitalize', 'mdast-util-find-and-replace', 'mdast-util-to-string', 'remark-breaks', 'remark-frontmatter', 'remark-gfm', 'remark-parse', 'remark-rehype', 'remark-stringify', 'strip-markdown', 'unified', 'unist-util-visit', 'zod', 'zod/v4', ] }, }, vue: { compilerOptions: { isCustomElement: (tag) => tag === 'iconify-icon', } }, devtools: { enabled: false, } })