| name | netlify |
| description | Deploys applications to Netlify including functions, forms, redirects, and edge functions. Use when deploying static sites, JAMstack applications, or serverless functions. |
Netlify
The modern web development platform for deploying and hosting websites.
Quick Start
Install CLI:
npm install -g netlify-cli
Login:
netlify login
Deploy:
netlify deploy
Deploy to production:
netlify deploy --prod
Project Setup
Connect Git Repository
- Go to app.netlify.com
- Add new site > Import from Git
- Select repository
- Configure build settings
- Deploy
Drag and Drop
Visit https://app.netlify.com/drop and drag your build folder.
netlify.toml Configuration
[build]
command = "npm run build"
publish = "dist"
functions = "netlify/functions"
[build.environment]
NODE_VERSION = "18"
# Production context
[context.production]
command = "npm run build:prod"
# Preview context (branch deploys)
[context.deploy-preview]
command = "npm run build:preview"
# Branch-specific
[context.staging]
command = "npm run build:staging"
# Dev settings
[dev]
command = "npm run dev"
port = 3000
targetPort = 5173
# Headers
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
# Redirects
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Environment Variables
Setting Variables
Via Dashboard: Site settings > Environment variables > Add variable
Via CLI:
netlify env:set MY_VAR "value"
netlify env:list
netlify env:get MY_VAR
netlify env:unset MY_VAR
Context-Specific Variables
# netlify.toml
[context.production.environment]
API_URL = "https://api.example.com"
[context.deploy-preview.environment]
API_URL = "https://staging-api.example.com"
[context.branch-deploy.environment]
API_URL = "https://dev-api.example.com"
Using Variables
// In build process
const apiUrl = process.env.API_URL;
// In functions
export async function handler(event, context) {
const secret = process.env.API_SECRET;
}
Serverless Functions
Basic Function
// netlify/functions/hello.js
export async function handler(event, context) {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello, World!' }),
};
}
TypeScript Function
// netlify/functions/users.ts
import type { Handler, HandlerEvent, HandlerContext } from '@netlify/functions';
interface User {
id: string;
name: string;
}
const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
const { httpMethod, body, queryStringParameters } = event;
if (httpMethod === 'GET') {
const users: User[] = await getUsers();
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(users),
};
}
if (httpMethod === 'POST') {
const data = JSON.parse(body || '{}');
const user = await createUser(data);
return {
statusCode: 201,
body: JSON.stringify(user),
};
}
return {
statusCode: 405,
body: 'Method Not Allowed',
};
};
export { handler };
Scheduled Functions
// netlify/functions/scheduled.ts
import { schedule } from '@netlify/functions';
const handler = async () => {
console.log('Running scheduled task');
await runTask();
return { statusCode: 200 };
};
// Run every day at midnight
export const handler = schedule('0 0 * * *', handler);
Background Functions
// netlify/functions/background-task-background.js
// Suffix with -background for async processing
export async function handler(event, context) {
// Long-running task (up to 15 minutes)
await processLargeDataset();
return {
statusCode: 200,
};
}
Edge Functions
Basic Edge Function
// netlify/edge-functions/geo.ts
import type { Context } from '@netlify/edge-functions';
export default async (request: Request, context: Context) => {
const country = context.geo.country?.code ?? 'Unknown';
const city = context.geo.city ?? 'Unknown';
return new Response(
JSON.stringify({
message: `Hello from ${city}, ${country}!`,
}),
{
headers: { 'Content-Type': 'application/json' },
}
);
};
export const config = { path: '/api/geo' };
Edge Function with Middleware Pattern
// netlify/edge-functions/auth.ts
import type { Context } from '@netlify/edge-functions';
export default async (request: Request, context: Context) => {
const token = request.headers.get('Authorization');
if (!token) {
return new Response('Unauthorized', { status: 401 });
}
// Validate token
const user = await validateToken(token);
if (!user) {
return new Response('Invalid token', { status: 403 });
}
// Continue to origin
return context.next();
};
export const config = { path: '/api/*' };
Edge Function Declaration
# netlify.toml
[[edge_functions]]
path = "/api/geo"
function = "geo"
[[edge_functions]]
path = "/api/*"
function = "auth"
Redirects & Rewrites
_redirects File
# Simple redirect
/old-page /new-page 301
# Wildcard redirect
/blog/* /posts/:splat 301
# Rewrite (proxy)
/api/* /.netlify/functions/:splat 200
# SPA fallback
/* /index.html 200
# Conditional redirect
/country/* /us/:splat 200 Country=us
/country/* /uk/:splat 200 Country=gb
netlify.toml Redirects
[[redirects]]
from = "/old"
to = "/new"
status = 301
[[redirects]]
from = "/api/*"
to = "https://api.example.com/:splat"
status = 200
force = true
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
conditions = { Role = ["admin"] }
Forms
HTML Form
<form name="contact" method="POST" data-netlify="true">
<input type="hidden" name="form-name" value="contact" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
React Form
function ContactForm() {
const [status, setStatus] = useState('');
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const form = e.currentTarget;
const formData = new FormData(form);
try {
await fetch('/', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(formData as any).toString(),
});
setStatus('success');
} catch (error) {
setStatus('error');
}
};
return (
<form
name="contact"
method="POST"
data-netlify="true"
onSubmit={handleSubmit}
>
<input type="hidden" name="form-name" value="contact" />
<input type="text" name="name" required />
<input type="email" name="email" required />
<button type="submit">Send</button>
</form>
);
}
Form Notifications
Configure in Dashboard: Forms > [Form Name] > Settings > Notifications
Identity (Auth)
Setup
<!-- Add to HTML -->
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
JavaScript API
import netlifyIdentity from 'netlify-identity-widget';
netlifyIdentity.init();
// Open modal
netlifyIdentity.open();
// Login
netlifyIdentity.on('login', user => {
console.log('Logged in:', user);
});
// Logout
netlifyIdentity.on('logout', () => {
console.log('Logged out');
});
// Get current user
const user = netlifyIdentity.currentUser();
Large Media (Git LFS)
# Install
netlify lm:install
# Setup
netlify lm:setup
# Track files
git lfs track "*.jpg" "*.png" "*.gif"
Blobs (Storage)
// netlify/functions/upload.ts
import { getStore } from '@netlify/blobs';
export async function handler(event) {
const store = getStore('uploads');
// Store blob
await store.set('file-key', event.body, {
metadata: { contentType: 'image/png' },
});
// Get blob
const blob = await store.get('file-key');
// Delete blob
await store.delete('file-key');
return { statusCode: 200 };
}
Local Development
# Start dev server
netlify dev
# Start with specific port
netlify dev --port 3000
# Link to site
netlify link
# Pull environment variables
netlify env:pull
Best Practices
- Use netlify.toml - Version control your config
- Set up branch deploys - Preview before production
- Use context-specific vars - Different values per environment
- Enable form spam filtering - Protect forms
- Use edge functions - For low-latency operations
Common Mistakes
| Mistake | Fix |
|---|---|
| Missing form-name input | Add hidden input with form name |
| Wrong publish directory | Check framework output folder |
| Functions not found | Use netlify/functions directory |
| Redirects not working | Check order (first match wins) |
| Build failures | Check build logs, Node version |
Reference Files
- references/functions.md - Function patterns
- references/forms.md - Form handling
- references/edge.md - Edge functions