netlify-deployment-platform

Netlify Platform Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "netlify-deployment-platform" with this command: npx skills add bobmatnyc/claude-mpm-skills/bobmatnyc-claude-mpm-skills-netlify-deployment-platform

Netlify Platform Skill

progressive_disclosure: entry_point: summary: "JAMstack deployment platform with serverless functions, forms, and identity" when_to_use:

  • "When deploying static sites and SPAs"
  • "When building JAMstack applications"
  • "When needing serverless functions"
  • "When requiring built-in forms and auth" quick_start:
  • "npm install -g netlify-cli"
  • "netlify login"
  • "netlify init"
  • "netlify deploy --prod" token_estimate: entry: 70-85 full: 3800-4800

Netlify Fundamentals

Core Concepts

  • Sites: Static sites deployed to Netlify's global CDN

  • Builds: Automated build process triggered by Git commits

  • Deploy Contexts: production, deploy-preview, branch-deploy

  • Atomic Deploys: All-or-nothing deployments with instant rollback

  • Instant Cache Invalidation: CDN cache cleared automatically

Platform Benefits

  • Global CDN: Built-in content delivery network

  • Continuous Deployment: Auto-deploy from Git

  • HTTPS by Default: Free SSL certificates

  • Deploy Previews: Preview every pull request

  • Serverless Functions: Backend logic without servers

  • Forms & Identity: Built-in features for common needs

Static Site Deployment

Supported Frameworks

React (Create React App, Vite)

Build command: npm run build Publish directory: build (CRA) or dist (Vite)

Next.js (Static Export)

Build command: npm run build && npm run export Publish directory: out

Vue.js

Build command: npm run build Publish directory: dist

Gatsby

Build command: gatsby build Publish directory: public

Hugo

Build command: hugo Publish directory: public

Svelte/SvelteKit

Build command: npm run build Publish directory: build

Manual Deployment

Install Netlify CLI

npm install -g netlify-cli

Login to Netlify

netlify login

Initialize site

netlify init

Deploy draft (preview URL)

netlify deploy

Deploy to production

netlify deploy --prod

Deploy with build

netlify deploy --build --prod

netlify.toml Configuration

Basic Configuration

netlify.toml

[build]

Build command

command = "npm run build"

Publish directory

publish = "dist"

Functions directory

functions = "netlify/functions"

Production context

[context.production] command = "npm run build:prod"

[context.production.environment] NODE_ENV = "production" API_URL = "https://api.example.com"

Deploy Preview context

[context.deploy-preview] command = "npm run build:preview"

Branch deploys

[context.branch-deploy] command = "npm run build"

Build Settings

[build] command = "npm run build" publish = "dist"

Base directory for monorepos

base = "packages/web"

Ignore builds on certain changes

ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"

[build.environment] NODE_VERSION = "18" NPM_VERSION = "9" RUBY_VERSION = "3.1"

Advanced Build Configuration

[build] command = "npm run build" publish = "dist"

Build processing

[build.processing] skip_processing = false [build.processing.css] bundle = true minify = true [build.processing.js] bundle = true minify = true [build.processing.images] compress = true

Environment Variables

Setting Variables

Via CLI

netlify env:set API_KEY "secret-value" netlify env:set NODE_ENV "production"

List variables

netlify env:list

Import from .env file

netlify env:import .env

Variable Scopes

netlify.toml

[context.production.environment] API_URL = "https://api.production.com" ENABLE_ANALYTICS = "true"

[context.deploy-preview.environment] API_URL = "https://api.staging.com" ENABLE_ANALYTICS = "false"

[context.branch-deploy.environment] API_URL = "https://api.dev.com"

Accessing in Build

// During build const apiUrl = process.env.API_URL;

// Client-side (must be prefixed) const publicKey = process.env.REACT_APP_PUBLIC_KEY;

Serverless Functions

Function Structure

// netlify/functions/hello.js exports.handler = async (event, context) => { return { statusCode: 200, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message: 'Hello from Netlify Function', path: event.path, method: event.httpMethod, }), }; };

TypeScript Functions

// netlify/functions/api.ts import { Handler, HandlerEvent, HandlerContext } from '@netlify/functions';

