Netlify Deployment Samples
Netlify deployment configuration examples including netlify.toml, edge functions, and form handling
Key Facts
- Category
- Deployment
- Items
- 4
- Format Families
- sample
Sample Overview
Netlify deployment configuration examples including netlify.toml, edge functions, and form handling This sample set belongs to Deployment and can be used to test related workflows inside Elysia Tools.
💻 Netlify Basic Configuration toml
🟢 simple
⭐
Basic Netlify configuration with build settings, redirects, and headers
⏱️ 10 min
🏷️ netlify, configuration, deployment
Prerequisites:
Netlify basics, TOML syntax, Static site concepts
[build]
publish = "build"
command = "npm run build"
functions = "functions"
[build.environment]
NODE_VERSION = "18"
NPM_VERSION = "9"
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-XSS-Protection = "1; mode=block"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "strict-origin-when-cross-origin"
[[headers]]
for = "/static/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[context.production]
command = "npm run build:prod"
[context.deploy-preview]
command = "npm run build:preview"
💻 Netlify Next.js Configuration toml
🟡 intermediate
⭐⭐⭐
Optimized Netlify configuration for Next.js applications with ISR and edge functions
⏱️ 20 min
🏷️ netlify, next.js, framework
Prerequisites:
Next.js, Netlify plugin system, Edge functions
[build]
publish = ".next"
command = "npm run build"
environment = { NODE_VERSION = "18" }
[[plugins]]
package = "@netlify/plugin-nextjs"
[[redirects]]
from = "/_next/static/*"
to = "/_next/static/:splat"
status = 200
force = true
[[redirects]]
from = "/api/*"
to = "/.netlify/functions/:splat"
status = 200
[[redirects]]
from = "/_next/data/*/blog/*.json"
to = "/.netlify/functions/__ isr-blog?slug=:splat&:splat"
status = 200
[[redirects]]
from = "/blog/*"
to = "/.netlify/functions/__ isr-blog?slug=:splat"
status = 200
[[headers]]
for = "/api/*"
[headers.values]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, OPTIONS"
Access-Control-Allow-Headers = "Content-Type, Authorization"
[[headers]]
for = "/_next/static/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[headers]]
for = "/_next/image/*"
[headers.values]
Cache-Control = "public, max-age=86400, must-revalidate"
[context.production.environment]
NEXT_PUBLIC_API_URL = "https://api.example.com"
NEXT_PUBLIC_SITE_URL = "https://example.com"
[context.branch-deploy.environment]
NEXT_PUBLIC_API_URL = "https://dev-api.example.com"
NEXT_PUBLIC_SITE_URL = "https://dev--example.netlify.app"
[context.deploy-preview.environment]
NEXT_PUBLIC_API_URL = "https://preview-api.example.com"
NEXT_PUBLIC_SITE_URL = "https://deploy-preview-1--example.netlify.app"
[functions]
node_version = "18"
[[functions]]
directory = "functions"
node_bundler = "esbuild"
[[edge_functions]]
function = "geo-redirect"
path = "/geo-check"
💻 Netlify Edge Functions javascript
🟡 intermediate
⭐⭐⭐⭐
Edge functions examples for geolocation, A/B testing, and custom middleware
⏱️ 30 min
🏷️ netlify, edge functions, middleware
Prerequisites:
JavaScript, Edge computing concepts, Netlify edge functions
// Netlify Edge Functions Examples
// 1. Geolocation-based redirect
// edge-functions/geo-redirect.js
export const geoRedirectEdgeFunction = async (request, context) => {
const url = new URL(request.url);
const country = request.geo?.country?.code?.toLowerCase();
// Redirect based on country
if (country === 'us') {
const usUrl = new URL('/us', url);
return Response.redirect(usUrl, 302);
} else if (country === 'uk') {
const ukUrl = new URL('/uk', url);
return Response.redirect(ukUrl, 302);
} else if (country === 'de') {
const deUrl = new URL('/de', url);
return Response.redirect(deUrl, 302);
}
// Add country data to headers
const response = await context.next();
response.headers.set('x-user-country', country || 'unknown');
return response;
};
// 2. A/B testing edge function
// edge-functions/ab-test.js
export const abTestEdgeFunction = async (request, context) => {
const url = new URL(request.url);
// Skip A/B test for API routes
if (url.pathname.startsWith('/api/')) {
return context.next();
}
// Check for existing A/B test variant
const variant = request.headers.get('x-ab-variant') ||
Math.random() < 0.5 ? 'A' : 'B';
// Redirect to variant-specific path
if (variant === 'B' && !url.pathname.includes('/variant-b')) {
const variantUrl = new URL('/variant-b' + url.pathname, url);
const response = Response.redirect(variantUrl, 302);
response.headers.set('x-ab-variant', variant);
return response;
}
const response = await context.next();
response.headers.set('x-ab-variant', variant);
return response;
};
// 3. Authentication middleware
// edge-functions/auth.js
export const authEdgeFunction = async (request, context) => {
const url = new URL(request.url);
// Skip auth for public routes
const publicPaths = ['/login', '/signup', '/forgot-password', '/api/auth'];
if (publicPaths.some(path => url.pathname.startsWith(path))) {
return context.next();
}
// Check for authentication token
const authCookie = request.headers.get('cookie')?.split(';')
?.find(cookie => cookie.trim().startsWith('auth_token='))
?.split('=')[1];
if (!authCookie) {
// Redirect to login
const loginUrl = new URL('/login', url);
loginUrl.searchParams.set('redirect', url.pathname);
return Response.redirect(loginUrl, 302);
}
// Validate token (mock validation)
try {
const isValid = await validateToken(authCookie);
if (!isValid) {
throw new Error('Invalid token');
}
// Add user info to headers for downstream functions
const response = await context.next();
response.headers.set('x-user-authenticated', 'true');
return response;
} catch (error) {
const loginUrl = new URL('/login', url);
loginUrl.searchParams.set('error', 'invalid_token');
loginUrl.searchParams.set('redirect', url.pathname);
return Response.redirect(loginUrl, 302);
}
};
async function validateToken(token) {
// Mock validation - replace with real token validation
return token.length > 10;
}
// 4. Rate limiting edge function
// edge-functions/rate-limit.js
export const rateLimitEdgeFunction = async (request, context) => {
const url = new URL(request.url);
const clientIP = request.headers.get('x-nf-client-connection-ip') ||
request.headers.get('x-forwarded-for') ||
'unknown';
// Simple rate limiting logic (in production, use Redis or similar)
const RATE_LIMIT = 100; // requests per minute
const key = `rate-limit-${clientIP}`;
// This is a mock implementation
// In production, you'd use a proper rate limiting store
const now = Date.now();
const windowStart = now - 60000; // 1 minute ago
// Check rate limit (mock logic)
const requestCount = await getRequestCount(key, windowStart);
if (requestCount >= RATE_LIMIT) {
return new Response('Rate limit exceeded', {
status: 429,
headers: {
'Retry-After': '60',
'Content-Type': 'text/plain'
}
});
}
// Increment request count
await incrementRequestCount(key);
const response = await context.next();
response.headers.set('x-rate-limit-remaining', String(RATE_LIMIT - requestCount));
return response;
};
// Mock functions for rate limiting (replace with real implementation)
async function getRequestCount(key, windowStart) {
// Mock implementation
return Math.floor(Math.random() * 150);
}
async function incrementRequestCount(key) {
// Mock implementation
return Promise.resolve();
}
// 5. Content personalization edge function
// edge-functions/personalize.js
export const personalizeEdgeFunction = async (request, context) => {
const url = new URL(request.url);
// Skip personalization for API routes
if (url.pathname.startsWith('/api/')) {
return context.next();
}
// Get user preferences from cookie or headers
const preferences = getUserPreferences(request);
const response = await context.next();
// Inject personalization script
const personalizationScript = `
<script>
window.userPreferences = ${JSON.stringify(preferences)};
// Trigger personalization
window.dispatchEvent(new CustomEvent('userPreferencesLoaded', {
detail: window.userPreferences
}));
</script>
`;
// Insert script before closing body tag
const html = await response.text();
const personalizedHtml = html.replace(
'</body>',
personalizationScript + '</body>'
);
return new Response(personalizedHtml, {
headers: response.headers
});
};
function getUserPreferences(request) {
const cookieHeader = request.headers.get('cookie') || '';
// Parse preferences from cookies
const preferences = {
theme: 'light',
language: 'en',
region: 'us'
};
cookieHeader.split(';').forEach(cookie => {
const [name, value] = cookie.trim().split('=');
if (name === 'theme') preferences.theme = value || 'light';
if (name === 'language') preferences.language = value || 'en';
if (name === 'region') preferences.region = value || 'us';
});
// Override with geo data if available
if (request.geo?.country?.code) {
preferences.region = request.geo.country.code.toLowerCase();
}
return preferences;
}
// 6. Content security policy edge function
// edge-functions/csp.js
export const geoRedirectWithATesting = async (request, context) => {
const response = await context.next();
// Set Content Security Policy headers
const csp = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://vercel.live",
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
"font-src 'self' https://fonts.gstatic.com",
"img-src 'self' data: https: blob:",
"connect-src 'self' https://api.example.com",
"frame-ancestors 'none'",
"base-uri 'self'",
"form-action 'self'"
].join('; ');
response.headers.set('Content-Security-Policy', csp);
response.headers.set('X-Content-Type-Options', 'nosniff');
response.headers.set('X-Frame-Options', 'DENY');
response.headers.set('X-XSS-Protection', '1; mode=block');
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
return response;
};
💻 Netlify Forms and Analytics html
🔴 complex
⭐⭐⭐⭐
Complete forms handling, analytics tracking, and automation workflows
⏱️ 40 min
🏷️ netlify, forms, analytics, frontend
Prerequisites:
HTML, JavaScript, Netlify forms, Analytics
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Netlify Forms & Analytics Example</title>
<style>
.form-container {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
border: 1px solid #ddd;
border-radius: 8px;
}
.form-group {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
input, textarea, select {
width: 100%;
padding: 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
background: #007cba;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #005a87;
}
.form-netlify {
display: none;
}
.analytics-data {
background: #f5f5f5;
padding: 1rem;
border-radius: 4px;
margin: 2rem 0;
}
</style>
</head>
<body>
<!-- 1. Contact Form with Netlify Forms -->
<div class="form-container">
<h2>Contact Form</h2>
<form name="contact" method="POST" data-netlify="true" netlify-honeypot="bot-field">
<!-- Hidden field for spam protection -->
<input type="hidden" name="form-name" value="contact">
<div class="form-netlify">
<label>Don't fill this out if you're human: <input name="bot-field" /></label>
</div>
<div class="form-group">
<label for="name">Name *</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email *</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="subject">Subject</label>
<input type="text" id="subject" name="subject">
</div>
<div class="form-group">
<label for="message">Message *</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<div class="form-group">
<label for="interest">Area of Interest</label>
<select id="interest" name="interest">
<option value="">Select an option</option>
<option value="web-development">Web Development</option>
<option value="mobile-apps">Mobile Apps</option>
<option value="consulting">Consulting</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="newsletter" value="yes">
Subscribe to newsletter
</label>
</div>
<button type="submit">Send Message</button>
</form>
</div>
<!-- 2. File Upload Form -->
<div class="form-container">
<h2>File Upload Form</h2>
<form name="upload" method="POST" data-netlify="true" enctype="multipart/form-data">
<input type="hidden" name="form-name" value="upload">
<div class="form-group">
<label for="file-name">Name</label>
<input type="text" id="file-name" name="name" required>
</div>
<div class="form-group">
<label for="file-email">Email</label>
<input type="email" id="file-email" name="email" required>
</div>
<div class="form-group">
<label for="file">Upload File (max 2MB)</label>
<input type="file" id="file" name="file" accept=".pdf,.doc,.docx,.txt" required>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea id="description" name="description" rows="3"></textarea>
</div>
<button type="submit">Upload File</button>
</form>
</div>
<!-- 3. Multi-step Form with Progressive Enhancement -->
<div class="form-container">
<h2>Multi-step Registration Form</h2>
<form name="registration" method="POST" data-netlify="true">
<input type="hidden" name="form-name" value="registration">
<!-- Step 1: Basic Information -->
<div id="step-1" class="form-step">
<h3>Step 1: Basic Information</h3>
<div class="form-group">
<label for="reg-name">Full Name *</label>
<input type="text" id="reg-name" name="full_name" required>
</div>
<div class="form-group">
<label for="reg-email">Email Address *</label>
<input type="email" id="reg-email" name="email_address" required>
</div>
<div class="form-group">
<label for="reg-phone">Phone Number</label>
<input type="tel" id="reg-phone" name="phone_number">
</div>
<button type="button" onclick="nextStep(2)">Next</button>
</div>
<!-- Step 2: Professional Information -->
<div id="step-2" class="form-step" style="display: none;">
<h3>Step 2: Professional Information</h3>
<div class="form-group">
<label for="company">Company</label>
<input type="text" id="company" name="company">
</div>
<div class="form-group">
<label for="position">Position</label>
<input type="text" id="position" name="position">
</div>
<div class="form-group">
<label for="experience">Years of Experience</label>
<select id="experience" name="experience">
<option value="0-1">0-1 years</option>
<option value="2-5">2-5 years</option>
<option value="6-10">6-10 years</option>
<option value="10+">10+ years</option>
</select>
</div>
<button type="button" onclick="nextStep(1)">Previous</button>
<button type="button" onclick="nextStep(3)">Next</button>
</div>
<!-- Step 3: Preferences -->
<div id="step-3" class="form-step" style="display: none;">
<h3>Step 3: Preferences</h3>
<div class="form-group">
<label for="interests">Areas of Interest</label>
<div>
<label>
<input type="checkbox" name="interests" value="design"> Design
</label>
<label>
<input type="checkbox" name="interests" value="development"> Development
</label>
<label>
<input type="checkbox" name="interests" value="marketing"> Marketing
</label>
</div>
</div>
<div class="form-group">
<label for="hear-about">How did you hear about us?</label>
<select id="hear-about" name="hear_about">
<option value="">Select an option</option>
<option value="search">Search Engine</option>
<option value="social">Social Media</option>
<option value="referral">Referral</option>
<option value="advertisement">Advertisement</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="comments">Additional Comments</label>
<textarea id="comments" name="comments" rows="4"></textarea>
</div>
<button type="button" onclick="nextStep(2)">Previous</button>
<button type="submit">Submit Registration</button>
</div>
</form>
</div>
<!-- 4. Analytics Data Display -->
<div class="analytics-data">
<h3>Real-time Analytics Data</h3>
<div id="visitor-info">
<p><strong>Location:</strong> <span id="location">Loading...</span></p>
<p><strong>Device:</strong> <span id="device">Loading...</span></p>
<p><strong>Browser:</strong> <span id="browser">Loading...</span></p>
<p><strong>Session ID:</strong> <span id="session-id">Loading...</span></p>
</div>
</div>
<!-- Netlify Analytics Script -->
<script>
// Initialize Netlify Analytics
if (typeof netlifyAnalytics !== 'undefined') {
netlifyAnalytics.on('routeChange', ({ path }) => {
console.log('Route changed to:', path);
});
}
</script>
<!-- 5. Form Handling Script -->
<script>
// Multi-step form logic
function nextStep(stepNumber) {
// Hide all steps
document.querySelectorAll('.form-step').forEach(step => {
step.style.display = 'none';
});
// Show selected step
document.getElementById(`step-${stepNumber}`).style.display = 'block';
}
// Form submission handling
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', function(e) {
// Show loading state
const submitBtn = this.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.textContent = 'Submitting...';
submitBtn.disabled = true;
// Track form submission
if (typeof netlifyAnalytics !== 'undefined') {
netlifyAnalytics.track({
eventName: 'form_submission',
data: {
formName: this.getAttribute('name'),
timestamp: new Date().toISOString()
}
});
}
// Let the form submit normally to Netlify
setTimeout(() => {
submitBtn.textContent = originalText;
submitBtn.disabled = false;
}, 3000);
});
});
// Load visitor information
async function loadVisitorInfo() {
try {
// Simulate visitor data (in real app, this would come from Netlify Functions)
const visitorData = {
location: await getLocation(),
device: getDeviceInfo(),
browser: getBrowserInfo(),
sessionId: getSessionId()
};
document.getElementById('location').textContent = visitorData.location;
document.getElementById('device').textContent = visitorData.device;
document.getElementById('browser').textContent = visitorData.browser;
document.getElementById('session-id').textContent = visitorData.sessionId;
} catch (error) {
console.error('Error loading visitor info:', error);
}
}
async function getLocation() {
// In production, you'd use Netlify Functions to get geo data
// For now, return a mock location
return 'San Francisco, CA, USA';
}
function getDeviceInfo() {
const userAgent = navigator.userAgent;
if (/Mobile|Android|iPhone|iPad/.test(userAgent)) {
return 'Mobile';
} else if (/Tablet/.test(userAgent)) {
return 'Tablet';
} else {
return 'Desktop';
}
}
function getBrowserInfo() {
const userAgent = navigator.userAgent;
if (userAgent.includes('Chrome')) return 'Chrome';
if (userAgent.includes('Firefox')) return 'Firefox';
if (userAgent.includes('Safari')) return 'Safari';
if (userAgent.includes('Edge')) return 'Edge';
return 'Unknown';
}
function getSessionId() {
// Get or create session ID from local storage
let sessionId = localStorage.getItem('netlify_session_id');
if (!sessionId) {
sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
localStorage.setItem('netlify_session_id', sessionId);
}
return sessionId;
}
// Load visitor info when page loads
document.addEventListener('DOMContentLoaded', loadVisitorInfo);
// Track page view
if (typeof netlifyAnalytics !== 'undefined') {
netlifyAnalytics.track({
eventName: 'page_view',
data: {
path: window.location.pathname,
title: document.title,
timestamp: new Date().toISOString()
}
});
}
// Track form interactions
document.querySelectorAll('input, textarea, select').forEach(field => {
field.addEventListener('focus', function() {
if (typeof netlifyAnalytics !== 'undefined') {
netlifyAnalytics.track({
eventName: 'form_field_focus',
data: {
fieldName: this.name,
fieldType: this.type,
timestamp: new Date().toISOString()
}
});
}
});
});
</script>
</body>
</html>