// @ts-check /** * Astro configuration for Greg Kilmer's profile site. * * Stack: * - @astrojs/node (standalone) -> Node server with API routes for the Cosmos homelab. * - @astrojs/react -> React 19 islands for interactive components (mobile menu, * theme toggle, animated hero background, contact form). * - @astrojs/mdx -> MDX content collections (projects, experience). * - @tailwindcss/vite -> Tailwind v4 via the Vite plugin (CSS-first config in styles). * - astro-icon + mdi set -> render Material Design Icons (no emojis, per spec). * * The `standalone` output produces `dist/server/entry.mjs`, launched by `npm run serve` * or by the Docker runtime. API routes under src/pages/api/* are served by the same server. */ import { defineConfig } from 'astro/config'; import node from '@astrojs/node'; import react from '@astrojs/react'; import mdx from '@astrojs/mdx'; import tailwindcss from '@tailwindcss/vite'; // `SITE_URL` lets us produce absolute URLs in metadata / API responses. Defaults to the // production domain from the spec; override locally or in CI as needed. const SITE_URL = process.env.SITE_URL ?? 'https://gregkilmer.com'; // Astro exposes the configured server host/port to the Node adapter via env at runtime. // We read them here only for documentation; the adapter picks them up automatically. const PORT = Number(process.env.PORT ?? 4321); const HOST = process.env.HOST ?? '0.0.0.0'; /** * React-refresh preamble, injected into the layout
in dev (see * BaseLayout.astro). Returned as a string so the layout can emit it as an * inline module script that runs BEFORE any island module evaluates. * * Why this is needed: Vite 8 (Rolldown) + @vitejs/plugin-react 5.x does not * inject this preamble through Astro's SSR dev HTML pipeline, so the compiled * islands call $RefreshSig$() at module-eval time, throw, and never hydrate — * surfacing as "_jsxDEV is not a function" and leaving every React island * (carousel, mobile menu, contact/order forms, animated background) dead. * * Production builds are unaffected: the client bundle uses jsx/jsxs directly * and never touches $RefreshSig$. Remove this once @astrojs/react ships * plugin-react 6, which handles Rolldown natively. */ export const REACT_REFRESH_PREAMBLE = "import { injectIntoGlobalHook } from '/@react-refresh';\n" + 'injectIntoGlobalHook(window);\n' + 'window.$RefreshReg$ = () => {};\n' + 'window.$RefreshSig$ = () => (type) => type;'; export default defineConfig({ // Used for canonical URLs, sitemaps, and absolute metadata. Keep this in sync with the // deployed domain on your Cosmos reverse proxy. site: SITE_URL, // Server output mode. `standalone` emits a self-contained Node server we can run in a // container. This is what enables /api/* routes to execute server-side. output: 'server', adapter: node({ mode: 'standalone', }), // Page-to-page transitions using the native View Transitions API. Persists the nav and // animates content swaps. Honored automatically by Astro's