import tailwindcss from '@tailwindcss/vite' // Blut24 — Marketing- und Registrierungsseite. // Nuxt 4 (srcDir = app/) + Nitro + Tailwind CSS v4 (Vite plugin, no @nuxtjs/tailwindcss module). export default defineNuxtConfig({ compatibilityDate: '2026-07-01', devtools: { enabled: false }, ssr: true, css: ['~/assets/css/main.css'], vite: { plugins: [tailwindcss()], }, nitro: { // better-sqlite3 ships a native .node binding — never bundle it. externals: { external: ['better-sqlite3'] }, }, runtimeConfig: { // ---- SQLite ------------------------------------------------------------------ // Absolute paths win; relative paths resolve against process.cwd(). clinicDbPath: '', // NUXT_CLINIC_DB_PATH (default data/clinics.db) registrationDbPath: '', // NUXT_REGISTRATION_DB_PATH (default data/registrations.db) // ---- SMTP (localhost:25, no auth — same transport as the ERP) ------------------ smtpHost: 'localhost', // NUXT_SMTP_HOST smtpPort: '25', // NUXT_SMTP_PORT mailFrom: 'Blut24 ', // NUXT_MAIL_FROM mailBcc: '', // NUXT_MAIL_BCC — optional internal copy notifyEmail: '', // NUXT_NOTIFY_EMAIL — internal notification on new registrations // ---- ERP onboarding gate (feature-flagged, see server/utils/erpOnboarding.ts) --- // Read from the plain env names ERP_ONBOARDING_URL / ERP_SERVICE_TOKEN as well. erpOnboardingUrl: '', // NUXT_ERP_ONBOARDING_URL erpServiceToken: '', // NUXT_ERP_SERVICE_TOKEN erpOrganizationId: '', // NUXT_ERP_ORGANIZATION_ID — operator org the records are created under erpCountryId: '208', // NUXT_ERP_COUNTRY_ID — C_Country_ID for Deutschland erpPriceListId: '', // NUXT_ERP_PRICE_LIST_ID erpGroupClinic: '1000002', // NUXT_ERP_GROUP_CLINIC — C_BP_Group "Kliniken" erpGroupCourier: '1000003', // NUXT_ERP_GROUP_COURIER — C_BP_Group "Medizinische Kurierdienste" public: { siteUrl: 'https://app.blut24.com', // NUXT_PUBLIC_SITE_URL androidApkUrl: '#app-download', // NUXT_PUBLIC_ANDROID_APK_URL — placeholder until the APK is published // Operator test domains, mirrored from the server-side REGISTRATION_TEST_DOMAINS. // The FORM does its own domain check for instant feedback, and without this it // blocked a whitelisted address before the request ever reached the server — // the server accepted it, the browser did not. // Publishing the list is acceptable: it is a temporary operator feature (empty in // real production), and a bypassed registration STILL requires confirming a mail // sent to that domain, so knowing the name grants nothing. registrationTestDomains: process.env.REGISTRATION_TEST_DOMAINS || '', }, }, app: { head: { // GERMAN IS THE DEFAULT. app.vue re-declares htmlAttrs.lang from the active locale // (app/composables/useLocale.ts) and, being registered later, wins — so this value // is what a document gets before any language is resolved, never a contradiction. // Same for the description: index.vue sets a reactive, translated one; this static // German fallback only ever surfaces on the two `noindex` legal pages. htmlAttrs: { lang: 'de' }, meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' }, { name: 'theme-color', content: '#B71C1C' }, { name: 'description', content: 'Blut24 — die kostenlose Plattform für Kliniken: Blutkonserven deutschlandweit finden, ' + 'bestellen und rückverfolgen. Mit FEFO-Verfallskontrolle, DGTI-Lieferschein und Scanner-App.', }, ], link: [ { rel: 'icon', type: 'image/svg+xml', href: '/blut24-icon.svg' }, ], }, }, })