interface RequestBody { name: string; email: string; }

export const handler: Handler = async ( event: HandlerEvent, context: HandlerContext ) => { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed', }; }

const { name, email }: RequestBody = JSON.parse(event.body || '{}');

return { statusCode: 200, body: JSON.stringify({ message: Hello ${name}, email, }), }; };

Advanced Function Patterns

// netlify/functions/database.js const { MongoClient } = require('mongodb');

let cachedDb = null;

async function connectToDatabase() { if (cachedDb) return cachedDb;

const client = await MongoClient.connect(process.env.MONGODB_URI); cachedDb = client.db(); return cachedDb; }

exports.handler = async (event) => { const db = await connectToDatabase(); const users = await db.collection('users').find({}).toArray();

return { statusCode: 200, body: JSON.stringify(users), }; };

Scheduled Functions

// netlify/functions/scheduled.js const { schedule } = require('@netlify/functions');

const handler = async () => { console.log('Running scheduled task');

// Your scheduled logic await performBackup();

return { statusCode: 200, }; };

// Run every day at midnight exports.handler = schedule('0 0 * * *', handler);

Background Functions

// netlify/functions/background-task.js // Auto-runs in background if response is 200 within 10s exports.handler = async (event) => { // Long-running task await processLargeDataset();

return { statusCode: 200, }; };

// Invoke: POST to /.netlify/functions/background-task

Netlify Forms

HTML Form

<!-- Contact form --> <form name="contact" method="POST" data-netlify="true"> <input type="hidden" name="form-name" value="contact" />

<label>Name: <input type="text" name="name" required /></label> <label>Email: <input type="email" name="email" required /></label> <label>Message: <textarea name="message" required></textarea></label>

<button type="submit">Send</button> </form>

React Form

// ContactForm.jsx import { useState } from 'react';

export default function ContactForm() { const [formData, setFormData] = useState({ name: '', email: '', message: '', });

const handleSubmit = async (e) => { e.preventDefault();

const response = await fetch('/', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    'form-name': 'contact',
    ...formData,
  }).toString(),
});

if (response.ok) {
  alert('Thank you for your message!');
}

};

return ( <form name="contact" onSubmit={handleSubmit} data-netlify="true"> <input type="hidden" name="form-name" value="contact" /> {/* Form fields */} </form> ); }

Form Features

<!-- Spam filtering with honeypot --> <form name="contact" method="POST" data-netlify="true" data-netlify-honeypot="bot-field"> <input type="hidden" name="form-name" value="contact" /> <p class="hidden"> <label>Don't fill this out: <input name="bot-field" /></label> </p> <!-- Form fields --> </form>

<!-- reCAPTCHA v2 --> <form name="contact" method="POST" data-netlify="true" data-netlify-recaptcha="true"> <div data-netlify-recaptcha="true"></div> <button type="submit">Submit</button> </form>

<!-- File uploads --> <form name="file-upload" method="POST" data-netlify="true" enctype="multipart/form-data"> <input type="file" name="file" /> <button type="submit">Upload</button> </form>

Form Notifications

netlify.toml

[[plugins]] package = "@netlify/plugin-emails"

[plugins.inputs] formName = "contact" to = "admin@example.com" subject = "New contact form submission"

Netlify Identity

Enable Identity

// Add to HTML <script src="https://identity.netlify.com/v1/netlify-identity-widget.js">&#x3C;/script>

// Initialize if (window.netlifyIdentity) { window.netlifyIdentity.on('init', user => { if (!user) { window.netlifyIdentity.on('login', () => { document.location.href = '/admin/'; }); } }); }

React Integration

// useNetlifyIdentity.js import { useEffect, useState } from 'react';

export function useNetlifyIdentity() { const [user, setUser] = useState(null);

useEffect(() => { const netlifyIdentity = window.netlifyIdentity;

netlifyIdentity.on('init', user => setUser(user));
netlifyIdentity.on('login', user => setUser(user));
netlifyIdentity.on('logout', () => setUser(null));

netlifyIdentity.init();

}, []);

return { user, login: () => window.netlifyIdentity.open('login'), logout: () => window.netlifyIdentity.logout(), signup: () => window.netlifyIdentity.open('signup'), }; }

