
Description
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, running a framework project locally with Netlify's platform features, or troubleshooting framework-specific Netlify integration. Covers what Netlify needs from each framework, how adapters handle server-side rendering, and the general local development options (`netlify dev` versus the Netlify Vite plugin family).
SKILL.md
Frameworks on Netlify
Netlify 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.
How It Works
During 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.
Detecting Your Framework
Check these files to determine the framework:
| File | Framework |
|---|---|
astro.config.* | Astro |
next.config.* | Next.js |
nuxt.config.* | Nuxt |
vite.config.* + react-router | Vite + React (SPA or Remix) |
vite.config.* + @tanstack/react-start | TanStack Start |
svelte.config.* | SvelteKit |
Framework Reference Guides
Each framework has specific adapter/plugin requirements and local dev patterns:
- Vite + React (SPA or with server routes): See references/vite.md
- Astro: See references/astro.md
- TanStack Start: See references/tanstack.md
- Next.js: See references/nextjs.md
- Nuxt: See references/nuxt.md
- SvelteKit: See references/sveltekit.md
Local Development
Running a framework project locally with Netlify's platform features (environment variables, Functions, Edge Functions) generally comes from one of two places:
netlify dev
netlify dev
Wraps the framework's own dev server and adds:
- Environment variable injection
- Functions and Edge Functions
- Redirects and headers processing
Works with any framework — run netlify dev in place of the framework's native dev command (e.g. instead of npm run dev).
Custom dev-server wiring — a non-standard command, a port/targetPort, or the framework key — goes in netlify.toml's [dev] block; see the netlify-config skill for the full syntax. One easy-to-miss rule: if you set both a custom command and a targetPort, framework must be "#custom", otherwise Netlify Dev runs its own detector and silently ignores your command.
Netlify Vite plugin family (Vite-based frameworks)
For frameworks built on Vite, a Netlify Vite plugin exposes platform primitives (Functions, Blobs, DB, environment variables) directly inside the framework's own dev server, so no netlify dev wrapper is needed — run the framework's normal dev command (e.g. npm run dev) once the plugin is registered in vite.config.ts.
- Vite-based projects (React SPA, SvelteKit, Remix):
@netlify/vite-plugin— see references/vite.md - TanStack Start:
@netlify/vite-plugin-tanstack-start— see references/tanstack.md
The per-framework reference guides may also document other local dev options (e.g. netlify dev) — check the guide for your framework for setup specifics.
Running a single command with the Netlify environment loaded
netlify dev:exec <cmd>
Loads the Netlify environment (env vars, etc.) for a single command without starting a dev server — useful for scripts, tests, or one-off tasks that need Netlify-managed environment variables.
General Patterns
Client-Side Routing (SPA)
For single-page apps with client-side routing, add a catch-all redirect:
# netlify.toml
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Remove this catch-all when you adopt an SSR adapter. A
/* → /index.htmlrule left over from an SPA setup will shadow your server routes: user-defined redirects innetlify.toml/_redirectstake precedence over the routes a framework adapter generates, so every request — including SSR pages and API/function routes — is served the staticindex.htmlwith a 200. When you migrate a client-rendered app to SSR, delete the SPA catch-all.
Custom 404 Pages
- Static sites: Create a
404.htmlin your publish directory. Netlify serves it automatically for unmatched routes. - SSR frameworks: Handle 404s in the framework's routing (the adapter maps this to Netlify's function routing).
Environment Variables in Frameworks
Each framework exposes environment variables to client-side code differently:
| Framework | Client prefix | Access pattern |
|---|---|---|
| Vite / React | VITE_ | import.meta.env.VITE_VAR |
| Astro | PUBLIC_ | import.meta.env.PUBLIC_VAR |
| Next.js | NEXT_PUBLIC_ | process.env.NEXT_PUBLIC_VAR |
| Nuxt | NUXT_PUBLIC_ | useRuntimeConfig().public.var |
In server-side code, prefer Netlify.env.get("VAR") to read environment variables. process.env.VAR also works inside Netlify Functions, but Edge Functions expose only Netlify.env.get — the portable form keeps server code working in both.
Never use a client prefix (VITE_, PUBLIC_, NEXT_PUBLIC_, NUXT_PUBLIC_) for secrets. Client-prefixed variables are inlined into the client bundle and exposed to the browser.
Environment Variable Changes Require a Redeploy
Client-prefixed vars (VITE_, NEXT_PUBLIC_, PUBLIC_, NUXT_PUBLIC_) are inlined into the client bundle at build time — their values are compiled into the JavaScript shipped to the browser. Editing one in the Netlify UI or CLI has no effect on the live site until a new build runs. The same applies server-side: Netlify injects environment variables at build time, so changing a value in the dashboard does not propagate to already-deployed functions on the next request. Any env var change — client- or server-side — requires a redeploy to take effect. If a value looks stale after you changed it, trigger a new deploy.
Runtime File Reads in Adapter-Generated Functions
When an adapter turns your server code into a Netlify Function, only traced module dependencies are bundled. Arbitrary files you read from disk at runtime — a local JSON/Markdown data file, an email template, an fs.readFile() target — are not uploaded with the function unless you declare them. Such a read succeeds under npm run dev (the whole project is on disk) but throws ENOENT in production. Declare the files so they ship with the function: in Next.js set outputFileTracingIncludes in next.config; for a hand-written Netlify Function use included_files in its config. Never assume the project filesystem is present at function runtime.
More skills from the context-and-tools repository
View all 15 skillsnetlify-access-control
manage Netlify site access control
Jul 14Access ControlNetlifyPermissionsSecuritynetlify-agent-runner
run AI agent tasks on Netlify
Jul 17AgentsAutomationLLMNetlifynetlify-ai-gateway
route AI requests via Netlify AI Gateway
Jul 17AI InfrastructureAPI DevelopmentLLMNetlifynetlify-blobs
manage file storage with Netlify Blobs
Jul 17BackendFile StorageNetlifyStoragenetlify-caching
configure CDN caching on Netlify
Jul 14CachingDeploymentNetlifyPerformancenetlify-config
configure Netlify site settings
Jul 17ConfigurationDeploymentNetlify
More from Netlify
View publisherconfigure-axis
configure AXIS agent evaluation scenarios
axis
Jul 20AgentsConfigurationEvalsNetlifyusing-axis
run and interpret AXIS reports
axis
Jul 14CLIEvalsNetlifynetlify-database
provision and manage Netlify Database
context-and-tools
Jul 20BackendDatabaseNetlifyPostgreSQLnetlify-deploy
deploy and host projects on Netlify
context-and-tools
Jul 17CLIDeploymentNetlifyWeb Developmentnetlify-edge-functions
write Netlify Edge Functions
context-and-tools
Jul 14Edge FunctionsMiddlewareNetlifyPerformancenetlify-forms
handle HTML forms with Netlify
context-and-tools
Jul 14FormsHTMLNetlifyWeb Development