CINXE.COM

Frameworks API | Netlify Docs

<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Frameworks API | Netlify Docs</title> <meta name="generator" content="VuePress 1.9.9"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,500,700,400italic|Roboto+Mono:400"> <link rel="icon" href="/netlify-icon.svg" type="image/svg+xml"> <link rel="apple-touch-icon" href="/apple-touch-icon.png"> <link rel="icon" href="/favicon-32x32.png" type="image/png" sizes="32x32"> <link rel="icon" href="/favicon-16x16.png" type="image/png" sizes="16x16"> <script>(function (w) { if (!w) return; const darkQuery = w.matchMedia('(prefers-color-scheme: dark)'); const root = document.documentElement; function setTheme(newTheme) { if (newTheme === 'dark' || (newTheme === 'system' && darkQuery.matches)) { root.classList.add('dark-mode'); } else { root.classList.remove('dark-mode'); } w.__theme = newTheme; } w.__setPreferredTheme = function (newTheme) { setTheme(newTheme); try { localStorage.setItem('nf-docs-theme', w.__theme); } catch (err) {} }; // If using system theme, change colors in real time // in response to user settings darkQuery.addEventListener('change', function (event) { if (w.__theme === 'system') { if (event.matches) { root.classList.add('dark-mode'); } else { root.classList.remove('dark-mode'); } } }); let preferredTheme; // Try to get saved theme try { preferredTheme = localStorage.getItem('nf-docs-theme') || 'system'; } catch (err) {} // Initialize preferredTheme setTheme(preferredTheme); })(window);</script> <script src="/rum.js" data-application-id="ededf59a-7705-4933-b2a0-5efa8b35b293" data-client-token="pub1b84fc7c7429f37e025e8160c02da8bb" data-service="docs" data-env="production" defer="true"></script> <meta name="description" content="Web development frameworks and build tools can use the Frameworks API to generate site deployments that take advantage of Netlify’s composable platform."> <meta property="og:title" content="Frameworks API"> <meta property="og:url" content="https://docs.netlify.com/frameworks-api/"> <meta property="og:description" content="Web development frameworks and build tools can use the Frameworks API to generate site deployments that take advantage of Netlify’s composable platform."> <meta property="og:image" content="https://docs.netlify.com/og-image.png"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta prefix="og: http://ogp.me/ns#" property="og:type" content="article"> <meta prefix="og: http://ogp.me/ns#" property="og:article:author" content="Netlify"> <meta name="google-site-verification" content="G4JqDTXMHpDyWoqIRwgw8PBqg-AncXqtdkHehcOR7kc"> <meta name="slack-app-id" content="A05P27DR8C8"> <link href="https://docs.netlify.com/frameworks-api/" rel="canonical" /> <link rel="preload" href="/assets/css/0.styles.d221ae53.css" as="style"><link rel="preload" href="/assets/js/app.1a68918d.js" as="script"><link rel="preload" href="/assets/js/10.a8fb7bb3.js" as="script"><link rel="preload" href="/assets/js/2.f24e0879.js" as="script"><link rel="preload" href="/assets/js/107.4de9a99f.js" as="script"><link rel="preload" href="/assets/js/3.be674a14.js" as="script"> <link rel="stylesheet" href="/assets/css/0.styles.d221ae53.css"> </head> <body> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NMKKF2M" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar-header"><div class="navbar"><div class="navbar__logo-link"><a href="/" class="router-link-active"><span class="visuallyhidden">Netlify Docs</span> <svg width="146" height="40" viewBox="0 0 146 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="netlify-lockup" data-v-4ee6c329><path d="M22.794 39.79V29.687l.21-.21h2.526l.21.21V39.79l-.21.209h-2.527l-.209-.21ZM22.794 10.314V.21l.21-.209h2.526l.21.21v10.104l-.21.21h-2.527l-.209-.21ZM14.1 32.687h-.347l-1.738-1.738v-.347l3.256-3.26 1.84.004.245.242v1.84L14.1 32.686ZM12.015 9.49v-.35l1.738-1.735h.347l3.256 3.256v1.836l-.246.248h-1.839L12.015 9.49ZM.582 18.524h14.316l.21.21v2.53l-.21.209H.582l-.21-.21v-2.53l.21-.209Z" fill="var(--lockup-lines-fill)" data-v-4ee6c329></path> <path d="M29.005 25.265h-2.526l-.21-.21v-5.912c0-1.054-.412-1.869-1.682-1.895-.654-.016-1.4 0-2.199.033l-.12.12v7.651l-.21.21h-2.526l-.21-.21V14.948l.21-.21h5.684a3.998 3.998 0 0 1 3.998 3.999v6.315l-.21.21v.003ZM41.24 20.841l-.21.21H34.5l-.21.209c0 .422.423 1.685 2.108 1.685.631 0 1.263-.21 1.476-.631l.21-.21h2.525l.21.21c-.21 1.263-1.263 3.16-4.424 3.16-3.58 0-5.265-2.526-5.265-5.477 0-2.952 1.685-5.478 5.055-5.478 3.37 0 5.056 2.526 5.056 5.478v.844Zm-3.161-2.107c0-.21-.21-1.686-1.895-1.686s-1.895 1.476-1.895 1.686l.21.21h3.37l.21-.21ZM47.136 22.104c0 .422.21.632.632.632h1.895l.209.209v2.107l-.21.21h-1.894c-1.895 0-3.58-.845-3.58-3.161v-4.634l-.21-.21h-1.475l-.21-.209v-2.107l.21-.21h1.476l.21-.209v-1.894l.209-.21h2.526l.21.21v1.894l.209.21h2.316l.21.21v2.106l-.21.21h-2.316l-.21.21V22.1l.003.003ZM54.93 25.265h-2.525l-.21-.21V10.73l.21-.21h2.526l.21.21v14.322l-.21.21v.003ZM60.618 13.046h-2.526l-.21-.209V10.73l.21-.21h2.526l.21.21v2.107l-.21.21Zm0 12.22h-2.526l-.21-.21V14.944l.21-.21h2.526l.21.21v10.112l-.21.21ZM70.52 10.73v2.107l-.21.21h-1.894c-.422 0-.632.209-.632.631v.844l.21.21H70.1l.21.21v2.106l-.21.21h-2.107l-.21.21v7.581l-.21.21H65.05l-.21-.21v-7.582l-.21-.21h-1.475l-.21-.209v-2.107l.21-.21h1.476l.21-.209v-.844c0-2.317 1.684-3.161 3.58-3.161h1.894l.21.21-.004.003ZM78.311 25.474c-.844 2.108-1.685 3.37-4.633 3.37h-1.054l-.21-.209v-2.107l.21-.21h1.054c1.053 0 1.263-.209 1.475-.84v-.21l-3.37-8.216v-2.108l.21-.21h1.894l.21.21 2.526 7.163h.21l2.525-7.163.21-.21h1.894l.21.21v2.108l-3.37 8.426.01-.004Z" fill="var(--lockup-wordmark-fill)" data-v-4ee6c329></path> <path d="M94.699 25.205V10.707l-.213-.214H92.78l-.213.214v5.117h-.213c-.661-.853-1.706-1.28-2.772-1.28-2.985 0-4.69 2.346-4.69 5.544 0 3.198 1.705 5.543 4.69 5.543 1.13 0 2.132-.469 2.772-1.28h.213l.213.854.213.213h1.493l.213-.213Zm-2.132-5.117c0 2.558-1.066 3.624-2.772 3.624-1.705 0-2.771-1.258-2.771-3.624 0-2.367 1.066-3.625 2.771-3.625 1.706 0 2.772 1.066 2.772 3.625ZM96.614 20.088c0 3.411 1.918 5.543 5.117 5.543 3.198 0 5.117-2.132 5.117-5.543 0-3.412-1.919-5.544-5.117-5.544s-5.117 2.133-5.117 5.544Zm2.132 0c0-2.346 1.066-3.625 2.985-3.625 1.918 0 2.985 1.28 2.985 3.625 0 2.345-1.067 3.624-2.985 3.624-1.92 0-2.985-1.279-2.985-3.624ZM110.26 20.088c0-2.346 1.066-3.625 2.985-3.625 1.705 0 2.345.853 2.558 1.706l.213.213h1.706l.213-.213c-.213-1.919-1.706-3.625-4.69-3.625-3.199 0-5.117 2.133-5.117 5.544 0 3.411 1.918 5.543 5.117 5.543 2.984 0 4.477-1.706 4.69-3.624l-.213-.213h-1.706l-.213.213c-.213.852-.853 1.705-2.558 1.705-1.919 0-2.985-1.279-2.985-3.624ZM127.733 22.433c0-1.919-1.066-2.772-3.199-3.198-2.132-.426-2.984-.64-2.984-1.706 0-.852.852-1.066 1.918-1.066 1.493 0 1.919.64 1.919 1.28l.214.213h1.705l.213-.213c0-2.132-1.705-3.198-4.051-3.198-2.984 0-4.05 1.492-4.05 2.984 0 1.92 1.279 2.772 3.411 3.198 2.132.427 2.772.64 2.772 1.706 0 .853-.64 1.28-2.133 1.28-1.492 0-2.132-.64-2.132-1.706l-.213-.213h-1.705l-.214.213c0 2.345 1.493 3.624 4.264 3.624 2.985 0 4.265-1.492 4.265-3.198Z" fill="var(--lockup-secondary-text-fill)" data-v-4ee6c329></path> <path d="M131.138 18.524h14.316l.209.21v2.53l-.209.209h-14.316l-.21-.21v-2.53l.21-.209Z" fill="var(--lockup-lines-fill)" data-v-4ee6c329></path></svg></a></div> <div class="navbar__actions-wrapper"><form id="search-form" role="search" class="algolia-search-wrapper search-form"><label class="search-form__label"><svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 32 32" class="search-form__label-icon-search"><path d="M20.571 15.143c0-4.411-3.589-8-8-8s-8 3.589-8 8 3.589 8 8 8 8-3.589 8-8zM29.714 30c0 1.25-1.036 2.286-2.286 2.286-0.607 0-1.196-0.25-1.607-0.679l-6.125-6.107c-2.089 1.446-4.589 2.214-7.125 2.214-6.946 0-12.571-5.625-12.571-12.571s5.625-12.571 12.571-12.571 12.571 5.625 12.571 12.571c0 2.536-0.768 5.036-2.214 7.125l6.125 6.125c0.411 0.411 0.661 1 0.661 1.607z" fill="rgba(175, 180, 182, 0.87)"></path></svg> <input id="algolia-search-input" placeholder="Search our docs by topic..." class="search-form__input"></label> <button tabindex="-1" type="reset" class="search-form__label-icon-close"><span class="visuallyhidden">Close search</span> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 18 18"><g fill="#A3A9AC" transform="scale(-1 1) rotate(45 .571 -12.959)"><rect width="2.333" height="18.667" x="8.164" y=".003"></rect> <polygon points="8.164 .003 10.497 .003 10.497 18.67 8.164 18.67" transform="rotate(-90 9.33 9.336)"></polygon></g></svg></button> <div class="search-form__content-overlay"></div></form> <div class="navbar__right-actions"><a href="/ask-netlify/" aria-label="ask netlify" class="navbar__ask-netlify-link"><span class="navbar__ask-netlify-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 44 44" class="wrapper__icon-ask-netlify"><path fill="currentColor" d="M18.77 23.56a1.8 1.8 0 1 1-3.6 0 1.8 1.8 0 0 1 3.6 0Zm8.26 1.8a1.8 1.8 0 1 0 0-3.6 1.8 1.8 0 0 0 0 3.6Zm-3.86-1.54.03.07v.38l-.03.07-.87 1.77-.12.09h-.32l-.13-.1-.9-1.76-.03-.07v-.38l.03-.07 1-.66h.31l1.03.66Z"></path> <path fill="currentColor" fill-rule="evenodd" d="M22.32 13C28.77 13 34 17.22 34 23.67a6.97 6.97 0 0 1-6.97 6.97H10v-6.97C10 17.22 15.23 13 21.68 13h.64ZM11.55 23.16a5.24 5.24 0 0 1 10.07-2.05h.76l.01-.03a5.24 5.24 0 0 1 10.06 2.08c0 2.65-2.13 5.17-4.53 5.23H16.5a5.24 5.24 0 0 1-4.95-5.23Z" clip-rule="evenodd"></path> <path fill="currentColor" d="m24.47 8.12.07-.16 1.16-.4.15.08.63 1.95-.4.82-.16.06-.82-.4-.63-1.95Zm9.88 3.27.16.06.48 1.13-.07.16-1.9.76-.85-.34-.07-.16.35-.85 1.9-.76ZM30.04 8l.16-.06 1.1.54.05.16-1.14 2.43-.87.3-.15-.08-.3-.86L30.04 8Z" class="ask-netlify-flair"></path></svg></span> <span class="navbar__ask-netlify-label">Ask Netlify</span></a> <div class="user-menu"><!----> <button href="#menu" aria-label="menu" class="menu-trigger is-not-visible-mamabear"><svg viewBox="0 0 31 25" xmlns="http://www.w3.org/2000/svg" class="wrapper__icon-menu"><rect x="0.581177" y="0.71875" width="30" height="4" fill="currentcolor"></rect> <rect x="0.581177" y="10.7188" width="30" height="4" fill="currentcolor"></rect> <rect x="0.581177" y="20.7188" width="30" height="4" fill="currentcolor"></rect></svg></button> <nav aria-label="Netlify navigation" class="navbar__nav is-visible-mamabear navbar__authlinks" data-v-1733a580><div class="navbar__nav-list" data-v-1733a580><a href="https://app.netlify.com/login" rel="noopener noreferrer" class="navbar__nav-link" data-v-1733a580> Log in </a> <a href="https://app.netlify.com/signup" target="self" rel="noopener noreferrer" class="navbar__nav-link signup-button" data-v-1733a580> Sign up </a></div></nav></div></div></div></div></header> <main class="wrapper wrapper--main"><div class="wrapper__sidebar wrapper__navigation"><a class="button button--icon button--close is-not-visible-mamabear"><svg aria-hidden="true" width="24" height="24" viewBox="0 0 16 16" class="icon"><path d="M8,15 C4.13400675,15 1,11.8659932 1,8 C1,4.13400675 4.13400675,1 8,1 C11.8659932,1 15,4.13400675 15,8 C15,11.8659932 11.8659932,15 8,15 Z M10.44352,10.7233105 L10.4528296,10.7326201 L10.7326201,10.4528296 C11.0310632,10.1543865 11.0314986,9.66985171 10.7335912,9.37194437 L9.36507937,8.0034325 L10.7360526,6.63245928 C11.0344957,6.33401613 11.0349311,5.84948135 10.7370237,5.55157401 L10.448426,5.26297627 C10.1505186,4.96506892 9.66598387,4.96550426 9.36754072,5.26394741 L8.00589385,6.62559428 L6.63738198,5.25708241 C6.33947464,4.95917507 5.85493986,4.95961041 5.55649671,5.25805356 L5.26737991,5.54717036 C4.96893676,5.84561351 4.96850142,6.33014829 5.26640876,6.62805563 L6.62561103,7.9872579 L5.25463781,9.35823112 C4.95619466,9.65667427 4.95575932,10.141209 5.25366666,10.4391164 L5.5422644,10.7277141 C5.84017175,11.0256215 6.32470652,11.0251861 6.62314967,10.726743 L7.99412289,9.35576976 L9.36263476,10.7242816 C9.66054211,11.022189 10.1450769,11.0217536 10.44352,10.7233105 Z"></path></svg></a> <div aria-label="Docs" class="sidebar wrapper__sidebar-interior"><nav aria-label="Docs"><div><div class="sidebar__section"><span class="sidebar__section-label">Welcome</span> <ul class="sidebar__links"><li class="sidebar__link-item"><div><a href="/" aria-current="page" class="sidebar__link">Home</a></div></li><li class="sidebar__link-item"><div><a href="/get-started/" class="sidebar__link">Get started</a></div></li><li class="sidebar__link-item"><div><a href="/welcome/add-new-site/" class="sidebar__link">Add new site</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Get help </button> <!----> <!----></section></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Platform</span> <ul class="sidebar__links"><li class="sidebar__link-item"><div><a href="/platform/what-is-netlify/" class="sidebar__link">What is Netlify?</a></div></li><li class="sidebar__link-item"><div><a href="/platform/who-is-netlify-for/" class="sidebar__link">Who is Netlify for?</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Checklists </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> How we release </button> <!----> <!----></section></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Platform primitives</span> <ul class="sidebar__links"><li class="sidebar__link-item"><div><a href="/platform/primitives/" class="sidebar__link">Overview</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Functions </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Edge Functions </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Image CDN </button> <!----> <!----></section></li><li class="sidebar__link-item"><div><a href="/blobs/overview/" class="sidebar__link">Blobs</a></div></li><li class="sidebar__link-item"><div><a href="/platform/caching/" class="sidebar__link">Caching</a></div></li><li class="sidebar__link-item"><div><a href="/platform/dev-server/" class="sidebar__link">Dev Server</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Platform extensions </button> <!----> <!----></section></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Frameworks</span> <ul class="sidebar__links"><li class="sidebar__link-item"><div><a href="/frameworks/" class="sidebar__link">Overview</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Framework support </button> <!----> <!----></section></li><li class="sidebar__link-item"><div><a href="/frameworks/environment-variables/" class="sidebar__link">Use environment variables with frameworks</a></div></li><li class="sidebar__link-item"><div><a href="/frameworks-api/" aria-current="page" class="active sidebar__link">Frameworks API</a></div></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Developer tools</span> <ul class="sidebar__links"><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> CLI </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> API </button> <!----> <!----></section></li><li class="sidebar__link-item"><div><a href="/terraform-provider/" class="sidebar__link">Terraform Provider</a></div></li><li class="sidebar__link-item"><div><a href="https://developers.netlify.app/sdk/get-started/introduction/" target="_blank" rel="noopener noreferrer" class="sidebar__link">Netlify SDK</a></div></li><li class="sidebar__link-item"><div><a href="/welcome/command-palette/" class="sidebar__link">Command Palette</a></div></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Integrate &amp; extend</span> <ul class="sidebar__links"><li class="sidebar__link-item"><div><a href="/integrations/overview/" class="sidebar__link">Overview</a></div></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Integrations </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Build Plugins </button> <!----> <!----></section></li><li class="sidebar__link-item"><div><a href="/slack-app/" class="sidebar__link">Netlify App for Slack</a></div></li><li class="sidebar__link-item"><div><a href="/integrations/extend-netlify/" class="sidebar__link">Extend Netlify</a></div></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Configure &amp; deploy site</span> <ul class="sidebar__links"><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Git </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Environment variables </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Configure builds </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Site deploys </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Domains &amp; HTTPS </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Static routing </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Forms </button> <!----> <!----></section></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Visual editing</span> <ul class="sidebar__links"><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Visual Editor </button> <!----> <!----></section></li><li class="sidebar__link-item"><div><a href="/ai-assisted-publishing/" class="sidebar__link">AI-Assisted Publishing</a></div></li><li class="sidebar__link-item"><div><a href="https://visual-editor-reference.netlify.com/" target="_blank" rel="noopener noreferrer" class="sidebar__link">Visual editor reference</a></div></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Manage data</span> <ul class="sidebar__links"><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Connect </button> <!----> <!----></section></li></ul></div><div class="sidebar__section"><span class="sidebar__section-label">Site &amp; team management</span> <ul class="sidebar__links"><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Accounts &amp; billing </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Security </button> <!----> <!----></section></li><li class="sidebar__link-item"><section tabIndex="-1" class="sidebar__group collapsable is-sub-group"><button tabIndex="-1" class="sidebar__group-heading"> Monitor sites </button> <!----> <!----></section></li></ul></div></div></nav> <div aria-labelledby="#external-link__header" class="external-links" data-v-bad94b42><p id="external-link__header" class="external-links__header" data-v-bad94b42> Contact </p> <ul class="external-links__list" data-v-bad94b42><li class="external-links__item" data-v-bad94b42><a href="https://answers.netlify.com" target="_blank" rel="noopener noreferrer" class="external-links__link" data-v-bad94b42> Forums </a></li> <li class="external-links__item" data-v-bad94b42><a href="https://www.netlify.com/support/" target="_blank" rel="noopener noreferrer" class="external-links__link" data-v-bad94b42> Contact support </a></li></ul></div> <nav aria-label="Netlify navigation" class="navbar__nav is-visible-mamabear navbar__authlinks is-not-visible-mamabear" data-v-1733a580><div class="navbar__nav-list" data-v-1733a580><a href="https://app.netlify.com/login" rel="noopener noreferrer" class="navbar__nav-link" data-v-1733a580> Log in </a> <a href="https://app.netlify.com/signup" target="self" rel="noopener noreferrer" class="navbar__nav-link signup-button" data-v-1733a580> Sign up </a></div></nav></div></div> <div class="wrapper__sidebar wrapper__toc"><nav aria-label="On this page" data-toc="" class="contents wrapper__sidebar-interior"> <details><summary class="contents__header">On this page</summary> <ol><li><a href="/frameworks-api/#features" data-slug="features">Features</a> <ul><li><a href="/frameworks-api/#netlify-v1-config-json" data-slug="netlify-v1-config-json">.netlify/v1/config.json</a> <ul></ul></li><li><a href="/frameworks-api/#netlify-v1-blobs" data-slug="netlify-v1-blobs">.netlify/v1/blobs</a> <!----></li><li><a href="/frameworks-api/#netlify-v1-edge-functions" data-slug="netlify-v1-edge-functions">.netlify/v1/edge-functions</a> <ul></ul></li><li><a href="/frameworks-api/#netlify-v1-functions" data-slug="netlify-v1-functions">.netlify/v1/functions</a> <ul></ul></li></ul></li><li><a href="/frameworks-api/#merging-configurations" data-slug="merging-configurations">Merging configurations</a> <!----></li><li><a href="/frameworks-api/#versioning" data-slug="versioning">Versioning</a> <!----></li></ol></details></nav></div> <section class="wrapper__content"><header class="content__default"><div class="wrapper__breadcrumbs"><span class="breadcrumb__item"><span>Frameworks</span> <span class="breadcrumb__break">/</span></span></div> <h1>Frameworks API</h1></header> <div class="content__default"><p>Web development frameworks can use the Frameworks API to define how to deploy a site to Netlify. Use the API to provision and configure platform primitives so that developers don’t have to, allowing for a seamless integration with the framework and a zero-config setup.</p> <p>The API is file-based: as part of the build command, the framework should write files to specific directories, with a well-defined format. Netlify then reads and further processes these files to create a deployment.</p> <p>This page is for authors and collaborators of web frameworks who are building framework adapters for Netlify. It contains the full reference of the Frameworks API.</p> <h2 id="features"><a href="#features" class="header-anchor">#</a> Features</h2> <h3 id="netlify-v1-config-json"><a href="#netlify-v1-config-json" class="header-anchor">#</a> <code>.netlify/v1/config.json</code></h3> <p>Use the <code>config.json</code> file to configure how Netlify builds and deploys a site. It’s a subset of the <a href="/configure-builds/file-based-configuration/">user-facing file-based configuration</a> (using JSON instead of TOML) and it supports the following properties.</p> <ul><li><a href="#edge-functions"><code>edge_functions</code></a></li> <li><a href="#functions"><code>functions</code></a></li> <li><a href="#headers"><code>headers</code></a></li> <li><a href="#images"><code>images</code></a></li> <li><a href="#redirects"><code>redirects</code></a></li></ul> <h4 id="edge-functions"><a href="#edge-functions" class="header-anchor">#</a> <code>edge_functions</code></h4> <p>Accepts edge function declarations with the <a href="/edge-functions/declarations/#declare-edge-functions-in-netlify-toml">same properties as the user-facing configuration</a>. While edge functions can be <a href="#configuration-options">configured in the same file as the function code</a>, this property is useful if you would like to declare multiple edge functions to run on the same path and customize the order they run in.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;edge_functions&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;auth&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/admin&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;cache&quot;</span><span class="token operator">:</span> <span class="token string">&quot;manual&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;injector&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/admin&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;auth&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/blog/*&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;rewriter&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/blog/*&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;excludedPattern&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/products/things/(.*)&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;highlight&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;pattern&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/products/(.*)&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;excludedPath&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/img/*&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;common&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/*&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre></div><p>Entries of the <code>edge_functions</code> array in the <code>config.json</code> file only take a single path per edge function. This means that if you want to configure the edge function to run on <code>/path1</code> and <code>/path2</code>, you need to create two separate entries. This has the advantage of letting you configure the exact order of precedence of each edge function for a given path.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;edge_functions&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;my-framework-edge-function-1&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/path1&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;my-framework-edge-function-2&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/path1&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;my-framework-edge-function-2&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/path2&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;function&quot;</span><span class="token operator">:</span> <span class="token string">&quot;my-framework-edge-function-1&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/path2&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre></div><h4 id="functions"><a href="#functions" class="header-anchor">#</a> <code>functions</code></h4> <p>Accepts function configuration options, including any property from <a href="#configuration-options-2">the inline configuration options</a>. When you define the properties, we prefer snake case — for example, use <code>included_files</code> instead of <code>includedFiles</code>.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;functions&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;directory&quot;</span><span class="token operator">:</span> <span class="token string">&quot;myfunctions/&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;included_files&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;files/*.md&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre></div><p>Optionally, you can apply these settings to only a subset of a site’s functions. For example, if a framework prefixes the functions it generates with <code>my_framework_</code>, it can target them within the <code>functions</code> object.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;functions&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;my_framework_*&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;included_files&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;files/*.md&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre></div><h4 id="headers"><a href="#headers" class="header-anchor">#</a> <code>headers</code></h4> <p>Specifies <a href="/routing/headers/">custom headers</a> that Netlify serves with the site when a client makes a request. It follows the same capabilities as the <code>headers</code> array of the <a href="/configure-builds/file-based-configuration/#headers">user-facing file-based configuration.</a></p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;headers&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">&quot;for&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/*&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;values&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;Basic-Auth&quot;</span><span class="token operator">:</span> <span class="token string">&quot;someuser:somepassword anotheruser:anotherpassword&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;X-Frame-Options&quot;</span><span class="token operator">:</span> <span class="token string">&quot;DENY&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;cache-control&quot;</span><span class="token operator">:</span> <span class="token string">&quot;max-age=0,no-cache,no-store,must-revalidate&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre></div><h4 id="images"><a href="#images" class="header-anchor">#</a> <code>images</code></h4> <p>Configures the <a href="/image-cdn/overview/">Netlify Image CDN</a>. You can specify <a href="/image-cdn/overview/#remote-path">allowed domains for remote image transformations</a>.</p> <p>The <code>remote_images</code> property accepts an array of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp" target="_blank" rel="noopener noreferrer">regular expressions</a>, which can represent specific subdomains or directories.</p> <p>Note that slashes need to be double escaped (once due to the regular expression syntax, and a second time due to the JSON syntax). For example, here’s how you could configure the Image CDN to allow any images under <code>https://example.com/</code>.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;images&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;remote_images&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;https:\\/\\/example.com\\/.*&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre></div><h4 id="redirects"><a href="#redirects" class="header-anchor">#</a> <code>redirects</code></h4> <p>Specifies <a href="/routing/redirects/">redirect and rewrite rules</a> that Netlify evaluates when a client makes a request. It follows the same syntax as the <code>redirects</code> array of the <a href="/configure-builds/file-based-configuration/#redirects">user-facing file-based configuration.</a></p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;redirects&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">&quot;force&quot;</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token property">&quot;from&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/old-path&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;status&quot;</span><span class="token operator">:</span> <span class="token number">301</span><span class="token punctuation">,</span> <span class="token property">&quot;to&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/new-path&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;conditions&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;Country&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;US&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token property">&quot;Language&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;en&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;es&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token property">&quot;query&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;path&quot;</span><span class="token operator">:</span> <span class="token string">&quot;:path&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token property">&quot;from&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/news&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;to&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/blog&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre></div><p>These rules are appended to any rules defined by the user in <a href="/routing/redirects/#syntax-for-the-redirects-file">the <code>_redirects</code> file</a> or <a href="/routing/redirects/#syntax-for-the-netlify-configuration-file">the <code>netlify.toml</code> file</a>. Since Netlify reads rules from top to bottom and processes the first matching rule it finds, this means that the user-defined rules take precedence over rules defined in the Frameworks API.</p> <p>If you want to change this behavior and ensure that the rules defined by the framework are evaluated first, you can use the <code>redirects!</code> property instead (with an exclamation mark). Please note that this takes precedence over any redirect rules defined by framework users, so use it sparingly and make sure to communicate to your framework users how this might affect their workflows.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;redirects!&quot;</span><span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">&quot;from&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/some-path&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;to&quot;</span><span class="token operator">:</span> <span class="token string">&quot;/new-path&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre></div><h3 id="netlify-v1-blobs"><a href="#netlify-v1-blobs" class="header-anchor">#</a> <code>.netlify/v1/blobs</code></h3> <p>Upload <a href="/blobs/overview/">blobs</a> to the <a href="/blobs/overview/#deploy-specific-stores">deploy-specific store</a>. This is useful if you want the ability to generate files at build time and then modify them at runtime throughout the lifecycle of the deploy.</p> <p>Our build system traverses the <code>.netlify/v1/blobs/deploy</code> directory and generates a blob for each <code>blob</code> file it finds. The blob key is the path of the file relative to the <code>.netlify/v1/blobs/deploy</code> directory (without a leading slash).</p> <div class="language- extra-class"><pre class="language-text"><code>.netlify/ └── v1/ └── blobs/ └── deploy/ ├── example.com/ │ └── blob └── netlify.com/ ├── blob └── blob.meta.json </code></pre></div><p>For example, the directory tree above would generate two blobs:</p> <ul><li>a blob with the key <code>example.com</code>, holding the contents of the file at <code>.netlify/v1/blobs/deploy/example.com/blob</code></li> <li>a blob with the key <code>netlify.com</code>, holding the contents of the file at <code>.netlify/v1/blobs/deploy/netlify.com/blob</code></li></ul> <p>Optionally, you can include a <code>blob.meta.json</code> file that contains an object with arbitrary metadata, encoded as JSON, which you can then retrieve with the <a href="/blobs/overview/#getmetadata"><code>getMetadata</code></a> and <a href="/blobs/overview/#getwithmetadata"><code>getWithMetadata</code></a> client methods.</p> <div class="custom-block netlify-tip"><p class="custom-block-title">Root key</p> <p>You can’t place a <code>blob</code> file directly under the <code>.netlify/v1/blobs/deploy</code> directory, because that would lead to an empty string as the relative path, which isn’t a valid blob key. If the concept of a root key exists in your specific use case (for example, naming keys after URL paths), you can place all entries under another sub-directory, like <code>my-cache</code>, and treat <code>my-cache</code> as <code>/</code> and <code>my-cache/child</code> as <code>/child</code>.</p></div> <p>Let’s imagine that your framework implements a cache for HTTP requests. You could use Netlify Blobs to store cached responses, and make your generated <a href="#netlify-v1-functions">functions</a> and <a href="#netlify-v1-edge-functions">edge functions</a> check whether there’s a blob for a given URL before making an HTTP call.</p> <div class="language-ts extra-class"><pre class="language-ts"><code><span class="token comment">// .netlify/v1/functions/my-framework-cache.ts</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> getDeployStore <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@netlify/blobs&quot;</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> Config<span class="token punctuation">,</span> Context <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@netlify/functions&quot;</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>req<span class="token operator">:</span> Request<span class="token punctuation">,</span> context<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> domain <span class="token punctuation">}</span> <span class="token operator">=</span> context<span class="token punctuation">.</span>params<span class="token punctuation">;</span> <span class="token keyword">const</span> cache <span class="token operator">=</span> <span class="token function">getDeployStore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> cachedResponse <span class="token operator">=</span> <span class="token keyword">await</span> cache<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>domain<span class="token punctuation">,</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">&quot;stream&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>cachedResponse <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Response</span><span class="token punctuation">(</span>cachedResponse<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">https://</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>domain<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> body <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span><span class="token function">blob</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">await</span> cache<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>domain<span class="token punctuation">,</span> body<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> response<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">const</span> config<span class="token operator">:</span> Config <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">// Accepts requests on paths like &quot;/cache/example.com&quot;.</span> path<span class="token operator">:</span> <span class="token string">&quot;/cache/:domain&quot;</span> <span class="token punctuation">}</span> </code></pre></div><p>To pre-warm the cache with a response for <code>https://example.com</code>, you could fetch it at build time and write the response to a file at <code>.netlify/v1/blobs/deploy/example.com/blob</code>.</p> <p>Additionally, you could modify the example above to also persist the headers of cached responses. To write a metadata object for the same <code>example.com</code> key, write a JSON object to <code>.netlify/v1/blobs/deploy/example.com/blob.meta.json</code> with a payload like:</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;headers&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;Content-Type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;text/html; charset=UTF-8&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;Date&quot;</span><span class="token operator">:</span> <span class="token string">&quot;Wed, 12 Jun 2024 09:14:11 GMT&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre></div><h3 id="netlify-v1-edge-functions"><a href="#netlify-v1-edge-functions" class="header-anchor">#</a> <code>.netlify/v1/edge-functions</code></h3> <p>Generate <a href="/edge-functions/overview/">edge functions</a> for a site and configure the URL paths on which they run.</p> <p>Edge Functions let you intercept requests at the very beginning of the request chain, and intercept responses just before they are delivered to the client. In both cases, you have the option to modify the payloads in any way you like.</p> <p>For example, you could generate an edge function that intercepts requests for JSON (by inspecting <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept" target="_blank" rel="noopener noreferrer">the <code>Accept</code> header</a>) and <a href="/edge-functions/api/#return-a-rewrite">rewrite them</a> to a path that implements your framework’s API route. If a client requests <code>https://example.com/products/123</code> and asks for a JSON response, the edge function would serve the contents of the <code>https://example.com/api/products/123</code> path.</p> <p>To create this edge function, your framework would write the code below to a file at <code>.netlify/v1/edge-functions/my-framework-api-route-handler.ts</code>.</p> <div class="language-tsx extra-class"><pre class="language-tsx"><code><span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> Config<span class="token punctuation">,</span> Context <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@netlify/edge-functions&quot;</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>req<span class="token operator">:</span> Request<span class="token punctuation">,</span> context<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>headers<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">&quot;accept&quot;</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string">&quot;application/json&quot;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> pathname <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token constant">URL</span></span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>url<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name"><span class="token constant">URL</span></span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/api</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>pathname<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> req<span class="token punctuation">.</span>url<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">const</span> config<span class="token operator">:</span> Config <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">// Configures the paths on which the edge function runs.</span> <span class="token comment">// The value below lets you intercept requests for any path.</span> path<span class="token operator">:</span> <span class="token string">&quot;/*&quot;</span><span class="token punctuation">,</span> <span class="token comment">// Sometimes it's useful to exclude certain paths. In our</span> <span class="token comment">// example, we don't need to intercept requests that are</span> <span class="token comment">// already targeting an `/api/` path.</span> excludedPath<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;/api/*&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre></div><h4 id="configuration-options"><a href="#configuration-options" class="header-anchor">#</a> Configuration options</h4> <p>To configure generated edge functions from within the function file, export a <code>config</code> object. It accepts the following properties:</p> <ul><li><code>path</code> (<code>string</code> or <code>string[]</code>): The URL path or set of paths for which the edge function is invoked. It accepts a string for a single path, or an array of strings for multiple paths. It supports wildcards and named parameters using <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API" target="_blank" rel="noopener noreferrer">the <code>URLPattern</code> web standard syntax</a>.</li> <li><code>excludedPath</code> (<code>string</code> or <code>string[]</code>): A URL path or set of paths for which the edge function is never invoked. It accepts a string for a single path, or an array of strings for multiple paths. It supports wildcards and named parameters using <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API" target="_blank" rel="noopener noreferrer">the <code>URLPattern</code> web standard syntax</a>.</li> <li><code>method</code> (<code>string</code> or <code>string[]</code>): A method or set of methods for which the edge function is invoked. Supported HTTP methods are GET, POST, PUT, PATCH, DELETE, and OPTIONS. If not specified, the edge function is invoked for all methods.</li> <li><code>cache</code> (<code>string</code>): Opts in to <a href="/edge-functions/optional-configuration/#response-caching">response caching</a>.</li> <li><code>name</code> (<code>string</code>): A human-friendly name for the edge function. It is shown instead of the filename in build logs and in the UI.</li> <li><code>generator</code> (<code>string</code>): Lets you tag an edge function with the name and the version of your framework. While this has no direct effect on any user-facing areas, it lets us internally correlate requests for this edge function with a specific framework version to identify and troubleshoot possible issues with a release.</li> <li><code>onError</code> (<code>string</code>): Defines the behavior for <a href="/edge-functions/optional-configuration/#error-handling">when the edge function terminates unexpectedly</a>. You can choose to serve a generic error page (<code>fail</code>, the default value), skip the erroring edge function and continue the request chain (<code>bypass</code>), or provide a URL path that requests are rewritten to in the event of an error (for example, <code>/my-framework-error-page</code>).</li> <li><code>rateLimit</code> (<code>object</code>): Sets <a href="/security/secure-access-to-sites/rate-limiting/#function-edge-function-examples">custom rate limiting rules</a> for the edge function.</li></ul> <div class="custom-block netlify-warning"><p class="custom-block-title">Static values only</p> <p>The <code>config</code> object must be defined in <a href="/edge-functions/get-started/#create-an-edge-function">the edge function’s main file</a> and it must not be renamed or re-exported. It can only use static values, which means that using constants or variables is not allowed.</p></div> <h4 id="bundling"><a href="#bundling" class="header-anchor">#</a> Bundling</h4> <p>When an edge function is created, either directly by a user or by a framework using the Frameworks API, Netlify automatically handles the bundling process. This involves collecting all the edge function’s dependencies, including local imports and <a href="https://www.netlify.com/blog/support-for-npm-modules-in-edge-functions/" target="_blank" rel="noopener noreferrer">third-party modules</a>, into a single file.</p> <p>Optionally, you can choose to handle this process yourself, using tools like <a href="https://esbuild.github.io/" target="_blank" rel="noopener noreferrer">esbuild</a> or <a href="https://vitejs.dev/" target="_blank" rel="noopener noreferrer">Vite</a> to generate a self-contained bundle with all the dependencies inlined. When you do this, the Netlify bundling process is essentially a no-op, and we use your generated bundle as is.</p> <p>There are some things to consider if you choose to do this:</p> <ul><li>It’s important to note that <a href="/edge-functions/api/#runtime-environment">edge functions run on Deno</a>, not Node.js. This has the following implications: <ul><li>You shouldn’t rely on Node.js built-ins.</li> <li>You should always generate ESM code (not CommonJS) with the latest syntax.</li></ul></li> <li>If you’re bundling your code using esbuild, set <a href="https://esbuild.github.io/api/#platform" target="_blank" rel="noopener noreferrer">the <code>platform</code> property</a> to <code>neutral</code> and set <a href="https://esbuild.github.io/api/#target" target="_blank" rel="noopener noreferrer"><code>target</code> to <code>esnext</code></a>.</li> <li>For Vite, set <a href="https://github.com/netlify/remix-compute/blob/124b930bf0a72427240d744bb96e17cb2f258536/packages/remix-edge-adapter/src/plugin.ts#L49" target="_blank" rel="noopener noreferrer"><code>target</code> to <code>webworker</code></a> and <a href="https://github.com/netlify/remix-compute/blob/124b930bf0a72427240d744bb96e17cb2f258536/packages/remix-edge-adapter/src/plugin.ts#L51" target="_blank" rel="noopener noreferrer">mark all Node.js built-ins as external</a>.</li></ul> <h4 id="import-maps"><a href="#import-maps" class="header-anchor">#</a> Import maps</h4> <p>You can customize the resolution of module specifiers in edge functions using <a href="/edge-functions/api/#import-maps">import maps</a>. To do this, place a file following <a href="https://html.spec.whatwg.org/multipage/webappapis.html#import-maps" target="_blank" rel="noopener noreferrer">the import map syntax</a> at <code>.netlify/v1/edge-functions/import_map.json</code>.</p> <p>For example, the file below would let you rewrite the bare specifier <code>html-rewriter</code> to a specific remote URL, and point <code>utils</code> to a local directory so you can import <code>utils/ab-test.ts</code> instead of <code>./nested/directory/utils/ab-test.ts</code>.</p> <div class="language-json extra-class"><pre class="language-json"><code><span class="token punctuation">{</span> <span class="token property">&quot;imports&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">&quot;html-rewriter&quot;</span><span class="token operator">:</span> <span class="token string">&quot;https://ghuc.cc/worker-tools/html-rewriter/index.ts&quot;</span><span class="token punctuation">,</span> <span class="token property">&quot;utils/&quot;</span><span class="token operator">:</span> <span class="token string">&quot;./nested/directory/utils&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre></div><h3 id="netlify-v1-functions"><a href="#netlify-v1-functions" class="header-anchor">#</a> <code>.netlify/v1/functions</code></h3> <p>Generate serverless functions for a site and configure the URL paths on which they run. It accepts the same naming conventions and uses the same syntax as <a href="/functions/get-started/?fn-language=ts">user-defined functions</a>.</p> <p>Functions are a way to dynamically render parts of your application, like API routes. You can also use them to power your framework’s <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Web_frameworks" target="_blank" rel="noopener noreferrer">server-side rendering</a> capabilities.</p> <p>For example, you could generate an SSR function by writing the following code to <code>.netlify/v1/functions/my-framework-ssr.ts</code>.</p> <div class="language-ts extra-class"><pre class="language-ts"><code><span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> Config<span class="token punctuation">,</span> Context <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@netlify/functions&quot;</span><span class="token punctuation">;</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> renderPage <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;./your-framework-code.ts&quot;</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>req<span class="token operator">:</span> Request<span class="token punctuation">,</span> context<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> html <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">renderPage</span><span class="token punctuation">(</span>req<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Response</span><span class="token punctuation">(</span>html<span class="token punctuation">,</span> <span class="token punctuation">{</span> headers<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token string-property property">&quot;content-type&quot;</span><span class="token operator">:</span> <span class="token string">&quot;text/html&quot;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">const</span> config<span class="token operator">:</span> Config <span class="token operator">=</span> <span class="token punctuation">{</span> path<span class="token operator">:</span> <span class="token string">&quot;/*&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre></div><h4 id="configuration-options-2"><a href="#configuration-options-2" class="header-anchor">#</a> Configuration options</h4> <p>Generated functions can be configured from within the function file using an exported <code>config</code> object. It accepts the following properties:</p> <ul><li><code>path</code> (<code>string</code> or <code>string[]</code>): The URL path or set of paths for which the function is invoked. It supports wildcards and named parameters using <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API" target="_blank" rel="noopener noreferrer">the <code>URLPattern</code> web standard syntax</a>.</li> <li><code>preferStatic</code> (<code>boolean</code>): By default, functions run for any requests to the configured paths, regardless of whether or not they also match static files. To prevent the function from shadowing files on the CDN, set <code>preferStatic: true</code>.</li> <li><code>displayName</code> (<code>string</code>): A human-friendly name for the function. It is shown instead of the filename in build logs and in the UI.</li> <li><code>generator</code> (<code>string</code>): Lets you tag a function with the name and the version of your framework. While this has no direct effect on any user-facing areas, it lets us internally correlate requests for this function with a specific framework version to identify and troubleshoot possible issues with a release.</li> <li><code>includedFiles</code> (<code>string[]</code>): List of additional paths to include in the function bundle. Although Netlify includes statically referenced files (like <code>require(&quot;./some-file.js&quot;)</code>) by default, you can specify additional files or directories and reference them dynamically in function code. You can use <code>*</code> to match any character or prefix an entry with <code>!</code> to exclude files. Paths are absolute paths relative to the base directory.</li> <li><code>nodeBundler</code> (<code>string</code>): Changes the default bundling mechanism used to collect all function dependencies (including local files and third-party modules) into a deployable package. You can set it to <code>esbuild</code> if you want to use <a href="https://esbuild.github.io/" target="_blank" rel="noopener noreferrer">esbuild</a> to bundle everything into a single file, which usually leads to a smaller payload; you can set it to <code>none</code> if you want to use <a href="#bundling-2">your own bundling process</a>.</li> <li><code>externalNodeModules</code> (<code>string[]</code>): When setting <code>nodeBundler</code> to <code>esbuild</code>, this property lets you provide a list of npm packages that are marked as <a href="https://esbuild.github.io/api/#external" target="_blank" rel="noopener noreferrer">external</a>, which means their original structure is kept in a <code>node_modules</code> directory as opposed to being inlined with the function code.</li> <li><code>ignoredNodeModules</code> (<code>string[]</code>): When setting <code>nodeBundler</code> to <code>esbuild</code>, this property lets you provide a list of npm packages that are marked as <a href="https://esbuild.github.io/api/#external" target="_blank" rel="noopener noreferrer">external</a> but whose source is not preserved in the <code>node_modules</code> directory. This should only be used for packages that you know for a fact are not used at runtime, otherwise it can lead to an error when the function is invoked.</li> <li><code>nodeVersion</code> (<code>string</code>): Sets the major version of Node.js to run the function with. It takes values like <code>20</code> to use Node.js 20.x, for example.</li> <li><code>schedule</code> (<code>string</code>): When defined, turns the function into a <a href="/functions/scheduled-functions/">scheduled function</a> and defines the schedule on which it runs.</li> <li><code>rateLimit</code> (<code>object</code>): Sets <a href="/security/secure-access-to-sites/rate-limiting/#function-edge-function-examples">custom rate limiting rules</a> for the function.</li></ul> <div class="custom-block netlify-warning"><p class="custom-block-title">Static values only</p> <p>The <code>config</code> object must be defined in <a href="/functions/get-started/#route-requests">the function’s main file</a> and it must not be renamed or re-exported. It can only use static values, which means that using constants or variables is not allowed.</p></div> <h4 id="bundling-2"><a href="#bundling-2" class="header-anchor">#</a> Bundling</h4> <p>When a function is created, either directly by a user or by a framework using the Frameworks API, Netlify automatically handles the bundling process by default. This means collecting all the function’s dependencies, including local files and third-party modules, into a deployable package.</p> <p>Optionally, you can choose to take control over this process. This may be useful if your framework already includes its own bundling pipeline. To opt out of the default bundling mechanism, you must set two configuration properties (<code>nodeBundler</code> and <code>includedFiles</code>) in the function’s <code>config</code> object.</p> <div class="language-ts extra-class"><pre class="language-ts"><code><span class="token keyword">import</span> <span class="token keyword">type</span> <span class="token punctuation">{</span> Config<span class="token punctuation">,</span> Context <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">&quot;@netlify/functions&quot;</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">async</span> <span class="token punctuation">(</span>req<span class="token operator">:</span> Request<span class="token punctuation">,</span> context<span class="token operator">:</span> Context<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Response</span><span class="token punctuation">(</span><span class="token string">&quot;Hello world&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">const</span> config<span class="token operator">:</span> Config <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token comment">// Setting `nodeBundler` to `none` lets you opt out of the</span> <span class="token comment">// automatic bundling process.</span> nodeBundler<span class="token operator">:</span> <span class="token string">&quot;none&quot;</span><span class="token punctuation">,</span> <span class="token comment">// When using a custom bundling process, you must provide the</span> <span class="token comment">// full list of files to include in the deployable package.</span> <span class="token comment">// You can use the `includedFiles` property, which supports globs.</span> includedFiles<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;my-framework-bundle-output/**&quot;</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> </code></pre></div><h2 id="merging-configurations"><a href="#merging-configurations" class="header-anchor">#</a> Merging configurations</h2> <p>All Netlify platform primitives can be provisioned and configured directly by developers — for example, a developer can create a redirect rule by <a href="/routing/redirects/#syntax-for-the-redirects-file">writing a <code>_redirects</code> file</a> or deploy a function by <a href="/functions/get-started/#create-function-file">writing a file to the functions directory</a>.</p> <p>The Frameworks API was designed to extend these configuration options, not override them. This means that any user-defined configurations are respected, and the following rules apply when those configurations are merged with the Frameworks API:</p> <ul><li>For properties that are “additive” (like the <a href="/image-cdn/overview/#remote-path">allowed domains for the Netlify Image CDN</a> or <a href="/frameworks-api/#netlify-v1-functions">the list of serverless functions</a>), any entries from the Frameworks API are appended to the ones defined by the user; if order is relevant, user-defined configuration takes precedence</li> <li>For properties that are mutually-exclusive (like the <a href="#functions">functions directory</a>), any user-defined configuration takes precedence<div class="custom-block netlify-tip"><p class="custom-block-title">Avoid collisions with user-defined functions</p> <p>To help make sure your framework-defined functions aren’t overridden by user-defined functions, we recommend that you include your framework’s name in your function names. For example, <code>my-framework-ssr.ts</code>.</p></div></li></ul> <h2 id="versioning"><a href="#versioning" class="header-anchor">#</a> Versioning</h2> <p>The filesystem is the only interface to the Frameworks API; there are no client libraries for programmatic access. This lowers the barrier of entry to the absolute minimum, allowing any framework, of any technology stack, to take advantage of the Netlify platform by writing files to disk.</p> <p>But even without pulling in a library, there is still an intrinsic dependency between the Frameworks API and any framework that uses it. As we update the API surface with new features or changes to existing ones, we will always do so in a backward-compatible way, to ensure that all framework versions continue to operate without any disruption.</p> <p>To this end, all features have a version identifier in their file paths (for example, <code>.netlify/v1/config.json</code>). A breaking change to that feature would be released as <code>.netlify/v2/config.json</code>, with no changes to the previous path, giving framework authors the choice to update their implementation at their own schedule.</p></div> <!----> <div class="content__default wrapper__last_updated"><time datetime="2024-10-16"> Last updated: October 16, 2024 </time></div> <!----> <div class="feedback"><div class="media"><div class="media__body"><h4 class="media__title"> Did you find this doc useful? </h4> <!----> <p class="media__copy"> Your feedback helps us improve our docs. </p> <!----> <!----></div> <div class="media__figure"><button aria-label="upvote" class="feedback__vote feedback__vote--upvote"><svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" aria-hidden="true"><g fill="none" fill-rule="evenodd"><circle cx="32" cy="32" r="32" fill="none" fill-rule="nonzero"></circle> <g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M40 29h-7.645l1.473-3.889c.377-.996.042-2.135-.803-2.73-.963-.679-2.263-.427-2.936.569L26 29v9a4 4 0 0 0 4 4h6.517c1.51 0 2.893-.852 3.573-2.203L42 36v-5a2 2 0 0 0-2-2zM22 29v12"></path></g></g></svg></button><button aria-label="downvote" class="feedback__vote feedback__vote--downvote"><svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" aria-hidden="true"><g fill="none" fill-rule="evenodd"><circle cx="32" cy="32" r="32" fill="none" fill-rule="nonzero"></circle> <g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M23 35h7.645l-1.473 3.889c-.377.996-.042 2.135.803 2.73.963.679 2.263.427 2.936-.569l4.09-6.05v-9a4 4 0 0 0-4-4h-6.518c-1.51 0-2.893.852-3.573 2.202L21 28v5a2 2 0 0 0 2 2zM41 35V23"></path></g></g></svg></button></div></div> <div><form class='form form--floating-labels feedback__form--appear' method='post' name='feedback'><input type="hidden" name="form-name" value="feedback"> <input type="hidden" name="path" value="/frameworks-api/"> <input type="hidden" name="vote" value=""> <label class="visuallyhidden"> Do not fill in this field <input name="verification" value=""></label> <div class="form__field"><label><div class="form__label"> What else would you like to tell us about this doc? </div> <textarea name="feedback" class="form__textarea"></textarea></label></div> <div class="btn-group"><button disabled="disabled" class="btn"> Send </button></div></form></div></div> <footer class="footer"><div class="footer-wrapper"><nav aria-label="Footer navigation" class="footer-nav"><ul class="footer__nav"><li class="footer__nav-item"><a href="https://netlify.com/" class="footer__nav-link"> Netlify </a></li> <li class="footer__nav-item"><a href="https://netlify.com/careers/" class="footer__nav-link"> Careers </a></li> <li class="footer__nav-item"><a href="https://netlify.com/blog/" class="footer__nav-link"> Blog </a></li> <li class="footer__nav-item"><a href="https://www.netlify.com/legal/terms-of-use/" class="footer__nav-link"> Terms </a></li> <li class="footer__nav-item"><a href="https://www.netlify.com/privacy/" class="footer__nav-link"> Privacy </a></li></ul></nav> <div class="dark-mode-widget footer__theme-toggle" data-v-0d17f8d5><label for="theme-select" class="visuallyhidden" data-v-0d17f8d5>Select a theme</label> <div class="forms-select-c" data-v-0d17f8d5><div class="theme-toggle-icon" data-v-0d17f8d5><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" data-v-0d17f8d5><path fill-rule="evenodd" clip-rule="evenodd" d="M14 7C14 10.866 10.866 14 7 14C3.13401 14 0 10.866 0 7C0 3.13401 3.13401 0 7 0C10.866 0 14 3.13401 14 7ZM7 12.2C6.99999 12.2 7.00001 12.2 7 12.2C4.12812 12.2 1.8 9.87188 1.8 7C1.8 4.12812 4.12812 1.8 7 1.8C7.00001 1.8 6.99999 1.8 7 1.8V12.2Z" fill="currentColor"></path></svg> <!----> <!----></div> <select value="system" name="theme-select" id="theme-select" class="forms-input"> <option value="system" data-v-0d17f8d5>System</option><option value="light" data-v-0d17f8d5>Light</option><option value="dark" data-v-0d17f8d5>Dark</option></select> <svg width="21" height="13" viewBox="0 0 21 13" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-arrow-down forms-select-c-arrow"><path d="M20.7656 1.82812C21.0156 2.10938 21.0156 2.375 20.7656 2.625L10.9219 12.4688C10.6719 12.7188 10.4219 12.7188 10.1719 12.4688L0.328125 2.625C0.078125 2.375 0.078125 2.10938 0.328125 1.82812L1.26562 0.9375C1.51562 0.65625 1.78125 0.65625 2.0625 0.9375L10.5469 9.375L19.0312 0.9375C19.3125 0.65625 19.5781 0.65625 19.8281 0.9375L20.7656 1.82812Z"></path></svg></div></div></div> <p class="footer__copyright">© 2024 Netlify</p></footer></section></main></div><div class="global-ui"></div></div> <script src="/assets/js/app.1a68918d.js" defer></script><script src="/assets/js/10.a8fb7bb3.js" defer></script><script src="/assets/js/2.f24e0879.js" defer></script><script src="/assets/js/107.4de9a99f.js" defer></script><script src="/assets/js/3.be674a14.js" defer></script> <script src="/netlify-cnm/cnm.js" async defer></script> <script async id="netlify-rum-container" src="/.netlify/scripts/rum" data-netlify-rum-site-id="90a54386-9477-4113-bd6a-b9227b573d00" data-netlify-deploy-branch="main" data-netlify-deploy-context="production" data-netlify-cwv-token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzaXRlX2lkIjoiOTBhNTQzODYtOTQ3Ny00MTEzLWJkNmEtYjkyMjdiNTczZDAwIiwiYWNjb3VudF9pZCI6IjU4ZGE4ODkzZDY4NjVkMzVjOTJhNzJiOCIsImRlcGxveV9pZCI6IjY3NDBmMzNkOTdmMTdiMDAwODkyNzMyMCIsImlzc3VlciI6Im5mc2VydmVyIn0.w3RbnVlZywFu8_P7X1si0AcznAHq7JlUzsxOj5i3olQ"></script><script type="text/javascript"> if (window.location.host === "docs.netlify.com") { !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.13.1"; analytics.load("kjz0qkJslzzHMcNGI3GkDb9HDZ6vspYZ"); }}(); } </script></body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10