Protected Functions

// netlify/functions/protected.js exports.handler = async (event, context) => { const { user } = context.clientContext;

if (!user) { return { statusCode: 401, body: 'Unauthorized', }; }

return { statusCode: 200, body: JSON.stringify({ message: 'Protected data', user: user.email, }), }; };

Redirects and Rewrites

_redirects File

_redirects file in publish directory

Redirect with status code

/old-path /new-path 301

Rewrite (proxy)

/api/* https://api.example.com/:splat 200

SPA fallback

/* /index.html 200

Force HTTPS

http://example.com/* https://example.com/:splat 301!

Conditional redirects

/news/* /blog/:splat 302 Country=us

Role-based redirects

/admin/* /admin/dashboard 200! Role=admin /admin/* /unauthorized 401

netlify.toml Redirects

[[redirects]] from = "/old-path" to = "/new-path" status = 301

[[redirects]] from = "/api/*" to = "https://api.example.com/:splat" status = 200 force = true

[[redirects]] from = "/*" to = "/index.html" status = 200

[[redirects]] from = "/admin/*" to = "/admin/dashboard" status = 200 conditions = {Role = ["admin"]}

Proxy with headers

[[redirects]] from = "/proxy/*" to = "https://backend.com/:splat" status = 200 force = true [redirects.headers] X-From = "Netlify"

Custom Headers

[[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" X-XSS-Protection = "1; mode=block" Content-Security-Policy = "default-src 'self'"

[[headers]] for = "/assets/*" [headers.values] Cache-Control = "public, max-age=31536000, immutable"

Deploy Previews

Automatic Preview URLs

netlify.toml

[context.deploy-preview] command = "npm run build:preview"

[context.deploy-preview.environment] NODE_ENV = "preview" API_URL = "https://api-staging.example.com"

Branch Deploys

Deploy specific branches

[context.staging] command = "npm run build:staging"

[context.staging.environment] API_URL = "https://api-staging.example.com"

Branch pattern matching

[context.branch-deploy] command = "npm run build"

Deploy Notifications

GitHub PR comments

Slack notifications

Email notifications

Configured in Netlify UI

Split Testing (A/B Testing)

Configuration

netlify.toml

[[redirects]] from = "/*" to = "/version-a/:splat" status = 200 conditions = {Cookie = ["ab_test=a"]} force = true

[[redirects]] from = "/*" to = "/version-b/:splat" status = 200 conditions = {Cookie = ["ab_test=b"]} force = true

50/50 split

[[redirects]] from = "/*" to = "/version-a/:splat" status = 200! percentage = 50

[[redirects]] from = "/*" to = "/version-b/:splat" status = 200!

Edge Functions

Deno Runtime

// netlify/edge-functions/hello.ts import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => { const url = new URL(request.url);

return new Response(Hello from ${url.pathname}, { headers: { "content-type": "text/html" }, }); };

export const config = { path: "/hello" };

Geolocation

// netlify/edge-functions/geo.ts import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => { const { city, country } = context.geo;

return Response.json({ location: ${city}, ${country}, }); };

Transform Response

// netlify/edge-functions/transform.ts import type { Context } from "https://edge.netlify.com";

export default async (request: Request, context: Context) => { const response = await context.next(); const text = await response.text();

// Modify HTML const modified = text.replace( '</body>', '<script>console.log("Injected by edge");</script></body>' );

return new Response(modified, response); };

export const config = { path: "/*" };

Custom Domains and SSL

Add Custom Domain

Via CLI

netlify domains:add example.com

DNS Configuration

A record: 75.2.60.5

CNAME: <site-name>.netlify.app

Verify domain

netlify domains:verify example.com

SSL Certificates

Automatic HTTPS (default)

Free Let's Encrypt certificates

Auto-renewal

Force HTTPS redirect

[[redirects]] from = "http://example.com/*" to = "https://example.com/:splat" status = 301 force = true

Analytics

Netlify Analytics

<!-- Automatically injected, no code needed --> <!-- Server-side analytics, no client-side JS -->

Custom Analytics

// Track custom events function trackEvent(eventName, data) { fetch('/.netlify/functions/analytics', { method: 'POST', body: JSON.stringify({ event: eventName, ...data }), }); }

trackEvent('button_click', { button: 'signup' });

CLI Advanced Usage

Development Server

Run functions locally

netlify dev

Specific port

netlify dev --port 3000

Live session sharing

netlify dev --live

Functions only

netlify functions:serve

Site Management

Link existing site

netlify link

Create new site

netlify sites:create

List sites

netlify sites:list

Site info

netlify status

Open site in browser

netlify open

Deploy Management

List deploys

netlify deploy:list

Rollback to previous deploy

netlify rollback

Cancel deploy

netlify deploy:cancel <deploy-id>

Git Integration

Continuous Deployment

netlify.toml

[build] command = "npm run build" publish = "dist"

Auto-publish on Git push

Production: main/master branch

Previews: all pull requests

Branch deploys: configured branches

Deploy Hooks

Trigger builds via webhook

curl -X POST -d {} https://api.netlify.com/build_hooks/&#x3C;hook-id>

Scheduled builds (use external cron + webhook)

Best Practices

Performance Optimization

Enable processing

[build.processing] skip_processing = false

[build.processing.css] bundle = true minify = true

[build.processing.js] bundle = true minify = true

[build.processing.images] compress = true

Asset optimization

[[headers]] for = "/assets/*" [headers.values] Cache-Control = "public, max-age=31536000, immutable"

Security Headers

[[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" X-Content-Type-Options = "nosniff" X-XSS-Protection = "1; mode=block" Referrer-Policy = "strict-origin-when-cross-origin" Permissions-Policy = "geolocation=(), microphone=(), camera=()" Content-Security-Policy = """ default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; """

Function Best Practices

// Keep functions lightweight // Use connection pooling // Cache external API responses // Set appropriate timeouts // Handle errors gracefully

exports.handler = async (event) => { try { // Set timeout const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 8000);

const response = await fetch(API_URL, {
  signal: controller.signal,
});

clearTimeout(timeout);

return {
  statusCode: 200,
  body: JSON.stringify(await response.json()),
};

} catch (error) { console.error('Function error:', error);

return {
  statusCode: 500,
  body: JSON.stringify({ error: 'Internal server error' }),
};

} };

Build Optimization

[build] command = "npm run build" publish = "dist"

Skip builds when not needed

ignore = """ git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF -- . ':(exclude)docs/' ':(exclude)*.md' """

Cache dependencies

[build.environment] NPM_FLAGS = "--legacy-peer-deps" NODE_OPTIONS = "--max-old-space-size=4096"

Monorepo Support

netlify.toml

[build] base = "packages/web" command = "npm run build" publish = "dist"

Only build when package changes

ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/web"

Common Patterns

SPA with API Proxy

[build] command = "npm run build" publish = "build" functions = "netlify/functions"

[[redirects]] from = "/api/*" to = "/.netlify/functions/:splat" status = 200

[[redirects]] from = "/*" to = "/index.html" status = 200

Microsite with Subfolder

[[redirects]] from = "/blog/*" to = "https://blog.example.com/:splat" status = 200 force = true

Authentication Gateway

[[redirects]] from = "/app/*" to = "/app/dashboard" status = 200 conditions = {Role = ["user"]}

[[redirects]] from = "/app/*" to = "/login" status = 302

Summary: Netlify provides a complete JAMstack platform with static hosting, serverless functions, forms, and identity management. Key strengths include atomic deploys, instant cache invalidation, deploy previews, and built-in CDN. Configure via netlify.toml for builds, redirects, headers, and environment-specific settings. Leverage serverless functions for backend logic, forms for user input, and Edge Functions for edge computing. Best practices include performance optimization, security headers, and efficient build configurations.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

drizzle-orm

No summary provided by upstream source.

Repository SourceNeeds Review
General

pydantic

No summary provided by upstream source.

Repository SourceNeeds Review
General

playwright-e2e-testing

No summary provided by upstream source.

Repository SourceNeeds Review
General

tailwind-css

No summary provided by upstream source.

Repository SourceNeeds Review