How to set up Netlify Functions on Netlify
Create a netlify/functions directory with JavaScript handler files, configure netlify.toml with your functions path, and deploy via Git or CLI. Functions automatically deploy with your site and are accessible at /.netlify/functions/<function-name>. Test locally using netlify dev before deploying to production.
Prerequisites
- Netlify account created at app.netlify.com
- Node.js (version 16+) and npm installed
- Netlify CLI installed globally via npm
- Git repository (GitHub, GitLab, or Bitbucket)
- Basic familiarity with JavaScript and command line
Step-by-Step Instructions
Install Netlify CLI and Initialize Your Project
npm install -g netlify-cli. Create a new project directory and navigate into it with mkdir my-netlify-functions && cd my-netlify-functions. Initialize npm in your project root with npm init -y to create a package.json file with default values. This sets up the foundation for your serverless functions project.Create the Functions Directory Structure
mkdir netlify/functions. Netlify automatically detects this directory during builds without requiring additional configuration. If you prefer a custom directory name (e.g., functions instead of netlify/functions), you'll need to configure it in netlify.toml later. The directory structure should look like: my-netlify-functions/
├── netlify/
│ └── functions/
├── package.json
└── netlify.tomlWrite Your First Serverless Function
hello.mjs (use .mjs for ES modules, which is the required syntax). Add the following handler code: export default async (request, context) => {
return new Response(`Hello, ${context?.identity?.context?.user?.email ?? 'world'}!`, {
headers: { 'Content-Type': 'text/plain' }
});
}; The handler function receives two arguments: request (a web platform Request object containing HTTP details) and context (Netlify metadata including user identity). Your function must export a default handler and return a Response object.Configure netlify.toml for Custom Settings (Optional)
netlify.toml file in your project root to customize your build and function settings. Add the following configuration: [build]
functions = "netlify/functions"
command = "npm run build"
publish = "dist"
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200 The [build] section specifies your functions directory (change to functions if using a custom path), build command, and publish directory. The [[redirects]] section (optional) routes API requests to your functions. If using the default netlify/functions directory, this file is optional but recommended for clarity.Set Up Local Development Environment
netlify dev (or ntl dev for short) in your project root to start the local development server. This command automatically detects your netlify.toml and package.json configuration. The server will start on http://localhost:8888 by default. Your functions will be accessible at http://localhost:8888/.netlify/functions/hello. Open this URL in your browser to test your function—it should return "Hello, world!" or your email if you're logged in.Add Environment Variables for Local Development
.env file in your project root to store sensitive configuration values like API keys. Add your variables in the format KEY=value, for example: SPOTIFY_CLIENT_ID=your_client_id
SPOTIFY_CLIENT_SECRET=your_secret These variables are automatically loaded into process.env when you run netlify dev. Access them in your functions using process.env.SPOTIFY_CLIENT_ID. Add .env to your .gitignore file to prevent committing secrets to version control.Connect Your Git Repository to Netlify
Deploy Functions and Test in Production
https://your-site-name.netlify.app/.netlify/functions/hello. Test your production function by visiting this URL in your browser or using curl: curl https://your-site-name.netlify.app/.netlify/functions/hello Check the deploy logs in the dashboard if your function doesn't work as expected.Create Additional Functions and API Routes
netlify/functions/users.mjs to handle user data at /.netlify/functions/users. You can handle different HTTP methods (GET, POST, PUT, DELETE) within a single function by checking request.method: export default async (request, context) => {
if (request.method === 'GET') {
return new Response('Get users');
} else if (request.method === 'POST') {
return new Response('Create user');
}
}; Use the optional netlify.toml redirects to create cleaner API routes (e.g., /api/users instead of /.netlify/functions/users).Access Data Files and External APIs
db.json in netlify/functions/data/db.json and import it in your function: import db from './data/db.json' assert { type: 'json' };
export default async (request, context) => {
return new Response(JSON.stringify(db), {
headers: { 'Content-Type': 'application/json' }
});
}; Functions cannot access files outside their folder (e.g., ../src/data.json will fail during deployment). For external APIs, use fetch within your function to call third-party services like Spotify or Firebase.Common Issues & Troubleshooting
CORS errors when fetching functions from your frontend
Ensure you're testing with netlify dev on port 8888, not your app's dev server (e.g., port 3000). CORS issues occur when the frontend and functions run on different ports. In production, both are served from the same domain, so CORS is not an issue. Use netlify dev to test the production-like environment locally.
Function returns 404 or 'not found' error
Verify the function file exists in netlify/functions/ with the correct name and extension (.mjs, .cjs, or .js). Check that the filename matches your URL endpoint (e.g., hello.mjs creates /.netlify/functions/hello). Ensure netlify.toml correctly specifies the functions directory. Run netlify dev and check the terminal output for any build errors. If using a custom directory, confirm it's set in netlify.toml under [build] functions = "your-directory".
Environment variables are undefined in production but work locally
Environment variables set in .env only work locally with netlify dev. For production, set variables in the Netlify dashboard under Site Settings > Build & Deploy > Environment variables. Add each variable as a key-value pair. Redeploy your site after adding variables so they're available during the build. Verify variable names match exactly (they're case-sensitive).
Deploy fails with 'Could not resolve' or bundling errors
Check the deploy logs in the Netlify dashboard for specific error messages. Common causes include: importing files outside the functions directory (move them inside), using top-level await in CommonJS files (use .mjs or add type: module to package.json), or missing dependencies (add them to package.json). Ensure your build command in netlify.toml is correct and matches your project setup.
Function works locally but not after deployment
Compare your local environment (netlify dev) with production by checking: (1) Node.js version—set NODE_VERSION in netlify.toml if needed, (2) environment variables—confirm they're set in the dashboard, (3) file paths—ensure relative paths work in the deployed functions directory, (4) dependencies—verify all imports are in package.json. Check the deploy logs for build errors and redeploy after fixes.