{"id":27253,"plugin_id":"plugin_asdk_app_691f1f8f72408191afdbbdf8242bdf86","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-07T00:02:43.580Z","digest":"ca8ce3264e9da19899b344612f60fef423d01d8c3b91bfb85999ab41487fe182","against":24997,"payload":{"description":"Deploy and configure web frameworks on Netlify — build settings and SSR/edge adapters plus local platform emulation and env vars. Use when setting up or fixing a framework deploy (Next.js / Astro / Nuxt / SvelteKit / Remix / React Router / TanStack Start / SolidStart / Gatsby / Angular / Vite / Express / Hydrogen / Hugo / Eleventy / Vue / React), adding SSR or edge functions or middleware wired to Netlify context, fixing SPA redirect and catch-all rules, setting a build command or publish directory, or debugging \"why isn't my env var updating\" and framework build failures.","included_files":[{"relative_path":"references/astro.md","size_in_bytes":4730},{"relative_path":"references/nextjs.md","size_in_bytes":4555},{"relative_path":"references/nuxt.md","size_in_bytes":1556},{"relative_path":"references/sveltekit.md","size_in_bytes":2114},{"relative_path":"references/tanstack.md","size_in_bytes":2943},{"relative_path":"references/vite.md","size_in_bytes":3216}],"name":"netlify-frameworks","skill_md_contents":"---\nname: netlify-frameworks\ndescription: Deploy and configure web frameworks on Netlify — build settings and SSR/edge adapters plus local platform emulation and env vars. Use when setting up or fixing a framework deploy (Next.js / Astro / Nuxt / SvelteKit / Remix / React Router / TanStack Start / SolidStart / Gatsby / Angular / Vite / Express / Hydrogen / Hugo / Eleventy / Vue / React), adding SSR or edge functions or middleware wired to Netlify context, fixing SPA redirect and catch-all rules, setting a build command or publish directory, or debugging \"why isn't my env var updating\" and framework build failures.\n---\n\nRoute framework-specific deep work to the guides in this skill: `references/astro.md`, `references/nextjs.md`, `references/nuxt.md`, `references/sveltekit.md`, `references/tanstack.md`, `references/vite.md`.\n\n## Env vars: modern rules (read first)\n\nEnv values are injected **at build time**. Any change (client- or server-side) requires a **redeploy** — editing a var in the UI/CLI does NOT reach the live site or already-deployed functions until a new build runs.\n\n**Never use a client prefix for secrets.** Client-prefixed vars are inlined into the browser bundle:\n`VITE_`, `NEXT_PUBLIC_`, `PUBLIC_`, `NUXT_PUBLIC_`, `REACT_APP_`, `GATSBY_`, `VUE_APP_`.\n\nClient-embed prefixes by framework: CRA `REACT_APP_`, Gatsby `GATSBY_`, Next `NEXT_PUBLIC_`, Nuxt `NUXT_ENV_`, Vue CLI `VUE_APP_`.\n\n**Scopes:** build-time access needs **Builds** scope; SSR/DSG runtime access needs **both Functions and Builds**. `netlify.toml` is read only during build — functions cannot read it at runtime; set runtime vars in UI/CLI/API.\n\nNetlify build variables can't be used as values in the UI or `netlify.toml` env sections. Set them inline before the build command:\n```toml\n[build]\n  command = \"REACT_APP_CONTEXT=$CONTEXT npm run build\"\n```\n\n## SPA redirects and the SSR catch-all footgun\n\nSPAs (React, Vue CLI, Vite, Nuxt in SPA mode) need a rewrite to serve `index.html` for `pushState`:\n```\n/* /index.html 200\n```\n\n**Remove any SPA catch-all when adopting an SSR adapter.** A leftover `/* → /index.html 200` silently serves static `index.html` for SSR pages and API routes — user redirects beat adapter-generated routes.\n\n## Local dev with platform emulation (no Netlify CLI)\n\nVite-based frameworks emulate Netlify primitives (functions, edge functions, blobs, Netlify Database, Cache API, Image CDN, redirects/rewrites, headers, env vars, AI Gateway) in the dev server:\n\n| Framework | Plugin/module | Run |\n|-----------|---------------|-----|\n| Astro (5.12+) | built-in (Netlify Vite plugin auto-loaded) | `astro dev` |\n| Nuxt | `@netlify/nuxt` | `nuxt dev` |\n| React Router | `@netlify/vite-plugin` | `react-router dev` |\n| SolidStart 2 | `@netlify/vite-plugin` | `vite dev` |\n| TanStack Start | `@netlify/vite-plugin-tanstack-start` | (vite) |\n| Vite | `@netlify/vite-plugin` | `npx vite` |\n\nStill need `netlify dev` (Netlify CLI) for: Gatsby generated functions (run `netlify build` first), Angular SSR local test (`netlify serve`), and frameworks without a Vite plugin.\n\n**`netlify dev` gotcha:** with both a custom `command` and a `targetPort` in `[dev]`, you must set `framework = \"#custom\"` — otherwise the detector runs and your custom command is silently ignored.\n\n## Build settings by framework\n\n| Framework | Build command | Publish |\n|-----------|---------------|---------|\n| Angular (standard) | `ng build --prod` | `dist/YOUR_PROJECT_NAME` |\n| Astro | `astro build` | `dist` |\n| Create React App | `react-scripts build` | `build` |\n| Eleventy | `eleventy` | `_site` |\n| Gatsby | `gatsby build` | `public` |\n| Hugo | `hugo` | `public` |\n| Hydrogen | `remix vite:build` | `dist/client` |\n| Next.js (SSR/hybrid) | `next build` | `.next` |\n| Next.js (static export) | `next build && next export` | `out` (`NETLIFY_NEXT_PLUGIN_SKIP=true`) |\n| Nuxt 3 | `nuxt build` | `dist` |\n| Nuxt 2 | `nuxt generate` | `dist` |\n| React Router | `react-router build` | `build/client` |\n| Remix (Vite) | `remix vite:build` | `build/client` |\n| SolidStart 2 (Vite plugin) | `vite build` | `dist/client` |\n| SolidStart 2 (Nitro) | `vite build` | `dist` |\n| SolidStart 1.x | `vinxi build` | `dist` |\n| SvelteKit | `vite build` | `build` |\n| TanStack Start (1.132.0+) | `vite build` | `dist/client` |\n| Vite | `vite build` | `dist` |\n| Vue CLI | `vue-cli-service build` | `dist` |\n\nDetection suggests these; override in `netlify.toml` or UI (project configuration > Build & deploy > Continuous deployment > Build settings).\n\n## SSR / adapter setup\n\n### Astro\n`npx astro add netlify` installs the adapter and edits `astro.config.mjs`. Adapter needed for SSR and out-of-the-box Image CDN for `<Image />`. SSR → Netlify Functions; middleware → Edge Functions. Adapter-less deploy only if no server features and no Image CDN need. Skew protection from 5.15.0.\n\n### Next.js (13.5+ only)\nZero-config via the OpenNext adapter (`@netlify/plugin-nextjs`). Do NOT pin the version — Netlify auto-updates each build. Treat the legacy adapter as read-only history, never a recommendation.\nAdapter provisions: serverless function for SSR/ISR/PPR/route handlers/Server Actions; Edge Function for Middleware; Full Route + Data Cache; Image CDN with `next/image`.\nSkew protection is opt-in: set `NETLIFY_NEXT_SKEW_PROTECTION=true`, redeploy. No automatic support for client `fetch` — direct calls with `x-deployment-id: process.env.NEXT_DEPLOYMENT_ID`. Details in `references/nextjs.md`.\n\n### SvelteKit\n```bash\nnpm install -D @sveltejs/adapter-netlify\n```\n```js\nimport adapter from '@sveltejs/adapter-netlify';\nexport default { kit: { adapter: adapter() } };\n```\nReplace `@sveltejs/adapter-auto` with the specific import. SSR routes → a `render` function.\n- `split: true` → one function per route. **Incompatible with Edge Functions** (`edge: false` or omit).\n- `edge: true` → SSR in a Deno edge function; can't combine with `split`.\n- **Redirects NOT supported in `netlify.toml`** — use `_redirects`.\n- Edge functions don't work locally with `netlify dev` for SvelteKit.\n\n### React Router (7+)\nNew: `npx create-react-router@latest --template netlify/react-router-template`. Existing:\n```bash\nnpm install @netlify/vite-plugin-react-router\n```\nAdd `netlifyReactRouter()` to Vite plugins. Default target = Serverless Functions.\n**Edge (Deno):** needs plugin v2.1.1+, set `edge: true`, and you **must** create `app/entry.server.tsx`:\n```typescript\nexport { default } from 'virtual:netlify-server-entry'\n```\nExclude your own function paths: `netlifyReactRouter({ edge: true, excludedPaths: ['/api/*'] })`.\n**Moving back to Serverless:** remove `edge: true` AND delete `app/entry.server.tsx`.\nMiddleware (React Router v7.9.0+, plugin v2.0.0+): opt in via `future.v8_middleware`; import `netlifyRouterContext` from `@netlify/vite-plugin-react-router/serverless` (or `/edge` when `edge: true`); access `context.get(netlifyRouterContext)`.\n\n### Remix\nNew: `npx create-remix@latest --template netlify/remix-template` (CLI prompts functions vs Edge Functions). Manual (Remix Vite required):\n```bash\nnpm install --save-dev @netlify/remix-adapter\n```\nAdd `netlifyPlugin()` from `@netlify/remix-adapter/plugin` to Vite plugins.\n\n### Nuxt\nSSR via Nitro, automatic on Nuxt 3. Local parity via `@netlify/nuxt` (`npx nuxi module add @netlify/nuxt`).\n- SSR on Edge Functions requires a different Nitro deployment preset (not auto-detected).\n- pnpm + Nuxt 3: set `PNPM_FLAGS=--shamefully-hoist`.\n- `nuxt/image` auto-uses Netlify Image CDN; set remote domains in `nuxt.config.ts`.\n\n### SolidStart\nSolidStart 2 builds on Vite — **no SolidStart-specific adapter**. Install `@netlify/vite-plugin`:\n```ts\nimport netlify from \"@netlify/vite-plugin\";\nimport { solidStart } from \"@solidjs/start/config\";\nimport { defineConfig } from \"vite\";\nexport default defineConfig({\n  plugins: [solidStart(), netlify({ build: { enabled: true } })],\n});\n```\nPublish `dist/client`. SSR routes, server functions, middleware → Netlify Functions, zero extra config.\n**Nitro alternative:** add `nitro()`, use plain `netlify()` (no `build.enabled`), publish `dist`.\nSolidStart 1: Nitro auto-configures; optionally set `preset: \"netlify\"` in `app.config.ts`; `vinxi build` / `dist`.\n\n### TanStack Start\nReact (and Solid.js) full-stack; SSR/Server Routes/Server Functions/middleware → serverless functions.\n```bash\nnpm install -D @netlify/vite-plugin-tanstack-start\n```\nAdd `netlify()` to Vite plugins alongside `tanstackStart()`; `vite build` / `dist/client` (1.132.0+). Netlify CLI deploys require netlify-cli 17.31+. Older versions: see `references/tanstack.md`.\n\n### Gatsby\n- **5.12.0+ (adapter):** auto-detects and installs `gatsby-adapter-netlify` (zero-config). Generates functions `SSR`, `DSG`. No Essential Gatsby plugin needed.\n- **5.11.0 or earlier (Essential Gatsby plugin):** auto-installs `@netlify/plugin-gatsby`; also manually install `gatsby-plugin-netlify` (required for SSR, Gatsby redirects, asset caching). Generates `__api`, `__ssr`, `__dsg`, `__ipx`. Skip via `NETLIFY_SKIP_GATSBY_FUNCTIONS` (all) / `NETLIFY_SKIP_API_FUNCTION` / `NETLIFY_SKIP_SSR_FUNCTION` / `NETLIFY_SKIP_DSG_FUNCTION`.\n- Gatsby 5 requires Node 18.\n- Large sites: set `GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE` to load datastore from CDN (avoids max function deploy size; slower first SSR/DSG load).\n- Image CDN: set `NETLIFY_IMAGE_CDN=true` (Contentful/Drupal/WordPress source plugins). **Not supported on 5.12.x with adapter — upgrade to 5.13.0+.**\n- `StaticImage` and `gatsby-transformer-sharp` don't work for SSR/DSG — host images on a CDN.\n\n### Angular\nSSR auto-configured via an Edge Function. Suggested dev: `ng serve` / `4200`.\n- **SSR pages are NOT subject to `_redirects` or `netlify.toml` redirects** — SSR uses Edge Functions that run before redirects. Use Angular's built-in redirects.\n- Access `Request`/`Context` in SSR via `netlify.request` / `netlify.context` providers (from `@netlify/edge-functions`); unavailable client-side or during prerendering. Test locally with `netlify serve`.\n- `NgOptimizedImage` auto-uses Image CDN; set `remote_images` (array of regex) under `[images]` in `netlify.toml`.\n\n### Express\nNode 18.14.0+. Deploy as a Netlify Function via `serverless-http`:\n```bash\nnpm i express serverless-http @netlify/functions @types/express\n```\n```ts\n// netlify/functions/api.ts\nimport express, { Router } from \"express\";\nimport serverless from \"serverless-http\";\nconst api = express();\nconst router = Router();\nrouter.get(\"/hello\", (req, res) => res.send(\"Hello World!\"));\napi.use(\"/api/\", router);\nexport const handler = serverless(api);\n```\n```toml\n[functions]\n  external_node_modules = [\"express\"]\n  node_bundler = \"esbuild\"\n[[redirects]]\n  force = true\n  from = \"/api/*\"\n  status = 200\n  to = \"/.netlify/functions/api/:splat\"\n```\nNo frontend: set a placeholder build command (e.g. `echo Building Functions`). All Function limits apply; not recommended as background/scheduled functions.\n\n### Hydrogen\nShopify stack on React Router 7. **SSR only on Netlify Edge Functions — Netlify Functions NOT officially supported.** Node 24+. Use the starter:\n```bash\nnpm create @shopify/hydrogen@latest -- --template https://github.com/netlify/hydrogen-template\ncp .env.example .env && npm run dev\n```\n\n## Static-site gotchas\n\n### Hugo\nSet `HUGO_VERSION` (any release after 0.19) in `[build.environment]` — a missing/mismatched version causes `exit code: 255`. Install themes as **git submodules** (`git submodule add ...`), not `git clone`.\n\n### Eleventy\n`eleventy` / `_site`. **Build plugins require editing `.gitignore`: change `node_modules` to `**/node_modules/**`** — otherwise Netlify plugins and Eleventy collide on `.netlify/plugins/node_modules/` and the build errors.\n\n## Vite meta-framework support matrix\nAstro (auto on 5.12+), Nuxt (via `@netlify/nuxt`), TanStack Start (via `@netlify/vite-plugin-tanstack-start`), React Router, SolidStart — all **full**. SvelteKit — **experimental**.\n\n## Deploy via CLI (Express, Nuxt, React, Vite)\n```sh\nnpm install netlify-cli -g\nnetlify init\n```\nFollow prompts to create/link the site and set build settings.\n\n<!-- Node version floors (18.14.0+) are stated per-framework where documented; no cross-framework build-image default is given in sources. -->\n\n<!-- system: agent-context/frameworks/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->\n# Netlify house rules (frameworks)\n\nThese are org conventions, not docs facts — merged into the rendered skill by\nctx-gen and never generated. Owned by the skills maintainer.\n\n1. Per-framework deep guides live in this skill: `references/astro.md`,\n   `references/nextjs.md`, `references/nuxt.md`, `references/sveltekit.md`,\n   `references/tanstack.md`, `references/vite.md` — route framework-specific\n   work there before improvising.\n2. Next.js: modern runtime (v5, Next ≥13.5) only — treat the legacy adapter\n   as read-only history, never a recommendation.\n3. Remove any SPA catch-all (`/* → /index.html 200`) when adopting an SSR\n   adapter — user redirects beat adapter-generated routes, so a leftover\n   catch-all silently serves static `index.html` for SSR pages and API routes.\n4. Any env var change — client- or server-side — requires a redeploy. Values\n   are injected at build time; editing one in the UI/CLI does not reach the\n   live site or already-deployed functions until a new build runs.\n5. `netlify dev` with both a custom `command` and a `targetPort` requires\n   `framework = \"#custom\"` in the `[dev]` block — otherwise the detector runs\n   and the custom command is silently ignored.\n6. Never use a client prefix (`VITE_`, `NEXT_PUBLIC_`, `PUBLIC_`,\n   `NUXT_PUBLIC_`, `REACT_APP_`, `GATSBY_`, `VUE_APP_`) for secrets —\n   client-prefixed vars are inlined into the browser bundle.\n7. Next.js skew protection is version-conditional: below Next 14.1.4 the\n   `NETLIFY_NEXT_SKEW_PROTECTION` env var is not sufficient on its own —\n   `experimental.useDeploymentId` (plus `useDeploymentIdServerActions` when\n   server actions are used) must also go in `next.config.js`. Always ask for\n   or state the version condition; never present the env var as the whole\n   setup.\n8. Client `fetch` calls are not covered by Next.js skew protection by default.\n   Give both options. Next.js 15.4+ has an experimental `useSkewCookie` flag\n   that carries the deployment identifier in a cookie so it rides along on\n   client `fetch` calls; Netlify supports it, but say it is not\n   production-ready and that it holds visitors on the older deploy until the\n   cookie clears. The other option, on any version, is adding\n   `x-deployment-id` with `process.env.NEXT_DEPLOYMENT_ID` per call.\n"},"changes":[{"path":"/description","type":"changed","before":"Guide for deploying web frameworks on Netlify. Use when setting up a framework project (Vite/React, Astro, TanStack Start, Next.js, Nuxt, SvelteKit, Remix) for Netlify deployment, configuring adapters or plugins, or troubleshooting framework-specific Netlify integration. Covers what Netlify needs from each framework and how adapters handle server-side rendering.","after":"Deploy and configure web frameworks on Netlify — build settings and SSR/edge adapters plus local platform emulation and env vars. Use when setting up or fixing a framework deploy (Next.js / Astro / Nuxt / SvelteKit / Remix / React Router / TanStack Start / SolidStart / Gatsby / Angular / Vite / Express / Hydrogen / Hugo / Eleventy / Vue / React), adding SSR or edge functions or middleware wired to Netlify context, fixing SPA redirect and catch-all rules, setting a build command or publish directory, or debugging \"why isn't my env var updating\" and framework build failures."},{"path":"/included_files","type":"changed","before":[{"relative_path":"LICENSE.txt","size_in_bytes":10776},{"relative_path":"agents/openai.yaml","size_in_bytes":353},{"relative_path":"assets/netlify-small.svg","size_in_bytes":1291},{"relative_path":"assets/netlify.png","size_in_bytes":2686},{"relative_path":"references/astro.md","size_in_bytes":3066},{"relative_path":"references/nextjs.md","size_in_bytes":2425},{"relative_path":"references/tanstack.md","size_in_bytes":1449},{"relative_path":"references/vite.md","size_in_bytes":2406}],"after":[{"relative_path":"references/astro.md","size_in_bytes":4730},{"relative_path":"references/nextjs.md","size_in_bytes":4555},{"relative_path":"references/nuxt.md","size_in_bytes":1556},{"relative_path":"references/sveltekit.md","size_in_bytes":2114},{"relative_path":"references/tanstack.md","size_in_bytes":2943},{"relative_path":"references/vite.md","size_in_bytes":3216}]},{"path":"/skill_md_contents","type":"changed","before":"---\nname: netlify-frameworks\ndescription: Guide for deploying web frameworks on Netlify. Use when setting up a framework project (Vite/React, Astro, TanStack Start, Next.js, Nuxt, SvelteKit, Remix) for Netlify deployment, configuring adapters or plugins, or troubleshooting framework-specific Netlify integration. Covers what Netlify needs from each framework and how adapters handle server-side rendering.\n---\n\n# Frameworks on Netlify\n\nNetlify supports any framework that produces static output. For frameworks with server-side capabilities (SSR, API routes, middleware), an adapter or plugin translates the framework's server-side code into Netlify Functions and Edge Functions automatically.\n\n## How It Works\n\nDuring build, the framework adapter writes files to `.netlify/v1/` — functions, edge functions, redirects, and configuration. Netlify reads these to deploy the site. You do not need to write Netlify Functions manually when using a framework adapter for server-side features.\n\n## Detecting Your Framework\n\nCheck these files to determine the framework:\n\n| File | Framework |\n|---|---|\n| `astro.config.*` | Astro |\n| `next.config.*` | Next.js |\n| `nuxt.config.*` | Nuxt |\n| `vite.config.*` + `react-router` | Vite + React (SPA or Remix) |\n| `app.config.*` + `@tanstack/react-start` | TanStack Start |\n| `svelte.config.*` | SvelteKit |\n\n## Framework Reference Guides\n\nEach framework has specific adapter/plugin requirements and local dev patterns:\n\n- **Vite + React (SPA or with server routes)**: See [references/vite.md](references/vite.md)\n- **Astro**: See [references/astro.md](references/astro.md)\n- **TanStack Start**: See [references/tanstack.md](references/tanstack.md)\n- **Next.js**: See [references/nextjs.md](references/nextjs.md)\n\n## General Patterns\n\n### Client-Side Routing (SPA)\n\nFor single-page apps with client-side routing, add a catch-all redirect:\n\n```toml\n# netlify.toml\n[[redirects]]\nfrom = \"/*\"\nto = \"/index.html\"\nstatus = 200\n```\n\n### Custom 404 Pages\n\n- **Static sites**: Create a `404.html` in your publish directory. Netlify serves it automatically for unmatched routes.\n- **SSR frameworks**: Handle 404s in the framework's routing (the adapter maps this to Netlify's function routing).\n\n### Environment Variables in Frameworks\n\nEach framework exposes environment variables to client-side code differently:\n\n| Framework | Client prefix | Access pattern |\n|---|---|---|\n| Vite / React | `VITE_` | `import.meta.env.VITE_VAR` |\n| Astro | `PUBLIC_` | `import.meta.env.PUBLIC_VAR` |\n| Next.js | `NEXT_PUBLIC_` | `process.env.NEXT_PUBLIC_VAR` |\n| Nuxt | `NUXT_PUBLIC_` | `useRuntimeConfig().public.var` |\n\nServer-side code in all frameworks can access variables via `process.env.VAR` or `Netlify.env.get(\"VAR\")`.\n\n## Bundled References (Load As Needed)\n\n- [Vite + React guide](references/vite.md)\n- [Astro guide](references/astro.md)\n- [TanStack Start guide](references/tanstack.md)\n- [Next.js guide](references/nextjs.md)\n","after":"---\nname: netlify-frameworks\ndescription: Deploy and configure web frameworks on Netlify — build settings and SSR/edge adapters plus local platform emulation and env vars. Use when setting up or fixing a framework deploy (Next.js / Astro / Nuxt / SvelteKit / Remix / React Router / TanStack Start / SolidStart / Gatsby / Angular / Vite / Express / Hydrogen / Hugo / Eleventy / Vue / React), adding SSR or edge functions or middleware wired to Netlify context, fixing SPA redirect and catch-all rules, setting a build command or publish directory, or debugging \"why isn't my env var updating\" and framework build failures.\n---\n\nRoute framework-specific deep work to the guides in this skill: `references/astro.md`, `references/nextjs.md`, `references/nuxt.md`, `references/sveltekit.md`, `references/tanstack.md`, `references/vite.md`.\n\n## Env vars: modern rules (read first)\n\nEnv values are injected **at build time**. Any change (client- or server-side) requires a **redeploy** — editing a var in the UI/CLI does NOT reach the live site or already-deployed functions until a new build runs.\n\n**Never use a client prefix for secrets.** Client-prefixed vars are inlined into the browser bundle:\n`VITE_`, `NEXT_PUBLIC_`, `PUBLIC_`, `NUXT_PUBLIC_`, `REACT_APP_`, `GATSBY_`, `VUE_APP_`.\n\nClient-embed prefixes by framework: CRA `REACT_APP_`, Gatsby `GATSBY_`, Next `NEXT_PUBLIC_`, Nuxt `NUXT_ENV_`, Vue CLI `VUE_APP_`.\n\n**Scopes:** build-time access needs **Builds** scope; SSR/DSG runtime access needs **both Functions and Builds**. `netlify.toml` is read only during build — functions cannot read it at runtime; set runtime vars in UI/CLI/API.\n\nNetlify build variables can't be used as values in the UI or `netlify.toml` env sections. Set them inline before the build command:\n```toml\n[build]\n  command = \"REACT_APP_CONTEXT=$CONTEXT npm run build\"\n```\n\n## SPA redirects and the SSR catch-all footgun\n\nSPAs (React, Vue CLI, Vite, Nuxt in SPA mode) need a rewrite to serve `index.html` for `pushState`:\n```\n/* /index.html 200\n```\n\n**Remove any SPA catch-all when adopting an SSR adapter.** A leftover `/* → /index.html 200` silently serves static `index.html` for SSR pages and API routes — user redirects beat adapter-generated routes.\n\n## Local dev with platform emulation (no Netlify CLI)\n\nVite-based frameworks emulate Netlify primitives (functions, edge functions, blobs, Netlify Database, Cache API, Image CDN, redirects/rewrites, headers, env vars, AI Gateway) in the dev server:\n\n| Framework | Plugin/module | Run |\n|-----------|---------------|-----|\n| Astro (5.12+) | built-in (Netlify Vite plugin auto-loaded) | `astro dev` |\n| Nuxt | `@netlify/nuxt` | `nuxt dev` |\n| React Router | `@netlify/vite-plugin` | `react-router dev` |\n| SolidStart 2 | `@netlify/vite-plugin` | `vite dev` |\n| TanStack Start | `@netlify/vite-plugin-tanstack-start` | (vite) |\n| Vite | `@netlify/vite-plugin` | `npx vite` |\n\nStill need `netlify dev` (Netlify CLI) for: Gatsby generated functions (run `netlify build` first), Angular SSR local test (`netlify serve`), and frameworks without a Vite plugin.\n\n**`netlify dev` gotcha:** with both a custom `command` and a `targetPort` in `[dev]`, you must set `framework = \"#custom\"` — otherwise the detector runs and your custom command is silently ignored.\n\n## Build settings by framework\n\n| Framework | Build command | Publish |\n|-----------|---------------|---------|\n| Angular (standard) | `ng build --prod` | `dist/YOUR_PROJECT_NAME` |\n| Astro | `astro build` | `dist` |\n| Create React App | `react-scripts build` | `build` |\n| Eleventy | `eleventy` | `_site` |\n| Gatsby | `gatsby build` | `public` |\n| Hugo | `hugo` | `public` |\n| Hydrogen | `remix vite:build` | `dist/client` |\n| Next.js (SSR/hybrid) | `next build` | `.next` |\n| Next.js (static export) | `next build && next export` | `out` (`NETLIFY_NEXT_PLUGIN_SKIP=true`) |\n| Nuxt 3 | `nuxt build` | `dist` |\n| Nuxt 2 | `nuxt generate` | `dist` |\n| React Router | `react-router build` | `build/client` |\n| Remix (Vite) | `remix vite:build` | `build/client` |\n| SolidStart 2 (Vite plugin) | `vite build` | `dist/client` |\n| SolidStart 2 (Nitro) | `vite build` | `dist` |\n| SolidStart 1.x | `vinxi build` | `dist` |\n| SvelteKit | `vite build` | `build` |\n| TanStack Start (1.132.0+) | `vite build` | `dist/client` |\n| Vite | `vite build` | `dist` |\n| Vue CLI | `vue-cli-service build` | `dist` |\n\nDetection suggests these; override in `netlify.toml` or UI (project configuration > Build & deploy > Continuous deployment > Build settings).\n\n## SSR / adapter setup\n\n### Astro\n`npx astro add netlify` installs the adapter and edits `astro.config.mjs`. Adapter needed for SSR and out-of-the-box Image CDN for `<Image />`. SSR → Netlify Functions; middleware → Edge Functions. Adapter-less deploy only if no server features and no Image CDN need. Skew protection from 5.15.0.\n\n### Next.js (13.5+ only)\nZero-config via the OpenNext adapter (`@netlify/plugin-nextjs`). Do NOT pin the version — Netlify auto-updates each build. Treat the legacy adapter as read-only history, never a recommendation.\nAdapter provisions: serverless function for SSR/ISR/PPR/route handlers/Server Actions; Edge Function for Middleware; Full Route + Data Cache; Image CDN with `next/image`.\nSkew protection is opt-in: set `NETLIFY_NEXT_SKEW_PROTECTION=true`, redeploy. No automatic support for client `fetch` — direct calls with `x-deployment-id: process.env.NEXT_DEPLOYMENT_ID`. Details in `references/nextjs.md`.\n\n### SvelteKit\n```bash\nnpm install -D @sveltejs/adapter-netlify\n```\n```js\nimport adapter from '@sveltejs/adapter-netlify';\nexport default { kit: { adapter: adapter() } };\n```\nReplace `@sveltejs/adapter-auto` with the specific import. SSR routes → a `render` function.\n- `split: true` → one function per route. **Incompatible with Edge Functions** (`edge: false` or omit).\n- `edge: true` → SSR in a Deno edge function; can't combine with `split`.\n- **Redirects NOT supported in `netlify.toml`** — use `_redirects`.\n- Edge functions don't work locally with `netlify dev` for SvelteKit.\n\n### React Router (7+)\nNew: `npx create-react-router@latest --template netlify/react-router-template`. Existing:\n```bash\nnpm install @netlify/vite-plugin-react-router\n```\nAdd `netlifyReactRouter()` to Vite plugins. Default target = Serverless Functions.\n**Edge (Deno):** needs plugin v2.1.1+, set `edge: true`, and you **must** create `app/entry.server.tsx`:\n```typescript\nexport { default } from 'virtual:netlify-server-entry'\n```\nExclude your own function paths: `netlifyReactRouter({ edge: true, excludedPaths: ['/api/*'] })`.\n**Moving back to Serverless:** remove `edge: true` AND delete `app/entry.server.tsx`.\nMiddleware (React Router v7.9.0+, plugin v2.0.0+): opt in via `future.v8_middleware`; import `netlifyRouterContext` from `@netlify/vite-plugin-react-router/serverless` (or `/edge` when `edge: true`); access `context.get(netlifyRouterContext)`.\n\n### Remix\nNew: `npx create-remix@latest --template netlify/remix-template` (CLI prompts functions vs Edge Functions). Manual (Remix Vite required):\n```bash\nnpm install --save-dev @netlify/remix-adapter\n```\nAdd `netlifyPlugin()` from `@netlify/remix-adapter/plugin` to Vite plugins.\n\n### Nuxt\nSSR via Nitro, automatic on Nuxt 3. Local parity via `@netlify/nuxt` (`npx nuxi module add @netlify/nuxt`).\n- SSR on Edge Functions requires a different Nitro deployment preset (not auto-detected).\n- pnpm + Nuxt 3: set `PNPM_FLAGS=--shamefully-hoist`.\n- `nuxt/image` auto-uses Netlify Image CDN; set remote domains in `nuxt.config.ts`.\n\n### SolidStart\nSolidStart 2 builds on Vite — **no SolidStart-specific adapter**. Install `@netlify/vite-plugin`:\n```ts\nimport netlify from \"@netlify/vite-plugin\";\nimport { solidStart } from \"@solidjs/start/config\";\nimport { defineConfig } from \"vite\";\nexport default defineConfig({\n  plugins: [solidStart(), netlify({ build: { enabled: true } })],\n});\n```\nPublish `dist/client`. SSR routes, server functions, middleware → Netlify Functions, zero extra config.\n**Nitro alternative:** add `nitro()`, use plain `netlify()` (no `build.enabled`), publish `dist`.\nSolidStart 1: Nitro auto-configures; optionally set `preset: \"netlify\"` in `app.config.ts`; `vinxi build` / `dist`.\n\n### TanStack Start\nReact (and Solid.js) full-stack; SSR/Server Routes/Server Functions/middleware → serverless functions.\n```bash\nnpm install -D @netlify/vite-plugin-tanstack-start\n```\nAdd `netlify()` to Vite plugins alongside `tanstackStart()`; `vite build` / `dist/client` (1.132.0+). Netlify CLI deploys require netlify-cli 17.31+. Older versions: see `references/tanstack.md`.\n\n### Gatsby\n- **5.12.0+ (adapter):** auto-detects and installs `gatsby-adapter-netlify` (zero-config). Generates functions `SSR`, `DSG`. No Essential Gatsby plugin needed.\n- **5.11.0 or earlier (Essential Gatsby plugin):** auto-installs `@netlify/plugin-gatsby`; also manually install `gatsby-plugin-netlify` (required for SSR, Gatsby redirects, asset caching). Generates `__api`, `__ssr`, `__dsg`, `__ipx`. Skip via `NETLIFY_SKIP_GATSBY_FUNCTIONS` (all) / `NETLIFY_SKIP_API_FUNCTION` / `NETLIFY_SKIP_SSR_FUNCTION` / `NETLIFY_SKIP_DSG_FUNCTION`.\n- Gatsby 5 requires Node 18.\n- Large sites: set `GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE` to load datastore from CDN (avoids max function deploy size; slower first SSR/DSG load).\n- Image CDN: set `NETLIFY_IMAGE_CDN=true` (Contentful/Drupal/WordPress source plugins). **Not supported on 5.12.x with adapter — upgrade to 5.13.0+.**\n- `StaticImage` and `gatsby-transformer-sharp` don't work for SSR/DSG — host images on a CDN.\n\n### Angular\nSSR auto-configured via an Edge Function. Suggested dev: `ng serve` / `4200`.\n- **SSR pages are NOT subject to `_redirects` or `netlify.toml` redirects** — SSR uses Edge Functions that run before redirects. Use Angular's built-in redirects.\n- Access `Request`/`Context` in SSR via `netlify.request` / `netlify.context` providers (from `@netlify/edge-functions`); unavailable client-side or during prerendering. Test locally with `netlify serve`.\n- `NgOptimizedImage` auto-uses Image CDN; set `remote_images` (array of regex) under `[images]` in `netlify.toml`.\n\n### Express\nNode 18.14.0+. Deploy as a Netlify Function via `serverless-http`:\n```bash\nnpm i express serverless-http @netlify/functions @types/express\n```\n```ts\n// netlify/functions/api.ts\nimport express, { Router } from \"express\";\nimport serverless from \"serverless-http\";\nconst api = express();\nconst router = Router();\nrouter.get(\"/hello\", (req, res) => res.send(\"Hello World!\"));\napi.use(\"/api/\", router);\nexport const handler = serverless(api);\n```\n```toml\n[functions]\n  external_node_modules = [\"express\"]\n  node_bundler = \"esbuild\"\n[[redirects]]\n  force = true\n  from = \"/api/*\"\n  status = 200\n  to = \"/.netlify/functions/api/:splat\"\n```\nNo frontend: set a placeholder build command (e.g. `echo Building Functions`). All Function limits apply; not recommended as background/scheduled functions.\n\n### Hydrogen\nShopify stack on React Router 7. **SSR only on Netlify Edge Functions — Netlify Functions NOT officially supported.** Node 24+. Use the starter:\n```bash\nnpm create @shopify/hydrogen@latest -- --template https://github.com/netlify/hydrogen-template\ncp .env.example .env && npm run dev\n```\n\n## Static-site gotchas\n\n### Hugo\nSet `HUGO_VERSION` (any release after 0.19) in `[build.environment]` — a missing/mismatched version causes `exit code: 255`. Install themes as **git submodules** (`git submodule add ...`), not `git clone`.\n\n### Eleventy\n`eleventy` / `_site`. **Build plugins require editing `.gitignore`: change `node_modules` to `**/node_modules/**`** — otherwise Netlify plugins and Eleventy collide on `.netlify/plugins/node_modules/` and the build errors.\n\n## Vite meta-framework support matrix\nAstro (auto on 5.12+), Nuxt (via `@netlify/nuxt`), TanStack Start (via `@netlify/vite-plugin-tanstack-start`), React Router, SolidStart — all **full**. SvelteKit — **experimental**.\n\n## Deploy via CLI (Express, Nuxt, React, Vite)\n```sh\nnpm install netlify-cli -g\nnetlify init\n```\nFollow prompts to create/link the site and set build settings.\n\n<!-- Node version floors (18.14.0+) are stated per-framework where documented; no cross-framework build-image default is given in sources. -->\n\n<!-- system: agent-context/frameworks/system.md — human-owned, merged by ctx-gen; edit system.md, not this section -->\n# Netlify house rules (frameworks)\n\nThese are org conventions, not docs facts — merged into the rendered skill by\nctx-gen and never generated. Owned by the skills maintainer.\n\n1. Per-framework deep guides live in this skill: `references/astro.md`,\n   `references/nextjs.md`, `references/nuxt.md`, `references/sveltekit.md`,\n   `references/tanstack.md`, `references/vite.md` — route framework-specific\n   work there before improvising.\n2. Next.js: modern runtime (v5, Next ≥13.5) only — treat the legacy adapter\n   as read-only history, never a recommendation.\n3. Remove any SPA catch-all (`/* → /index.html 200`) when adopting an SSR\n   adapter — user redirects beat adapter-generated routes, so a leftover\n   catch-all silently serves static `index.html` for SSR pages and API routes.\n4. Any env var change — client- or server-side — requires a redeploy. Values\n   are injected at build time; editing one in the UI/CLI does not reach the\n   live site or already-deployed functions until a new build runs.\n5. `netlify dev` with both a custom `command` and a `targetPort` requires\n   `framework = \"#custom\"` in the `[dev]` block — otherwise the detector runs\n   and the custom command is silently ignored.\n6. Never use a client prefix (`VITE_`, `NEXT_PUBLIC_`, `PUBLIC_`,\n   `NUXT_PUBLIC_`, `REACT_APP_`, `GATSBY_`, `VUE_APP_`) for secrets —\n   client-prefixed vars are inlined into the browser bundle.\n7. Next.js skew protection is version-conditional: below Next 14.1.4 the\n   `NETLIFY_NEXT_SKEW_PROTECTION` env var is not sufficient on its own —\n   `experimental.useDeploymentId` (plus `useDeploymentIdServerActions` when\n   server actions are used) must also go in `next.config.js`. Always ask for\n   or state the version condition; never present the env var as the whole\n   setup.\n8. Client `fetch` calls are not covered by Next.js skew protection by default.\n   Give both options. Next.js 15.4+ has an experimental `useSkewCookie` flag\n   that carries the deployment identifier in a cookie so it rides along on\n   client `fetch` calls; Netlify supports it, but say it is not\n   production-ready and that it holds visitors on the older deploy until the\n   cookie clears. The other option, on any version, is adding\n   `x-deployment-id` with `process.env.NEXT_DEPLOYMENT_ID` per call.\n"}],"summary":"Fields changed: 3. /description, /included_files, /skill_md_contents.","summary_kind":"deterministic","summary_metadata":{}}