# Table of Contents - [Billing | Netlify Docs](#billing-netlify-docs) - [Billing FAQ | Netlify Docs](#billing-faq-netlify-docs) - [Team management | Netlify Docs](#team-management-netlify-docs) - [Manage team members | Netlify Docs](#manage-team-members-netlify-docs) - [AI-Assisted Publishing | Netlify Docs](#ai-assisted-publishing-netlify-docs) - [Organization management | Netlify Docs](#organization-management-netlify-docs) - [Roles and permissions | Netlify Docs](#roles-and-permissions-netlify-docs) - [Team audit log | Netlify Docs](#team-audit-log-netlify-docs) - [Team-owned sites | Netlify Docs](#team-owned-sites-netlify-docs) - [User settings | Netlify Docs](#user-settings-netlify-docs) - [Ask Netlify | Netlify Docs](#ask-netlify-netlify-docs) - [Get started with Async Workloads | Netlify Docs](#get-started-with-async-workloads-netlify-docs) - [Async Workloads overview | Netlify Docs](#async-workloads-overview-netlify-docs) - [Async Workload Limitations | Netlify Docs](#async-workload-limitations-netlify-docs) - [Lifecycle of Async Workloads | Netlify Docs](#lifecycle-of-async-workloads-netlify-docs) - [Optional Configuration | Netlify Docs](#optional-configuration-netlify-docs) - [Get started with Netlify CLI | Netlify Docs](#get-started-with-netlify-cli-netlify-docs) - [Share Build Plugins | Netlify Docs](#share-build-plugins-netlify-docs) - [Sending Async Workload events | Netlify Docs](#sending-async-workload-events-netlify-docs) - [Debug with VS Code and Netlify CLI | Netlify Docs](#debug-with-vs-code-and-netlify-cli-netlify-docs) - [Build Plugins | Netlify Docs](#build-plugins-netlify-docs) - [Manage functions with Netlify CLI | Netlify Docs](#manage-functions-with-netlify-cli-netlify-docs) - [Multi-step Async Workloads | Netlify Docs](#multi-step-async-workloads-netlify-docs) - [Writing Async Workloads | Netlify Docs](#writing-async-workloads-netlify-docs) - [Local development with Netlify CLI | Netlify Docs](#local-development-with-netlify-cli-netlify-docs) - [Create Build Plugins | Netlify Docs](#create-build-plugins-netlify-docs) - [Netlify Blobs | Netlify Docs](#netlify-blobs-netlify-docs) - [Build hooks | Netlify Docs](#build-hooks-netlify-docs) - [Available software at build time | Netlify Docs](#available-software-at-build-time-netlify-docs) - [Ignore builds | Netlify Docs](#ignore-builds-netlify-docs) - [Build environment variables | Netlify Docs](#build-environment-variables-netlify-docs) - [Build configuration overview | Netlify Docs](#build-configuration-overview-netlify-docs) - [JavaScript SPAs | Netlify Docs](#javascript-spas-netlify-docs) - [API authentication in Netlify Connect | Netlify Docs](#api-authentication-in-netlify-connect-netlify-docs) - [File-based configuration | Netlify Docs](#file-based-configuration-netlify-docs) - [Get started with the Netlify API | Netlify Docs](#get-started-with-the-netlify-api-netlify-docs) - [Monorepos | Netlify Docs](#monorepos-netlify-docs) - [Manage build dependencies | Netlify Docs](#manage-build-dependencies-netlify-docs) - [Access data with Netlify Connect | Netlify Docs](#access-data-with-netlify-connect-netlify-docs) - [On-demand Builders | Netlify Docs](#on-demand-builders-netlify-docs) - [Monitor activity in Netlify Connect | Netlify Docs](#monitor-activity-in-netlify-connect-netlify-docs) - [Data revisions in Netlify Connect | Netlify Docs](#data-revisions-in-netlify-connect-netlify-docs) - [Manage cross-references in Netlify Connect | Netlify Docs](#manage-cross-references-in-netlify-connect-netlify-docs) - [Manage connected sites in Netlify Connect | Netlify Docs](#manage-connected-sites-in-netlify-connect-netlify-docs) - [Netlify Connect overview | Netlify Docs](#netlify-connect-overview-netlify-docs) - [Get started with Netlify Connect | Netlify Docs](#get-started-with-netlify-connect-netlify-docs) - [Sync events in Netlify Connect | Netlify Docs](#sync-events-in-netlify-connect-netlify-docs) - [Manage data layers in Netlify Connect | Netlify Docs](#manage-data-layers-in-netlify-connect-netlify-docs) - [Netlify Connect usage and billing | Netlify Docs](#netlify-connect-usage-and-billing-netlify-docs) - [Troubleshooting tips for Netlify Connect | Netlify Docs](#troubleshooting-tips-for-netlify-connect-netlify-docs) - [Configure external DNS for a custom domain | Netlify Docs](#configure-external-dns-for-a-custom-domain-netlify-docs) - [Delegate a stand-alone subdomain to Netlify DNS | Netlify Docs](#delegate-a-stand-alone-subdomain-to-netlify-dns-netlify-docs) - [Custom domains | Netlify Docs](#custom-domains-netlify-docs) - [Domain registration | Netlify Docs](#domain-registration-netlify-docs) - [Dedicated secondary DNS | Netlify Docs](#dedicated-secondary-dns-netlify-docs) - [Delegate your domain to Netlify | Netlify Docs](#delegate-your-domain-to-netlify-netlify-docs) - [HTTPS (SSL) | Netlify Docs](#https-ssl-netlify-docs) - [Automatic deploy subdomains | Netlify Docs](#automatic-deploy-subdomains-netlify-docs) - [DNS records | Netlify Docs](#dns-records-netlify-docs) - [Netlify DNS | Netlify Docs](#netlify-dns-netlify-docs) - [DNS & HTTPS troubleshooting tips | Netlify Docs](#dns-https-troubleshooting-tips-netlify-docs) - [Sites with multiple domains | Netlify Docs](#sites-with-multiple-domains-netlify-docs) - [Edge Functions API | Netlify Docs](#edge-functions-api-netlify-docs) - [Get started with Edge Functions | Netlify Docs](#get-started-with-edge-functions-netlify-docs) - [Create an Edge Functions integration | Netlify Docs](#create-an-edge-functions-integration-netlify-docs) - [Edge Functions declarations | Netlify Docs](#edge-functions-declarations-netlify-docs) - [Edge Functions limits | Netlify Docs](#edge-functions-limits-netlify-docs) - [Enhanced security with Secrets Controller | Netlify Docs](#enhanced-security-with-secrets-controller-netlify-docs) - [Get started with environment variables | Netlify Docs](#get-started-with-environment-variables-netlify-docs) - [Edge Functions usage and billing | Netlify Docs](#edge-functions-usage-and-billing-netlify-docs) - [Optional configuration for edge functions | Netlify Docs](#optional-configuration-for-edge-functions-netlify-docs) - [Forms usage and billing | Netlify Docs](#forms-usage-and-billing-netlify-docs) - [Edge Functions overview | Netlify Docs](#edge-functions-overview-netlify-docs) - [Spam filters | Netlify Docs](#spam-filters-netlify-docs) - [Form notifications | Netlify Docs](#form-notifications-netlify-docs) - [Form troubleshooting tips | Netlify Docs](#form-troubleshooting-tips-netlify-docs) - [Environment variables overview | Netlify Docs](#environment-variables-overview-netlify-docs) - [Astro on Netlify | Netlify Docs](#astro-on-netlify-netlify-docs) - [Form submissions | Netlify Docs](#form-submissions-netlify-docs) - [Forms setup | Netlify Docs](#forms-setup-netlify-docs) - [Frameworks API | Netlify Docs](#frameworks-api-netlify-docs) - [Express on Netlify | Netlify Docs](#express-on-netlify-netlify-docs) - [Eleventy on Netlify | Netlify Docs](#eleventy-on-netlify-netlify-docs) - [Environment variables and frameworks | Netlify Docs](#environment-variables-and-frameworks-netlify-docs) - [Angular on Netlify | Netlify Docs](#angular-on-netlify-netlify-docs) - [Hydrogen on Netlify | Netlify Docs](#hydrogen-on-netlify-netlify-docs) - [Hugo on Netlify | Netlify Docs](#hugo-on-netlify-netlify-docs) - [Frameworks | Netlify Docs](#frameworks-netlify-docs) - [Gatsby on Netlify | Netlify Docs](#gatsby-on-netlify-netlify-docs) - [Next.js on Netlify | Netlify Docs](#next-js-on-netlify-netlify-docs) - [Troubleshooting Next.js on Netlify | Netlify Docs](#troubleshooting-next-js-on-netlify-netlify-docs) - [Next.js ISR on Netlify | Netlify Docs](#next-js-isr-on-netlify-netlify-docs) - [Next.js redirects and rewrites on Netlify | Netlify Docs](#next-js-redirects-and-rewrites-on-netlify-netlify-docs) - [React on Netlify | Netlify Docs](#react-on-netlify-netlify-docs) - [Legacy Next.js on Netlify | Netlify Docs](#legacy-next-js-on-netlify-netlify-docs) - [Next.js Middleware on Netlify | Netlify Docs](#next-js-middleware-on-netlify-netlify-docs) - [React Router on Netlify | Netlify Docs](#react-router-on-netlify-netlify-docs) - [Nuxt on Netlify | Netlify Docs](#nuxt-on-netlify-netlify-docs) - [SvelteKit on Netlify | Netlify Docs](#sveltekit-on-netlify-netlify-docs) - [Vite on Netlify | Netlify Docs](#vite-on-netlify-netlify-docs) - [Stop or activate builds | Netlify Docs](#stop-or-activate-builds-netlify-docs) - [Remix on Netlify | Netlify Docs](#remix-on-netlify-netlify-docs) - [Next.js advanced API routes | Netlify Docs](#next-js-advanced-api-routes-netlify-docs) - [Background Functions overview | Netlify Docs](#background-functions-overview-netlify-docs) - [Scheduled Functions | Netlify Docs](#scheduled-functions-netlify-docs) - [Vue CLI on Netlify | Netlify Docs](#vue-cli-on-netlify-netlify-docs) - [Manage notifications in Netlify Connect | Netlify Docs](#manage-notifications-in-netlify-connect-netlify-docs) - [Functions API reference | Netlify Docs](#functions-api-reference-netlify-docs) - [Function logs | Netlify Docs](#function-logs-netlify-docs) - [Functions overview | Netlify Docs](#functions-overview-netlify-docs) - [Functions and Identity | Netlify Docs](#functions-and-identity-netlify-docs) - [Deploy functions | Netlify Docs](#deploy-functions-netlify-docs) - [Optional configuration for functions | Netlify Docs](#optional-configuration-for-functions-netlify-docs) - [Large Media overview | Netlify Docs](#large-media-overview-netlify-docs) - [Get started with Netlify | Netlify Docs](#get-started-with-netlify-netlify-docs) - [Large Media requirements and limitations | Netlify Docs](#large-media-requirements-and-limitations-netlify-docs) - [Large Media setup | Netlify Docs](#large-media-setup-netlify-docs) - [Repository collaboration with Large Media | Netlify Docs](#repository-collaboration-with-large-media-netlify-docs) --- # Billing | Netlify Docs To check billing information or change billing-related settings for a team, select the relevant team in the navigation, then select **Billing** . Organization Owners can access billing information by selecting their organization name in the navigation and going to **Organization overview \> Billing** . [#](#organization-usage) Organization usage -------------------------------------------- Organization Owners can check the total bandwidth and build minute usage of their organization and its linked teams on the organization’s [**Overview** page](/accounts-and-billing/organization-management/#organization-overview) . All teams belonging to an organization have their own usage allocation, and any usage above the allotment is charged at the organization level. An invoice with a breakdown of the teams’ usage charges is sent on a monthly basis on the corresponding bill cycle day. [#](#team-plans) Team plans ---------------------------- Each team has a subscription [plan](https://www.netlify.com/pricing/) . To check fees and usage for the current billing period, go to **Billing \> Current services \> Plan details** . To upgrade or downgrade your team plan, select the **Change team plan** button to choose your new plan. ![](/images/accounts-and-billing-plan-details.png) [#](#usage-and-insights) Usage and insights -------------------------------------------- Owners and Billing Admins can monitor the usage of various features in the Netlify UI. To find this information, go to **Billing \> Account usage insights** . **Account usage insights** provides you with a comprehensive overview of your team’s usage data: * **Sites:** the total number of sites and the number of sites using custom domains across your team. * **Bandwidth:** the amount of bandwidth used (in bytes) across your domains and Netlify Connect data layers. * **Builds:** tracks the build minute usage and number of builds across your sites. Shows a list of sites that have accrued the most build time. * **Compute:** tracks daily serverless functions and background functions usage. Want site-level data? For more detailed site-level information about serverless function usage, explore the [Function Metrics](/monitor-sites/function-metrics/) for your sites. * **Storage:** daily usage amounts for [Netlify Image CDN](/image-cdn/overview/) . * **Members:** your team’s current member count across all role types. ### [#](#bandwidth-usage) Bandwidth usage Netlify tracks outgoing bandwidth usage at the team level. Each team plan includes a monthly bandwidth allotment, and usage above the allotment is charged in extra usage packages as described on our [pricing page](https://www.netlify.com/pricing/?category=developer#features-bandwidth) . #### [#](#find-your-bandwidth-usage) Find your bandwidth usage Owners and Billing Admins can find the team’s current bandwidth usage and current allowance, including extra usage packages, in the Netlify UI. Find your team’s total current bandwidth in these places: * your team’s **Sites** page for a brief usage summary * the **Account usage insights** section on your team’s **Billing** page for more in-depth details You can monitor which sites use the most bandwidth under **Billing \> Bandwidth usage data** . For the most recent bandwidth usage data, go to **Current billing period** and select the caret next to **Top bandwidth usage per domain** to expand the section and access usage details. ![](/images/accounts-and-billing-top-bandwidth-usage-dropdown-caret.png) If your team is currently on an [Enterprise](https://www.netlify.com/pricing/) plan, you can access site bandwidth usage from the past billing period under **Previous billing period**. The number of domains listed under **Top bandwidth usage per domain** varies by team plan. Refer to the [pricing page](https://www.netlify.com/pricing/) for details. If your team uses [Netlify Connect](/connect/overview) , you can also find a list of the data layers that use the most bandwidth in this section. Scroll down to **Top bandwidth usage per Netlify Connect data layer** for a list of [data layer IDs](/connect/troubleshooting-tips/#find-your-data-layer-id) and the bandwidth used by each data layer. ![](/images/accounts-and-billing-top-bandwidth-usage-connect-data-layer-dropdown-caret.png) Bandwidth usage data updates in near real-time and may require a browser refresh. For additional bandwidth usage data, go to **Billing \> Account usage insights** . ##### [#](#export-bandwidth-usage-to-csv) Export bandwidth usage to CSV This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. You can export top bandwidth usage details to a CSV file. Under **Current billing period** or **Previous billing period**, select **Download CSV**. #### [#](#bandwidth-usage-calculation) Bandwidth usage calculation Metered usage consists of all outgoing data traffic on your team’s sites, including: * pages, files, assets, and other responses served to site visitors on production sites, branch deploys, or Deploy Previews. * outgoing data sent by your sites in [proxied API requests](/routing/redirects/rewrites-proxies/#proxy-to-another-service) , including requests to Netlify Functions. If your team uses [Netlify Connect](/connect/overview) , the bandwidth used by your data layers is also factored into your team’s bandwidth usage calculation. You can review the split of total bandwidth usage by sites and data layers by selecting the information icon (labeled “More information” for screen readers) in the **Bandwidth** widget on your team’s **Sites** page. ![](/images/accounts-and-billing-bandwidth-usage-split.png) For even more bandwidth details, select the **Bandwidth** widget to expand its details or review the **Accounts usage insights** section for your team at **Billing \> Account usage insights** . Bandwidth metering does _not_ include: * any data transferred as part of a site build or deploy. * form submissions or other incoming data. Need help reducing bandwidth? Visit our Forums for a verified Support Guide on [How to reduce your site’s bandwidth usage (without reducing traffic!)](https://answers.netlify.com/t/support-guide-how-to-reduce-your-sites-bandwidth-usage-without-reducing-traffic/42768) . ### [#](#builds-usage) Builds usage Netlify tracks builds usage at the team level. Each team [plan](https://www.netlify.com/pricing/) includes a number of concurrent builds and monthly allotment of build minutes. These plan features affect builds as follows: * **Build capacity.** Builds will begin as soon as possible, as supported by the concurrent build allotment for your team. If you are using all of your available concurrent build containers at once, subsequent builds will be queued until a build container is made available. * **Build minutes.** As builds are created and run, your account will accrue build minute usage. Build minutes include the time it takes for Netlify to execute the directives in your build scripts and deploy your build. They are accrued whether builds succeed or fail. You can find basic information about your team’s build minute usage under **Billing \> Current services \> Plan details** . More detailed information, including usage for the previous billing period as well as current build capacity status, is available on your team’s [**Builds** page](/monitor-sites/monitor-builds/) . You can also find more detailed builds usage information on your team’s **Sites** page and on your team’s billing page under **Billing \> Account usage insights** . Allowances for both concurrent builds and build minutes can be increased. To increase team build capacity, select the **Manage build capacity** button on the **Builds** page. Build minute usage above the plan’s allotment is charged in extra usage packages as described on our [pricing page](https://www.netlify.com/pricing/?category=developer#features-build-minutes) . Tip You have the option to temporarily [stop builds](/configure-builds/stop-or-activate-builds/) on a site to prevent further build minute usage. ### [#](#edge-functions-usage) Edge Functions usage Netlify tracks Edge Functions usage at the team level. Each team plan includes a monthly invocation allotment, and usage above the allotment is charged in extra usage packages as described on our [pricing page](https://www.netlify.com/pricing/?category=developer#features-edge-functions) . To check your Edge Functions usage in this billing period, go to **Billing \> Current services \> Plan details** . [#](#site-add-on-levels-and-usage) Site add-on levels and usage ---------------------------------------------------------------- You can find a list of all of a site’s enabled [add-ons](https://www.netlify.com/pricing/) under **Site configuration \> General \> Site details \> Add-ons** . Selecting an add-on from the list will direct you to the usage and settings panel for that add-on. Select the **Change level** button to change the level of the add-on. To check fees and usage for all of a team’s enabled site add-ons, go to **Billing \> Current services \> Site add-ons with fees** and select **All site add-ons** in the menu. Selecting an add-on from the list will reveal a breakdown of level changes and extra usage packages for the current billing period, if applicable, and a link to the add-on’s settings. ![](/images/accounts-and-billing-site-add-ons.png) Metered add-ons are automatically upgraded based on usage. Note that you cannot downgrade an add-on during a billing period where your usage exceeds the limits of the lower add-on level. [#](#domain-registrations) Domain registrations ------------------------------------------------ To review domain purchases and renewals charged in the current billing period, go to **Billing \> Current services \> Domain registrations** . For more information on domain registrations, including how you can disable auto-renewal, visit our doc on [domain renewal and expiration](/domains-https/netlify-dns/domain-registration/#domain-renewal-and-expiration) . [#](#change-billing-information) Change billing information ------------------------------------------------------------ To change the billing information for a team, select the team in the navigation, then select **Billing \> Billing details** . ![](/images/accounts-and-billing-billing-information.png) The team billing details include the following editable settings: * **Payment method:** all charges for domain registrations, add-ons, and plan subscriptions assigned to the team are charged to this payment method. * **Name:** name that appears on billing emails and receipts. * **Email:** all billing communications and receipts are sent to this email address. * **Details:** field you may use for your own internal recordkeeping. The value of this field appears at the top of all receipts. ![](/images/accounts-and-billing-add-payment-information.png) 3-D Secure authentication When editing a payment method, you may be asked to complete an additional 3-D Secure authentication step to verify your identity with your card’s issuing bank. Only **Owners** and **Billing Admins** can make changes to billing information. For more information about team member permissions, check the [team roles documentation](/accounts-and-billing/team-management/roles-and-permissions/) . To regenerate existing invoice receipts with updated billing information, such as VAT details, please [contact support](https://www.netlify.com/support/) . If you would like to make changes to billing information for an organization, please [contact sales](https://www.netlify.com/contact/) . [#](#payment-history) Payment history -------------------------------------- You can find a list of all previous payments under **Billing \> Invoices \> Paid invoice receipts** . ![](/images/accounts-and-billing-payment-history.png) Organization Owners can access their organization’s payment history by going to **Organization overview \> Billing \> Invoices** . Each paid invoice receipt has a link to download the receipt as a PDF. [#](#overdue-accounts) Overdue accounts ---------------------------------------- If payment for a team account is overdue, its service will be shut off in stages. We’ll post notifications in the Netlify UI and to the team’s [billing email](/accounts-and-billing/billing/#change-billing-information) . To restore full service, use the link in the email or UI banner to provide a valid payment method for the team. For itemized statements of overdue service charges, go to **Billing \> Invoices \> Overdue invoices** . Here’s a timeline of what happens with overdue accounts: 1. An account becomes overdue if payment is not made at the end of a team’s billing period. * This may happen because the team does not have a payment method set up or because the provided credit card details are no longer valid. * We will send notice, through daily emails and a banner in the web UI, that the team account is overdue. * We will retry processing the required payment once per day and also immediately after an update to the team payment method. 2. After two weeks of non-payment, the team account will be restricted. * Team members will no longer be able to take administrative actions like adding a new site or changing site configuration. * API PUT/POST/DELETE requests will fail with “Access denied”. 3. After four weeks of non-payment, the team account and all of its sites will be suspended. * The only allowed action will be to update the team payment method. * When people try to load a site belonging to the team, they will visit a page that says the site has been suspended. * We will stop sending daily emails prompting for payment. The web UI will continue to show a banner message. * The team account will no longer incur new charges beyond the overdue amount. 4. After eight weeks of non-payment, the team account will be canceled. * Team members will no longer be able to log in to the Netlify UI. A Team Owner or Billing Admin can restore full service at any time by providing a valid payment method for the team, unless the team account has been canceled. If the account has been canceled, you will need to [contact support](https://www.netlify.com/support/) . Last updated: December 2, 2024 [Billing FAQ](/accounts-and-billing/billing-faq/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Billing FAQ | Netlify Docs This page answers frequently asked questions about Netlify billing. Visit our [billing page](/accounts-and-billing/billing/) for instructions on how to change your billing information, access payment history, and more. If you have questions that aren’t answered by the docs, you can visit our Support Forums to ask questions about [pricing and plans](https://answers.netlify.com/t/pricing-and-plans/257) . Enterprise plan questions? If you have an Enterprise plan, we recommend reaching out to your [account manager](https://www.netlify.com/support/) for the latest and most accurate billing information for your plan. If you’re interested in an Enterprise plan, contact our [Sales team](https://www.netlify.com/contact/) . [#](#how-does-team-membership-affect-billing) How does team membership affect billing? --------------------------------------------------------------------------------------- The Team Owner is billed based on the number of active members, your [team plan’s](https://www.netlify.com/pricing/) member limit, and your team’s usage. Teams will not be charged for [Reviewers](/accounts-and-billing/team-management/roles-and-permissions/#reviewer) using collaborative Deploy Previews. Netlify will send a notification email to Team Owners when teams approach the member limit for their current team plan. ### [#](#git-contributors-and-billing) Git Contributors and billing You will only be charged for Git Contributors if you are on a [Core Pro or Enterprise plan](https://www.netlify.com/pricing/) . Once a [Git Contributor](/accounts-and-billing/team-management/roles-and-permissions/#git-contributor) is added to your team manually or through [the auto-approval setting](/site-deploys/overview/#enable-auto-approval-for-deploy-requests) , they will contribute to your total member count and will be added to your bill. Visit our documentation on [deploy permissions](/site-deploys/overview/#deploy-permissions) for more information. Team Owners are only charged for Git Contributors who have triggered a deploy during your team’s billing period. [#](#how-do-metered-features-work) How do metered features work? ----------------------------------------------------------------- For paid plans, metered features are priced based on your usage. When a site’s usage of a metered feature reaches the limit of the current level, it triggers an automatic upgrade to the next level, or purchase of an extra usage package. (Refer to the [pricing page](https://www.netlify.com/pricing/) for details on which usage thresholds trigger which type of upgrade or purchase.) ### [#](#free-tier-limits) Free tier limits Accounts on the free tier also have metered features, but they work differently than paid plans. You will receive email notifications when your site usage is approaching the free tier limits. Notifications are sent when your usage is at 50%, 75%, 90%, and 100% to the limit. If the build limit is reached, your sites will still be served to visitors, but new builds will be disabled for **all sites on your account**. For all other metered features, 100% of the limit, new builds will be disabled and **all sites on your account** will be suspended. You will need to add a payment method and upgrade to a paid plan to restore the account and your sites. Note that deleting the site with overages will not restore the account. Once a limit is reached on the free tier, the account must be upgraded to restore service. The free tier limits for each feature are listed on the [pricing page](https://www.netlify.com/pricing/) . [#](#what-s-an-extra-usage-package) What’s an extra usage package? ------------------------------------------------------------------- With metered features on paid plans, some usage thresholds trigger an automatic upgrade to the next level, and others trigger purchase of an extra usage package. (Refer to the [pricing page](https://www.netlify.com/pricing/) for details.) Extra usage packages increase your allowance for all metered features in the package — including ones that are still below their limit. Multiple packages can be added in a single billing period as package limits are reached. They are one-time purchases, meaning they will not be prorated, and will not be added in the next billing period unless usage in that month requires it. Free tier accounts [do not have extra usage packages](#free-tier-limits) . [#](#when-will-i-be-charged) When will I be charged? ----------------------------------------------------- For teams linked to an organization, Netlify billing runs on a monthly cycle which starts on the day the [organization](/accounts-and-billing/organization-management) was created. To find the billing dates for your organization, Organization Owners can go to **Organization overview** and check the billing period dates. For teams that aren’t linked to an organization, billing runs on a monthly cycle starting on the day you create your team. Billing period dates for specific teams can be found on the team’s **Billing page** and on the team’s **Sites** page. Different payment timing patterns apply to our products as described below: * **Charged annually:** payment timing pattern that applies to domain registrations, which renew on a yearly cycle. Registration fees are charged to the team payment method immediately on purchase or renewal. * **Charged monthly, in advance:** payment timing pattern that applies to [team plans](https://www.netlify.com/pricing/) , team member seats, extra concurrent builds, and [Site Analytics](https://www.netlify.com/pricing/) . Recurring fees are charged in a combined payment on the billing date to cover future usage in the new billing cycle that has just started. When you add a team plan or Site Analytics, fees for the first month are prorated for the number of days left in the billing cycle and charged immediately to the team payment method. When you add team member seats or extra concurrent builds, fees for the first month are prorated for the number of days left in the billing cycle and charged on the next billing date. * **Charged monthly, in arrears:** payment timing pattern that applies to [site add-on level upgrades](https://www.netlify.com/pricing/) (excluding Site Analytics). Fees are charged in a combined payment on the billing date to cover past usage in the old billing cycle that has just ended. Prices are prorated for the number of days at a given level. * **Charged once per purchase:** payment timing pattern that applies to [extra usage packages](/accounts-and-billing/billing-faq/#what-s-an-extra-usage-package) for bandwidth, build minutes, edge functions, and site add-ons. Each package purchase is applied to a running balance for the team and combined in a single payment at the end of the billing cycle. These one-time purchases are not prorated. [#](#are-charges-prorated) Are charges prorated? ------------------------------------------------- We prorate team plan, extra capacity, and add-on level fees based on the number of days with that plan, team member seat count, extra concurrent build count, or level in the current billing cycle. This can happen in the following situations: * Usage-triggered automatic level upgrade for a site add-on * Manual upgrade of a team plan or site add-on level * Manual downgrade of a team plan or site add-on level * Addition or removal of a team member seat * Addition or removal of an extra concurrent build Note When usage triggers an add-on level upgrade, the site add-on will remain at the higher level at the start of the next billing cycle. For items [charged monthly in advance](/accounts-and-billing/billing-faq/#when-will-i-be-charged) , downgrading or removing the item mid-cycle results in a prorated credit applied to any other charges in the invoice. For team plan downgrades and Site Analytics removals, the invoice is processed immediately. For extra capacity reductions, the invoice is processed on the next billing date. Extra usage packages are one-time purchases and are neither prorated nor carried to the next billing cycle. [#](#why-can-t-i-downgrade-my-add-on-level) Why can’t I downgrade my add-on level? ----------------------------------------------------------------------------------- You cannot downgrade to a lower level for a metered feature if your current usage is above the limits of the lower level. If you wait until the start of the next billing cycle, you can downgrade the add-on level before usage reaches the lower level limits. Remember that if site usage does pass a level limit, it will automatically upgrade back to the higher level. This does not apply to free tier accounts, which do not have add-on levels. [Learn more about free tier limits](#free-tier-limits) . [#](#how-will-i-know-when-metered-feature-usage-has-passed-the-level-limit) How will I know when metered feature usage has passed the level limit? --------------------------------------------------------------------------------------------------------------------------------------------------- You can check a site’s usage of an add-on by going to the configuration page for that add-on. For example, you can find Functions usage at **Site configuration \> Functions** . You can check the usage of all site add-ons across a team by going to **Billing \> Current services \> Site add-ons with fees** and selecting **All site add-ons** in the menu. You can find your team’s usage of bandwidth, build minutes, and edge functions under **Billing** . You can also find bandwidth and build minutes usage on your team’s **Sites** page. Learn more about these options in our [team plans and usage docs](/accounts-and-billing/billing/#team-plans-and-usage) . More detailed information about [build minutes used](/monitor-sites/monitor-builds/#historical-insights) , including a chart of the sites that have accrued the most build time, is available under **Builds \> Usage & insights** . Organization Owners can monitor usage for all of the teams linked to their organization on the **Organization overview**. For teams on a Core Starter or Core Pro plan, we also send notification emails when metered feature usage is approaching the limit of the current level, and when it triggers an upgrade or extra usage package. [#](#when-will-i-receive-notifications-about-my-usage) When will I receive notifications about my usage? --------------------------------------------------------------------------------------------------------- For free tier accounts, you will begin receiving notification emails when your site usage reaches 50%. [Learn more about free tier limits](#free-tier-limits) . If your team is on a Core Starter or Core Pro plan, Netlify will send usage notification emails to your team’s [billing email](/accounts-and-billing/billing/#change-billing-information) . Netlify sends a notification email when any site add-on is enabled, as usage for a metered feature approaches allowance limits, when usage triggers a level upgrade or extra usage package, and when the team payment method is charged at the end of the billing cycle. Below is an example of the notifications sent at different stages of usage. * **New service enabled:** * You add a form to a site and form detection is enabled. Netlify sends a notification email that the site is now on Forms Level 0, which includes 100 form submissions per month and 10 MB of uploaded files per month. * **Usage is approaching the Level 0 limit:** * The site reaches 50 form submissions a week later. Netlify sends a notification that form submissions are at 50% of the Forms Level 0 submissions limit. * The site reaches 75 form submissions a few days later. Netlify sends a notification that form submissions are now at 75% of the Forms Level 0 submissions limit. * The site reaches 90 form submissions the next day. Netlify sends a notification that form submissions are now at 90% of the Forms Level 0 submissions limit. * **Usage triggers a level upgrade:** * The site reaches 100 form submissions halfway through the first month. This triggers an upgrade to Forms Level 1, increasing the allowance to 1000 submissions and 1GB of uploads. Netlify will send a notification email, but the team payment method will not be charged until the end of the billing cycle. * **Usage is approaching the Level 1 limit:** * The site has a sudden spike in traffic and reaches 500 submissions a few days later. Netlify sends a notification that form submissions are now at 50% of the Forms Level 1 limit. * The traffic spike continues and reaches 750 submissions a couple of days later. Netlify sends a notification that form submissions are now at 75% of the Forms Level 1 limit. * The site reaches 900 submissions the next day. Netlify sends a notification that form submissions are now at 90% of the Forms Level 1 limit. * **Usage triggers an extra usage package:** * The site reaches 1000 submissions the next day. Netlify adds an extra usage package to the site, which adds 500 submissions and 500 MB of uploads to that site’s monthly allowance. Netlify sends an email confirming this purchase, but the team payment method won’t be charged yet. * **Billing cycle ends:** * At the end of the billing period, the team payment method is charged a single amount including a prorated charge for Forms Level 1 (because the site was at Forms Level 1 for only half the month), plus one extra usage package. Netlify will email a receipt. * The following month, the site continues on Forms Level 1. Netlify will send the first usage notification email when the site reaches 50% of the Forms Level 1 limits (500 form submissions or 500 MB of file uploads). [#](#can-i-set-a-limit-on-my-usage) Can I set a limit on my usage? ------------------------------------------------------------------- There is no way to set limits on metered feature usage, aside from not using a feature at all. For serverless functions, you can reduce usage by adding the [`durable` cache control directive](/platform/caching/#durable-directive) to allow edge nodes to share a cached response. [#](#how-can-i-make-sure-i-never-get-charged) How can I make sure I never get charged? --------------------------------------------------------------------------------------- Free tier accounts are not charged, but [have metered limits](#free-tier-limits) . For paid plans, we will send you notifications based on your usage, as described above. For details about your team’s metered usage, including bandwidth and build minutes, check out the following: * your team’s **Sites** page for a brief usage summary * the **Account usage insights** section on your team’s **Billing** page for more in-depth details Organization Owners can monitor usage details for organizations on the **Organization overview**. If you are approaching your allowance limit and want to avoid being charged, you can change your site code to remove the metered feature functionality. To prevent build minute usage from exceeding your current allowance, you can [stop builds](/configure-builds/stop-or-activate-builds/) . Remember that a sudden spike in usage may cause your site to pass the free level limit before you have a chance to change your site. [#](#what-can-i-do-if-my-site-usage-went-over-a-limit-because-of-spammers) What can I do if my site usage went over a limit because of spammers? ------------------------------------------------------------------------------------------------------------------------------------------------- We recommend taking measures to help prevent abuse of your site add-ons. For example, form submission spam can be reduced by adding a [reCAPTCHA 2 challenge](/forms/spam-filters/#recaptcha-2-challenge) and [honeypot field](/forms/spam-filters/#honeypot-field) . To help prevent bot registrations for your Identity add-on, you can require [email confirmation](/security/secure-access-to-sites/identity/registration-login/#registration-forms) for new users. [#](#what-will-happen-if-i-don-t-enter-my-credit-card) What will happen if I don’t enter my credit card? --------------------------------------------------------------------------------------------------------- You can get started with most Netlify add-ons for free without a credit card, including the features with metered pricing. When you start using a metered feature. At 100% of the limit, new builds will be disabled and **all sites on your account** will be suspended. You will need to add a payment method and upgrade to a paid plan to restore the account and your sites. [#](#what-can-i-do-if-i-ve-been-charged-the-wrong-amount) What can I do if I’ve been charged the wrong amount? --------------------------------------------------------------------------------------------------------------- If you find a problem with your billing, please contact our [support team](https://www.netlify.com/support/) and we’ll do our best to make it right! [#](#can-i-get-a-free-trial) Can I get a free trial? ----------------------------------------------------- Most paid features include a free tier of service for evaluation and smaller projects. When upgrading to a paid account, most [charges are prorated](/accounts-and-billing/billing-faq/#are-charges-prorated) . [#](#how-do-i-cancel) How do I cancel? --------------------------------------- To learn how to delete a team or delete your Netlify user, and the impact of either action, visit our Forums for a verified Support Guide on [how to cancel an account](https://answers.netlify.com/t/support-guide-how-to-cancel-an-account/10856) . [#](#what-does-legacy-mean-in-the-plan-name) What does “Legacy” mean in the plan name? --------------------------------------------------------------------------------------- Team plans labeled “(Legacy)” have pricing and allocations that are no longer available for new subscriptions. A team on a Legacy plan will continue under its existing terms for an extended grace period. All Legacy plans will be migrated to the current pricing and allocations described on the [pricing page](https://www.netlify.com/pricing/) . You can compare the terms on the pricing page with your current usage to check how your fees will change after migration. [#](#how-can-i-know-if-netlify-will-start-charging-for-a-free-service-in-the-future) How can I know if Netlify will start charging for a free service in the future? --------------------------------------------------------------------------------------------------------------------------------------------------------------------- We may find we need to change pricing to best match customer needs with company goals. Though we can’t make promises about what the future will bring, we fundamentally believe that composability is the best approach to building web projects, and we want to make it simple and free for developers everywhere to try it. That’s why our metered features have a free tier. For a general guideline, you can expect that any feature marked as “beta” will usually undergo pricing changes on release. Last updated: November 12, 2024 ← [Billing](/accounts-and-billing/billing/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Team management | Netlify Docs Teams can have multiple Netlify users as members, and your Netlify user can be a member of multiple teams. [#](#team-settings-and-information) Team settings and information ------------------------------------------------------------------ When working with sites or team settings, you can find the name of the current team in the navigation. If you are a member of more than one team, you can select the menu next to the team name and select a different team. ![](/images/accounts-and-billing-team-management-switch-teams.png) Default team If you are a member of more than one team, you can change the default team that appears on login by going to your [user settings](/accounts-and-billing/user-settings/) . Once you’ve selected a team, you can access the team’s overview, sites, [domains](/domains-https/netlify-dns/) , [members](/accounts-and-billing/team-management/manage-team-members/) , [audit log](/accounts-and-billing/team-management/team-audit-log/) , [billing](/accounts-and-billing/billing/) , and other team settings. [#](#access-or-modify-the-team-account-slug) Access or modify the team account slug ------------------------------------------------------------------------------------ Team Owners can find and edit the team’s account slug by going to **Team settings \> General \> Team details \> Team information** . The slug is an important detail to include when [requesting support](/welcome/get-help/resources-and-tips/#team-account-slug) . [#](#add-a-team-logo) Add a team logo -------------------------------------- Team Owners can upload a team logo to display on the team’s **Sites** page by going to **Team settings**. Select **Team settings \> General \> Team information \> Edit team information** , then select **Upload image**. After uploading your image, select **Save**. ### [#](#logo-image-guidelines) Logo image guidelines * Maximum file size: 1 MB * Supported file formats: PNG, GIF, JPEG (.jpeg and .jpg), WebP * Resolution: There are no resolution or aspect ratio restrictions. Images will be resized and cropped as needed to fit the display area. Images will maintain their aspect ratios when being resized. Cropping may be horizontal or vertical but never both. The size of the image on the team’s **Sites** page will be 230 pixels wide by 230 pixels tall. [#](#team-summary) Team summary -------------------------------- From your team’s **Sites** page, you’ll find: * a list of your team’s sites * summary of your team’s usage metrics * team member counts for all of your team’s sites ### [#](#team-usage-metrics) Team usage metrics To monitor usage of metered features, you can find the current amount of **Bandwidth** used by your team as well as how much bandwidth is available. This data updates daily. You can monitor team sites that use the most bandwidth. To review the [top bandwidth usage](/accounts-and-billing/billing/#bandwidth-usage) , go to **Billing \> Current services \> Plan details** . Learn more about these options in our [bandwidth usage docs](/accounts-and-billing/billing/#bandwidth-usage) . You can also find the number of **Build minutes** used out of your team’s total monthly allotment, updated every hour. You will need to refresh your browser to load the updated **Bandwidth** and **Build minutes** used data. Use **Concurrent builds** to gauge how much of your team’s capacity for concurrent builds is being used across all of the sites in your team in real-time. Owners and Billing Admins can access additional team usage information under **Billing \> Account usage insights** . Learn more about [usage and insights](/accounts-and-billing/billing/#usage-and-insights) . ### [#](#recent-activity) Recent activity The **Audit log** lists the latest actions made by members of your team so you can monitor what changes are being made, when, and by whom. In the **Members** list you can find recently added team members, or you can add a new member by selecting **Add members**. You can also find a list of your recently updated **Sites**, and you can create a new site by selecting **Add new site**. The list of latest **Builds** is updated every minute and displays the current build state such as completed, building, or failed. [#](#create-a-new-team) Create a new team ------------------------------------------ To create a new team, select the menu next to the team name in the navigation and then select **Create new team**. ![](/images/accounts-and-billing-team-switcher-on-nav@2x.png) Choose a name for the new team, then pick a plan. (For more details on plan features, visit the [pricing](https://www.netlify.com/pricing/) page.) Review your team information, enter your payment information, and select **Create team**. [#](#transfer-team-ownership) Transfer team ownership ------------------------------------------------------ As the Owner of a team, you can add one or more additional Owners and then remove or demote yourself using the following directions. Multiple Team Owners aren’t available on all [plans](https://www.netlify.com/pricing#features-multiple-owners) . If your plan doesn’t allow multiple Owners, [contact support](https://www.netlify.com/support/) for assistance instead. 1. To make an existing member an Owner, [change the team member’s permissions](/accounts-and-billing/team-management/manage-team-members/#change-a-team-member-s-permissions) to the Owner role. Or, [add a team member](/accounts-and-billing/team-management/manage-team-members/#add-new-team-members) with the Owner role. 2. On the **Members** page for your team, select **Options \> Remove from team** or **Options \> Edit member** to remove yourself or change your role. Last updated: November 29, 2024 ← [User settings](/accounts-and-billing/user-settings/) [Manage team members](/accounts-and-billing/team-management/manage-team-members/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage team members | Netlify Docs A list of your team’s members is available on your team’s **Members** page. [#](#add-new-team-members) Add new team members ------------------------------------------------ Team [Owners](/accounts-and-billing/team-management/roles-and-permissions/#owner) can invite new members to the team. To invite new members to the team: 1. Navigate to the **Members** page for your team. 2. Select **Add members**. 3. To add someone to your team, enter their email address. You can enter several email addresses to invite multiple people at once. Then select **Continue**. ![Interface to add team members asks for the emails of the new members.](/images/accounts-and-billing-add-members-to-team-flow@2x.png) Depending on your team [plan](https://www.netlify.com/pricing/?category=developer#features-members) , you may need to upgrade in order to add new members. For more information, please [contact sales](https://www.netlify.com/contact/) . 4. In the next step, select [permissions](/accounts-and-billing/team-management/manage-team-members/#change-team-member-permissions) for these new members. This includes selecting a [role](/accounts-and-billing/team-management/roles-and-permissions/) and site access, if applicable. 5. Select **Send invite** to invite the new members to your team. [#](#invite-reviewers) Invite Reviewers ---------------------------------------- Team Owners can also invite an unlimited number of [Reviewers](/accounts-and-billing/team-management/roles-and-permissions/#reviewer) to their team for free by using the [collaboration tools in their Deploy Previews](/site-deploys/deploy-previews/#collaborative-deploy-previews) . To add Reviewers to a team: 1. Go to a Deploy Preview URL for one of the team’s sites and select the **Team Members** tab in the Netlify Drawer. 2. Select **Add members** and enter the email address of the person you want to add to your team. [#](#change-team-member-permissions) Change team member permissions -------------------------------------------------------------------- If you’re a Team Owner, you can change a team member’s permissions from the **Team members** list on your team’s **Members** page. Team member permissions include changing a team member’s role or modifying their team site access. If a team member is provisioned by your organization’s [Directory Sync](/security/secure-netlify-access/directory-sync/) , Organization Owners can change that team member's role by [editing their directory group mapping](/security/secure-netlify-access/directory-sync/#change-the-user-role-for-a-directory-group) . ### [#](#change-team-member-roles) Change team member roles To change someone’s [role](/accounts-and-billing/team-management/roles-and-permissions) : 1. Select **Options \> Edit member** from the **Team members** list. ![Owners can use the "Options" menu to remove or edit a member.](/images/accounts-and-billing-edit-member.png) 2. Select a new role from the dropdown list. Visit our [team member roles](/accounts-and-billing/team-management/roles-and-permissions) docs for more information on the available roles. 3. Select **Update permissions**. ### [#](#manage-site-member-access) Manage site member access Owners can allow Developers to work on all sites within the team, or only on specific sites. The **Team members** list indicates whether a member has access to all sites or only specific sites. Owners always have access to all sites within the team. The **Reviewers** list shows the free users who can collaborate on Deploy Previews. Reviewers always have permission to collaborate on all sites within the team. To find out which members can access a particular site, go to **Sites**, select the site, and visit **Site configuration \> General \> Site members** . To change a member’s access: 1. Select **Options \> Edit member** from the **Team members** list. 2. Select whether you would like the member to be able to access **All sites**, or only **Specific sites**. * **All sites** includes any future sites that the team creates. * If you select **Specific sites**, use the list provided to select the sites the member should have access to. ![Owners can select the specific sites that a team member can access.](/images/accounts-and-billing-edit-member-site-access@2x.png) 3. Select **Update permissions**. ### [#](#approve-or-block-reviewers) Approve or block reviewers Pending Reviewers must be approved by a Team Owner or Developer before they can [collaborate on Deploy Previews](/site-deploys/deploy-previews/#collaborative-deploy-previews) . To approve a Reviewer: 1. Go to the **Reviewers** section of the **Members** list. The **Reviewers** list indicates whether a Reviewer is pending or approved. 2. Select **Options \> Approve reviewer** . To block a Reviewer: 1. Go to the **Reviewers** section of the **Members** list. 2. Select **Options \> Block** to remove a pending Reviewer from the **Reviewers** list and block any future Reviewer requests with the associated email address. Reviewers have access to certain collaboration features to provide feedback, while Developers and Owners have extended capabilities to manage feedback and troubleshoot reported issues. When a Developer or Reviewer is added to a site, they are granted team-wide access for collaborating on Deploy Previews. [#](#remove-a-team-member) Remove a team member ------------------------------------------------ To remove a team member, select **Options \> Remove from team** . You can also use this option to remove yourself from a team. Note that every team must have at least one Owner. As an Owner, you cannot remove or demote yourself unless there is an additional Owner on the team. [#](#delete-inactive-git-contributors) Delete inactive Git Contributors ------------------------------------------------------------------------ On the **Members** page for your team, you can access a list of your active and inactive [Git Contributors](/accounts-and-billing/team-management/roles-and-permissions/#git-contributor) . To remove an inactive Git Contributor, choose the Git Contributor you would like to remove and select **Options \> Delete contributor** . Note that deleting the Git Contributor does not automatically remove the user from the associated Git repository. Unless you remove them from the repository, the user can still trigger a build. [Team member roles](/accounts-and-billing/team-management/roles-and-permissions) Last updated: September 19, 2024 ← [Team management](/accounts-and-billing/team-management/) [Team member roles](/accounts-and-billing/team-management/roles-and-permissions/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # AI-Assisted Publishing | Netlify Docs Netlify AI-Assisted Publishing is a feature that uses AI to convert unstructured content into your site’s content schema. It enables editors to work wherever they are, and seamlessly convert that content into a structure your site is configured to use. Private Beta AI-Assisted Publishing is currently in private beta. Learn more about the feature and how to get access. * [Learn more](https://www.netlify.com/ai-assisted-publishing-private-beta/) Last updated: October 2, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Organization management | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Monitor all of your organization’s teams from your organization overview dashboard. Track metered feature usage, review billing, and streamline user authentication and provisioning with [Organization SSO](/security/secure-netlify-access/configure-organization-saml-sso/) or [SCIM Directory Sync](/security/secure-netlify-access/directory-sync/) . Organization Owners have access to the **Organization overview**, and have the [Team Owner role](/accounts-and-billing/team-management/roles-and-permissions/#owner) by default for all teams linked to their organization. [#](#organization-settings-and-information) Organization settings and information ---------------------------------------------------------------------------------- Organization Owners can access information about the organization’s [teams](/accounts-and-billing/team-management/) , [billing](/accounts-and-billing/billing) , and other settings by selecting the organization name in the navigation and going to **Organization overview**. ![](/images/accounts-and-billing-organization-settings-and-information.png) To access a team that is not linked to an organization, select **External teams** in the list of organizations within the navigation. [#](#invite-an-organization-owner) Invite an Organization Owner ---------------------------------------------------------------- _Note that inviting Organization Owners is in [beta](/platform/release-phases/#public-beta) _. Existing Organization Owners can invite new Organization Owners. By default, you can have up to 3 Organization Owners. 1. From your **Organization Overview**, go to **Owners**. 2. Select **Invite Organization Owner**. 3. Enter an email, then select **Send invites**. Organization Owners must accept their email invite before they can access your organization in this role. To further secure access to your Organization, check out our docs on [enforcing SSO for your organization](/security/secure-netlify-access/configure-organization-saml-sso/#enforce-organization-sso) . [#](#remove-an-organization-owner) Remove an Organization Owner ---------------------------------------------------------------- _Note that removing Organization Owners is in [beta](/platform/release-phases/#public-beta) _. SCIM Directory Sync enabled? Note that if your Organization has SCIM Directory Sync enabled and you remove an Organization Owner, that user will either be completely removed from your Organization or given a new role if that’s configured through SCIM Directory Sync. At this time, SCIM Directory Sync does not support assigning the Organization Owner role. To remove a user as an Organization Owner: 1. From your **Organization Overview**, go to **Owners**. 2. Select the Organization Owner you want to remove. 3. Choose **Remove from org**. If you want to give this user a new role, you can invite the user to a team or site again. Learn more about [adding team members](/accounts-and-billing/team-management/manage-team-members/#add-new-team-members) . [#](#add-an-organization) Add an organization ---------------------------------------------- To create an organization to manage your teams, please [contact sales](https://www.netlify.com/contact/) . [#](#add-an-organization-logo) Add an organization logo -------------------------------------------------------- Organization Owners can upload an organization logo to display on the **Organization overview**. Select **Settings > Edit information**, then select **Upload image**. After uploading your image, select **Save**. ### [#](#logo-image-guidelines) Logo image guidelines When uploading a logo, the image guidelines for organizations and teams are the same. Visit the [team management](/accounts-and-billing/team-management/#logo-image-guidelines) doc for more information. [#](#organization-overview) Organization overview -------------------------------------------------- You can find basic information about your organization, including usage information and a list of your organization’s **Teams**, on your organization’s **Overview** page. ### [#](#organization-usage) Organization usage You can monitor usage across your organization, including the number of team members and how much build capacity, bandwidth, and build minutes your teams are using. To get started, go to your organization’s **Overview** page to access the **Total usage** of metered features for all of your teams. This includes the current amount of **Total bandwidth used** by your organization as well as how much bandwidth is available. This data updates daily. You can also access the number of **Total build minutes used**, which updates every hour. You will need to refresh your browser to load the updated **Total bandwidth used** and **Total build minutes used** data. To gauge how much of your organization’s capacity for concurrent builds is being used across all of your teams’ sites in real-time, use **Concurrent builds**. To monitor the different usage limits for each of your organization’s teams, go to the **Teams** list and choose a team. For details about your team’s metered usage, including bandwidth and build minutes, check out: * your team’s **Sites** page for a brief usage summary * the **Account usage insights** section on your team’s **Billing** page for more in-depth details You can monitor which sites in your organization’s teams use the most bandwidth. To compare top bandwidth usage for a team’s sites, go to **Billing \> Current services \> Plan details** . Select your team plan to access bandwidth usage details, including the **Top bandwidth per domain**. Bandwidth usage data updates in near real-time and may require a browser refresh. Owners and Billing Admins can find additional usage data for their organization’s teams under **Billing \> Account usage insights** . Learn more about [usage and insights](/accounts-and-billing/billing/#usage-and-insights) . If you want to delete your organization and its associated teams, please [contact sales](https://www.netlify.com/contact/) . [#](#create-a-new-team) Create a new team ------------------------------------------ 1. Organization Owners can create a team in two ways: * Select the menu next to the team name in the navigation and then select **Create new team**. ![](/images/accounts-and-billing-team-switcher-on-nav@2x.png) * On your **[Organization overview](/accounts-and-billing/organization-management/#organization-settings-and-information) **, in the **Teams** card, select **Create new team**. ![](/images/accounts-and-billing-org-create-team.png) 2. Choose a name for the new team and select **Create team**. Check out our [team management docs](/accounts-and-billing/team-management/) for more details on how to manage your team. ### [#](#delete-a-team) Delete a team You can only delete a team if you have more than one team in your organization. To delete a team: 1. Go to the **Team settings** for the team you want to delete. 2. Select **Danger Zone**. 3. Select **Delete team**. To delete your only team in an organization, [contact our Sales team](https://www.netlify.com/contact/) for help. [#](#organization-level-audit-logs) Organization-level audit logs ------------------------------------------------------------------ As an Organization Owner, you can access the organization-level audit log to review the [audit logs](/accounts-and-billing/team-management/team-audit-log/) for all of your teams in one place. From the **Organization overview** page, select **Audit log**. Choose a team from the list to review audit logs for that team. ![](/images/accounts-and-billing-org-audit-logs.png) Last updated: November 29, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Roles and permissions | Netlify Docs Owners can assign roles to individuals invited to a team and manage their access and permissions across the Netlify platform. [#](#overview) Overview ------------------------ A role defines a standard set of permissions that a person has by default once they are assigned that role. Since Netlify roles are optimized for cross-functional collaboration across the Netlify platform, a role can determine a person’s access to different parts of the platform. An Owner can also customize site access for certain roles. A Team Owner can manage team roles and invite or remove new members from the **Members** page in **Team Settings** unless you’ve set up [SCIM](/security/secure-netlify-access/directory-sync/) to manage access control through an identity provider. Learn more about your options to [manage a team](/accounts-and-billing/team-management/manage-team-members/) . To optimize content publishing workflows, a Team Owner, Developer, or Publisher can customize even more granular [editorial permissions](/visual-editor/editorial-permissions/) for Visual Editor. [#](#access) Access -------------------- Owners can customize site access and Visual Editor access for certain roles. Other roles have predetermined access that Owners can’t modify, such as Billing Admins who have limited access to the Netlify platform beyond reviewing and managing billing. Team Owners can access all settings, sites, and resources owned by the team. Only Organization Owners can access organization settings for [Enterprise plans](https://www.netlify.com/pricing/?category=enterprise) that have set up an organization. ### [#](#site-access) Site access An Owner can choose which sites people in these roles can access: * Developers * Publishers * Content Editors * Reviewers Git Contributors have no access to the Netlify platform beyond being able to trigger a deploy and access site preview links that appear in pull/merge requests, Slack, or other places. Git Contributors can access site preview links for Deploy Previews and branch deploys as long as the links do not require Netlify Team Login, Netlify SSO, or other forms of authentication that a Git Contributor does not have. ### [#](#visual-editor-access) Visual Editor access By default, all Developers, Publishers, and Content Editors in a team can access that team’s Visual Editor dashboard. Reviewers can access preview links from Visual Editor. Within Visual Editor workspace, Owners, Developers, and Publishers can customize more granular access to Visual Editor projects, which are sites that have Visual Editor enabled and configured. Learn more about [editorial permissions](/visual-editor/editorial-permissions/) for Visual Editor. Before a site can be edited with Visual Editor, a Team Owner or Developer must enable Visual Editor for that site and complete any necessary configuration so the site works with Visual Editor. [#](#roles-and-permissions) Roles and permissions -------------------------------------------------- _Role options vary by [plan](https://www.netlify.com/pricing/#collaborate-across-larger-teams) ._ This overview summarizes the permissions for each role. For a description of each role, check out the [roles overview](#roles) . ### [#](#standard-roles-and-permissions) Standard roles and permissions | | Owner | Developer | Billing Admin | Git Contributor | Reviewer | | --- | --- | --- | --- | --- | --- | | Create sites | **✓** | **✓** | | | | | Trigger builds (Trigger from Git/deploy from Git) | **✓** | **✓** | | **✓** | | | Access and edit site configuration | **✓** | **✓** | | | | | Collaborate using the Netlify Drawer to share feedback on preview sites | **✓** | **✓** | **✓** | | **✓** | | Change levels for site add-ons | **✓** | **✓** | | | | | Modify billing information | **✓** | | **✓** | | | | Change team plan | **✓** | | **✓** | | | | Add or remove extra concurrent builds | **✓** | | | | | | Add or remove members | **✓** | | | | | | Add and approve Reviewers | **✓** | **✓** | | | | | Modify member roles | **✓** | | | | | | Edit team settings | **✓** | | | | | | Deploy to sites from private repos | **✓** | **✓** | | **✓** | | | Install and uninstall extensions | **✓** | | | | | | Add or edit data layers in Netlify Connect | **✓** | **✓** | | | | | Delete data layers in Netlify Connect | **✓** | | | | | | Add or edit cross-references in Netlify Connect | **✓** | **✓** | | | | | Delete cross-references in Netlify Connect | **✓** | | | | | | Add, edit, or delete API tokens in Netlify Connect | **✓** | **✓** | | | | | Add or edit API scopes in Netlify Connect | **✓** | **✓** | | | | | Delete API scopes in Netlify Connect | **✓** | | | | | | Delete or transfer sites | **✓** | | | | | | Delete the team | **✓** | | | | | | Access preview site links for sharing feedback | | | | | **✓** | | Publish and manage extensions on Netlify as an author | **✓** | | | | | ### [#](#visual-editor-roles-and-permissions) Visual Editor roles and permissions These roles can access Visual Editor: * Publisher * Content Editor * Developer * Team Owner * Reviewer There are more customizable permissions available in Visual Editor. Team Owners, Developers, Publishers, and other users with the **Manage Collaborators** permission can customize editorial permissions, create and manage member groups that can be assigned to projects, and choose who can access a project in Visual Editor workspace. Note that a project is a site that you can edit with Visual Editor. Learn more about these options in [Editorial permissions](/visual-editor/editorial-permissions/) . [#](#roles) Roles ------------------ When you add a person to your team, you must assign them a role. For some roles, you must also choose which sites they can access. Netlify team roles include: * [Owners](/accounts-and-billing/team-management/roles-and-permissions/#owner) * [Developers](/accounts-and-billing/team-management/roles-and-permissions/#developer) * [Publishers](/accounts-and-billing/team-management/roles-and-permissions/#publisher) * [Content Editors](/accounts-and-billing/team-management/roles-and-permissions/#content-editor) * [Git Contributors](/accounts-and-billing/team-management/roles-and-permissions/#git-contributor) * [Reviewers](/accounts-and-billing/team-management/roles-and-permissions/#reviewer) * [Billing Admins](/accounts-and-billing/team-management/roles-and-permissions/#billing-admin) ### [#](#owner) Owner Owners can access the entire team account and are able to add or remove members, adjust settings and roles, create and delete sites, and more. If user access control is managed by [SCIM](/security/secure-netlify-access/directory-sync) through an identity provider, then an identity provider admin will be able to invite and remove members. #### [#](#team-owner) Team Owner Every team must have at least one Owner at all times and can have multiple Owners. Owners cannot remove or demote themselves unless there is at least one additional Owner on the team. A Team Owner is a paid role, which means they contribute to your [total member count](https://www.netlify.com/pricing/?category=developer#features-members) and are included on your bill. #### [#](#organization-owner) Organization Owner If you have a [Enterprise plan](https://www.netlify.com/pricing/?category=enterprise) , you have the option of setting up an Organization. Organizations can have multiple teams and are managed by one or more Organization Owner. [Organization Owners](/accounts-and-billing/organization-management/) have the Team Owner role in all teams by default. ### [#](#developer) Developer Collaborators are now Developers As a part of expanding Netlify roles, the role formerly called Collaborator is now called the Developer role. The role retains the same main permissions with some [expanded access and permissions in Visual Editor](/visual-editor/editorial-permissions/) . Learn more about this change in the [blog post](https://www.netlify.com/blog/new-roles-for-better-team-management) . Developers can manage site deploys and other site configuration needs. Team Owners can [change site access](/accounts-and-billing/team-management/manage-team-members/#manage-site-member-access) to allow Developers to work on all sites within the team, or only on specific sites. Developers with access to a site can do things like trigger builds, edit site configuration, and more. Developers can configure a site for use in Visual Editor. They can also edit, publish, and manage project collaborators in Visual Editor. Learn more about what [Developers can do in Visual Editor](/visual-editor/editorial-permissions/#definitions) . Developers can also [approve or block Reviewers](/accounts-and-billing/team-management/manage-team-members/#approve-or-block-reviewers) so Reviewers can use the [Netlify Drawer](/site-deploys/collaborate-on-deploys/) to review branch deploys or Deploy Previews. Although Developers can [remove themselves from a team](/accounts-and-billing/team-management/manage-team-members/#remove-a-team-member) , they can’t remove other members. Developers are paid roles. They contribute to your [total member count](https://www.netlify.com/pricing/?category=developer#features-members) and are included on your bill. ### [#](#publisher) Publisher A Publisher can do everything a Content Editor can do in Visual Editor but they can also publish content, schedule when to publish content, and manage Visual Editor project collaborators. Learn more about [Publishers](/visual-editor/editorial-permissions/#definitions) . ### [#](#content-editor) Content Editor A Content Editor can edit content in Visual Editor but they cannot publish content live to your site. Content editing includes drafting and saving text, managing images, managing SEO settings, and customizing layouts. Content Editors can save a version of their work for review or follow-up with a Publisher. Learn more about [Content Editors](/visual-editor/editorial-permissions/#definitions) . ### [#](#git-contributor) Git Contributor When a non-team member triggers a build, a Team Owner can choose to add them to the team as a Git Contributor. Git Contributors can trigger builds, deploys, or Deploy Previews through Netlify from a private Git repository. They do not have access to the Netlify app or your team’s Netlify workspace. If you’re a Team Owner, you can add new Git Contributors to your team [manually for each deploy request](/site-deploys/overview/#add-a-non-team-member-as-a-git-contributor) , or automatically by [enabling auto-approval](/site-deploys/overview/#enable-auto-approval-for-deploy-requests) in **Team Settings**. If you are on a [Core Pro or Enterprise plan](https://www.netlify.com/pricing/?category=developer#features-members) , you will be charged for Git Contributors who have triggered a deploy during your team’s billing period. These active Git Contributors also contribute to your [total member count](https://www.netlify.com/pricing/?category=developer#features-members) . The Members page shows a list of your team’s active and inactive Git Contributors. If a Git Contributor hasn’t collaborated on any of your team’s sites during a billing period, they will be marked as inactive and you will not be charged for them. If needed, you can [remove inactive Git Contributors](/accounts-and-billing/team-management/manage-team-members/#delete-inactive-git-contributors) from your team. Reference the [Billing FAQ](/accounts-and-billing/billing-faq/#git-contributors-and-billing) page for more details. ### [#](#reviewer) Reviewer Once a Team Owner or Developer [approves](/accounts-and-billing/team-management/manage-team-members/#approve-or-block-reviewers) a Reviewer, that person can access preview links across sites in the team so they can [share site feedback on Deploy Previews](/site-deploys/collaborate-on-deploys/) or on [branch deploys](/site-deploys/collaborate-on-deploys/#configure-the-netlify-drawer) . A Team Owner can add an unlimited number of Reviewers [to your team for free](https://www.netlify.com/pricing/?category=developer#features-reviewers) . Reviewers do not contribute to your total member count, and are not included on your bill. Reviewers can also access read-only preview links from Visual Editor. To learn how to give site feedback as a Reviewer, check out our [Reviewers quickstart](/site-deploys/netlify-reviewer-quickstart/) . ### [#](#billing-admin) Billing Admin This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Billing Admins can change the team plan and modify billing information, but do not have access to other team or site features. Last updated: October 2, 2024 ← [Manage team members](/accounts-and-billing/team-management/manage-team-members) [Team-owned sites](/accounts-and-billing/team-management/team-owned-sites/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Team audit log | Netlify Docs This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify keeps a log of actions made by members of your team so you can keep track of what changes were made, when, and by whom. You can filter the team audit log by: * **Team events**: these events apply to the entire team and may include changes to the team settings or configuration, Web Application Firewall (WAF) rule updates, [Connect](/connect/monitor-activity/#review-team-member-activity) , and team membership changes. * **Site events**: these events apply to an individual site and may include changes to site settings or configuration and integration updates. You can also sort team audit log events by the oldest and newest events. Note that the oldest events tracked for your team will vary depending on your plan, which determines your [audit log retention](https://www.netlify.com/pricing/#features-audit-logs) . Looking for a site-specific log? You can monitor actions for a specific site by accessing its [Site audit log](/monitor-sites/logs/#site-audit-log) . To access a team’s audit log, select the team in the navigation and then select **Audit log** . ![Team audit log page showing the drop-down menu in the top right with the options All events, Site events, Team events, Newest, and Oldest.](/images/accounts-and-billing-audit-log.png) Last updated: November 21, 2024 ← [Team-owned sites](/accounts-and-billing/team-management/team-owned-sites/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Team-owned sites | Netlify Docs Each Netlify site belongs to a team, even if it’s a team of one. Add labels to organize your sites. [#](#transfer-sites-between-teams) Transfer sites between teams ---------------------------------------------------------------- You can transfer any site for which you have Owner access to any team where you are an Owner or Developer. To do this, go to **Site configuration \> General \> Site information** , and select **Transfer site**. You may also choose to create a new team from this menu. Warning Transferring a site between teams may affect site members, features, or pricing. This varies depending on the current site configuration and the plans of the teams you’re transferring between, so be sure to read the in-app warnings carefully. Here are some general rules to keep in mind: * Site members who are not members of the destination team will lose access to the site. You may want to invite them to the team before transferring. * Some features and settings are restricted to specific plans. If the destination team is on a lower plan than the originating team, you will lose any settings you may have entered for the features you lose. Check the current plan for each team and compare their [features and pricing](https://www.netlify.com/pricing/?category=developer) . * Sites linked to [GitHub Enterprise server or GitLab self-managed](/git/self-hosted-git/) repositories rely on a team-level connection to your instance, and require special handling for transfer. If you need to transfer a site that’s linked to a GitHub Enterprise server or GitLab self-managed repo, [contact support](https://www.netlify.com/support/) for assistance. * Legacy Global sites use a dedicated CDN, and require special handling for transfer. If you’re considering canceling a Global site plan or transferring a Global site to a team, [contact support](https://www.netlify.com/support/) so we can guide you through the process and avoid any interruptions in service. To transfer sites between teams with no shared Owners or Developers, please [contact support](https://www.netlify.com/support/) . [#](#site-management-with-labels) Site management with labels -------------------------------------------------------------- This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. You can organize your sites using team-wide labels that are available to all team members. To use labels, go to **Site overview** , and use the button with a pencil and tag icon to manage labels for the current site. ![The button for adding labels to a site](/images/add-labels-to-site.png) Labels can be used for any purpose, such as differentiating sandbox, internal, marketing, staging, and production sites or categorizing sites by bandwidth usage or teams. ![A site label modal to add or apply labels overlaying the current site overview.](/images/add-labels-from-site-overview.png) ### [#](#all-site-labels-list) All site labels list You can also find, create, and edit all your team’s labels by navigating to **Team settings \> Site labels** . To add label names, descriptions, and colors, select **Add label** and fill in the desired details. ![A modal in the team settings for creating team-wide labels.](/images/add-labels-from-team-settings.png) ### [#](#filter-sites-by-label) Filter sites by label To filter your team‘s site list by label, select a label on one of the sites in the list. You can also filter sites by selecting **Filter by label** and choosing the appropriate label. ![Filter menu in the Sites list, which includes labels.](/images/filter-by-label.png) Last updated: September 19, 2024 ← [Team member roles](/accounts-and-billing/team-management/roles-and-permissions/) [Team audit log](/accounts-and-billing/team-management/team-audit-log/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # User settings | Netlify Docs You can access your Netlify user settings by selecting your avatar (labeled “User” for screen readers) in the Netlify UI, then selecting [**User settings**](https://app.netlify.com/user/settings) . [#](#personal-profile) Personal profile ---------------------------------------- Your profile includes your avatar, name, email, password, default team, connected Git providers, and appearance preference for the Netlify UI. ### [#](#password-requirements) Password requirements Netlify requires that the password you use to log in is at least 10 characters. ### [#](#add-a-user-avatar) Add a user avatar If you signed up for Netlify using GitHub, GitLab, or Bitbucket, then your Netlify user avatar will default to your Git provider avatar. Users can upload a custom avatar to display by going to [**User settings**](https://app.netlify.com/user/settings) . Select **User settings \> General \> Personal information \> Edit settings** , then select **Upload image**. After uploading your image, select **Save**. #### [#](#avatar-image-guidelines) Avatar image guidelines * Maximum file size: 1 MB * Supported file formats: PNG, GIF, JPEG (.jpeg and .jpg), WebP * Resolution: There are no resolution or aspect ratio restrictions. Images will be resized and cropped as needed to fit the display area. Images will maintain their aspect ratios when being resized. Cropping may be horizontal or vertical but never both. ### [#](#remove-a-user-avatar) Remove a user avatar You can remove either the avatar set by your Git provider or a custom user avatar you previously uploaded by going to [**User settings**](https://app.netlify.com/user/settings) . Select **User settings \> General \> Personal information \> Edit settings** , then select **Remove image**. Then, select **Save**. Your avatar will fallback to a [Gravatar](https://gravatar.com/) using your user email. ### [#](#connect-your-git-provider-accounts) Connect your Git provider accounts You can connect your Netlify user to one or more Git providers to make logging in and collaborating with your team easier. You can add, edit, and disconnect your Git provider accounts from **User settings \> General \> Profile \> Connected accounts** . If you signed up for Netlify using GitHub, GitLab, or Bitbucket, then your Netlify user will already be linked to that Git provider. You can connect your Netlify user to multiple Git providers. However, for log in purposes, you can’t connect two different Netlify users to the same Git provider account. You also can’t connect one Netlify user to more than one account from the same Git provider, unless you’re [matching a non-team member](/site-deploys/overview/#match-to-an-existing-team-member) with a team member’s Netlify account. Member lists at the site and team level include connected accounts for each member. ### [#](#choose-a-netlify-ui-theme) Choose a Netlify UI theme You can choose a Netlify UI theme by going to **User settings \> General \> Profile \> Appearance** . You can select a theme or have it be set by your operating system preferences. ### [#](#manage-keyboard-shortcuts) Manage keyboard shortcuts Custom keyboard shortcuts can help you get around Netlify faster. You can define keyboard shortcuts in the [Command Palette](/welcome/command-palette/) . Shortcuts are made up of one or more modifier keys, such as shift or command + any other key. [#](#enable-two-factor-authentication-2fa) Enable two-factor authentication (2FA) ---------------------------------------------------------------------------------- Secure how you access teams and organizations with two-factor authentication (2FA). From your Netlify user settings, you can set up 2FA with an authentication app. If your Netlify team has a Pro plan or higher, your Organization or Team Owner may encourage or require you to set up 2FA for your Netlify user ID through your personal user settings. Once you enable 2FA for your Netlify user ID, you’re required to enter a temporary authentication code from your authentication app to access teams or organizations connected to that user ID and email. As a fallback, you can use a backup recovery code. Example authentication apps include: * [1Password](https://1password.com/) * [Authy](https://authy.com/) * [Duo](https://duo.com/product/multi-factor-authentication-mfa/duo-mobile-app) * [Google Authenticator](https://support.google.com/accounts/answer/1066447) To enable 2FA for your Netlify user ID: 1. Choose and install an authentication app on your phone. Your company or organization may ask you to use a certain authentication app. 2. To enable 2FA for your Netlify user ID, go to **User settings \> Security \> Two-factor authentication** 3. Select **Enable two-factor authentication**, and you’ll be presented with a QR code to scan into your chosen authentication app. Alternatively, you can enter the alphanumeric code listed under **Manual entry** directly into your authentication app. In both cases, the app will then present a 6-digit authentication code to enter into the Netlify UI. ![](/images/accounts-and-billing-2fa-steps.png) 4. Enter the code and select **Next: Recovery codes**. 5. Copy or print your recovery codes so you can still access your account even if you don’t have your authentication app or phone. Your recovery codes are only presented once, so be sure to copy or print them and keep them somewhere safe before completing your setup. Note that you can only use a specific recovery code once. Keep them secret! Keep them safe! Recovery codes help prevent you from being locked out of your account if you lose your phone or otherwise can’t access your authentication app. Store them somewhere secure where you know you can find them again. 6. After saving your recovery codes, select **Finished! I saved my recovery codes.** If you need to disable two-factor authentication for your user ID, go to **User settings \> Security \> Two-factor authentication** . Select **Disable two-factor authentication**. You will need to enter a valid authentication or recovery code to complete the task. [#](#connect-with-other-applications) Connect with other applications ---------------------------------------------------------------------- Under the **Applications** section of your user settings are controls for three methods of connecting your Netlify user with other applications and services: * **OAuth applications** – If you build or use an application that accesses the Netlify API as an OAuth app, you can add it here. When you register an application, Netlify will provide a client ID and secret you can use in your application settings. * **Personal access tokens (PATs)** – You can generate these for manual authentication in shell scripts or commands that use the [Netlify CLI](/cli/get-started/#obtain-a-token-in-the-netlify-ui) or [API](/api/get-started/#authentication) . For each token you generate, you can set an expiration date to help keep your information secure. Go to **Applications \> Personal access tokens** to get started. * **Authorized applications** – When you use your Netlify user account to log in with another application, such as Netlify CLI, Netlify Support Forums, or Zapier, the application is added to this list. You can revoke authorization by selecting **Options \> Revoke access** for the application. Grant access to a team where only SSO is allowed If your team requires you to log in with [single sign-on (SSO)](/security/secure-netlify-access/configure-team-saml-sso/) , API calls to your team using your access tokens will be denied access by default. This applies to both personal access tokens and tokens from authorized applications. You can choose to grant access to the team when generating a new personal access token or authorizing an application. You must be logged in to the team with SSO to grant access to it. Each token can be granted access to only one SSO team. To grant access to multiple teams, use multiple tokens. Last updated: September 11, 2024 [Team management](/accounts-and-billing/team-management/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Ask Netlify | Netlify Docs How can I help you today? Log in to unlock If you’re having trouble logging in, need a site or DNS transfer, or are encountering fraud, [contact the support team](https://www.netlify.com/support#contact) instead. Send 0 / 300 --- # Get started with Async Workloads | Netlify Docs This page will help you get started with the Async Workloads extension. It describes how to enable the extension, write basic workloads, and send events to them. [#](#key-concepts) Key concepts -------------------------------- The Async Workloads extension turns Netlify serverless functions into durable, event-driven workloads. When you define workloads, you create serverless functions. Given this, the capabilities and limitations for serverless functions also apply to workloads. Any exceptions will be explicitly noted. Learn more about [serverless functions](/functions/overview) . An Async Workload function is similar to a [background function](/functions/get-started/#background-function) but is durable, event-driven, and offers more enhanced capabilities. The function runs asynchronously, so it will not return a [`Response` object](https://developer.mozilla.org/en-US/docs/Web/API/Response) . Instead, the client can invoke the function by sending a matching event and the workload function can run its logic and persist any state it needs. [#](#setup) Setup ------------------ To get started, install the **Async Workloads** extension for your team. After you install the extension, all sites on your team will be able to build Async Workloads functions. For teams on the Starter plan, you need to configure the extension with an Async Workloads API key. In the Netlify UI, navigate to **Site configuration \> Build & Deploy \> Async Workloads** for the site you want to configure. Select **Create a new API key** to input and save the new API key. For customers on all other plans, this step is optional as an API key is automatically generated for you at the team level upon installing the extension. Add the `@netlify/async-workloads` module to your project. This will provide the functionality and types for those using TypeScript. * Loading error: Refresh the page to access this code sample npm install @netlify/async-workloads pnpm add @netlify/async-workloads yarn add @netlify/async-workloads [#](#write-an-async-workload-function) Write an Async Workload function ------------------------------------------------------------------------ Start by adding a serverless function to your project by creating the file in [your functions directory](/functions/optional-configuration/#directory) . A function file must be written using the [JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) syntax and have a [default export](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export) with a `asyncWorkloadFn` wrapped handler. * Loading error: Refresh the page to access this code sample import { asyncWorkloadFn, AsyncWorkloadEvent, AsyncWorkloadConfig } from "@netlify/async-workloads"; export default asyncWorkloadFn((event: AsyncWorkloadEvent) => { console.log('Hello, Async Workloads!'); }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['say-hello'] }; import { asyncWorkloadFn } from "@netlify/async-workloads"; export default asyncWorkloadFn((event) => { console.log('Hello, Async Workloads!'); }); export const asyncWorkloadConfig = { events: ['say-hello'] }; This workload will be called when the `"say-hello"` event is sent by a client. Once sent, this workload will run and log the message. [#](#send-your-first-event) Send your first event -------------------------------------------------- Async Workloads provides a client library called `AsyncWorkloadsClient` that can be used to send events. The basic flow is to instantiate the client and then send the message. const client = new AsyncWorkloadsClient(); // optionally send data await client.send('EVENT_NAME', {data: {}}); Typically, Async Workload functions are triggered by other serverless endpoints that respond to user actions on a website. When this occurs, the client is instantiated and used within that serverless endpoint after other checks are performed or data is aggregated. The following example is a serverless function that can be called at the `/say-hey` route on the site. When the function is called, it will send the event to the Async Workloads system. At that point, the workload function defined above will run. * Loading error: Refresh the page to access this code sample import type {Config} from "@netlify/functions"; import { AsyncWorkloadsClient } from "@netlify/async-workloads"; export default async (req: Request) => { // do some work... authenticate the user, pull data, etc. const client = new AsyncWorkloadsClient(); await client.send('say-hello'); return new Response('', { status: 200 }); }; export const config: Config = { path: '/say-hey' } import { AsyncWorkloadsClient } from "@netlify/async-workloads"; export default async (req) => { // do some work... authenticate the user, pull data, etc. const client = new AsyncWorkloadsClient(); await client.send('say-hello'); return new Response('', { status: 200 }); }; export const config = { path: '/say-hey' } Last updated: October 22, 2024 ← [Overview](/async-workloads/overview/) [Write workloads](/async-workloads/writing-workloads/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Async Workloads overview | Netlify Docs Netlify Async Workloads is a powerful tool that enables developers to build resilient, scalable, and event-driven applications without the need to manage infrastructure and queues. With Async Workloads, complex workflows such as handling multi-step workflows, retries, and ensuring fault tolerance are simplified, allowing developers to focus on functionality rather than infrastructure management. [#](#key-features-of-async-workloads) Key features of Async Workloads: ----------------------------------------------------------------------- * **Durable execution:** handle failures automatically, retrying workloads with default or custom limits and schedules if they fail due to issues like network errors, timeouts, or third-party service outages. * **Event-based architecture:** workloads are triggered by specific events, decoupling the client from directly interacting with single entry points. This allows for more scalable, asynchronous processing of tasks. * **Multi-step workflows:** Developers can break down workloads into discrete, retryable steps. If a step succeeds, it won’t be repeated on a retry, making the process more efficient and resilient. * **Scheduling and sleeping:** workloads can represent full workflows including intervals of time between processes. Easily schedule or pause a workflow for a set amount of time based on user conditions (like sending a follow-up email 7 days into a 10-day trial). * **Simple developer experience:** developers can easily create event-driven workflows without managing any infrastructure. By using Netlify’s existing serverless platform, Async Workloads eliminates the need to provision, scale, or maintain compute resources. [#](#platform-extension) Platform extension -------------------------------------------- Async Workloads is provided as a Netlify Extension so that it can be enabled on any site and plan level. This is an exemplary showcase of the power of Netlify's composable platform and extensibility. The extension uses the serverless resources on the site to do all of its internal work with controls to adjust the frequency of the background work it performs. The system provisions serverless functions and blobs on the site to handle all internal processes. The usage of Async Workloads provisioned resources is billed as any other provisioned resources. So instead of buying, hosting, and managing a queueing system, Async Workloads uses access to the serverless functions and blobs on the site to do all of its internal work. [#](#modify-configuration) Modify configuration ------------------------------------------------ To update the Async Workloads configuration settings for your site: For team-level configuration (not available for teams using the Starter plan): 1. In the Netlify UI, navigate to the [Async Workloads extension details page](https://app.netlify.com/extensions/async-workloads) . 2. Update your configuration and then select **Save**. For site-level configuration: 1. In the Netlify UI, navigate to **Site configuration \> Build & Deploy \> Async Workloads** for the site you want to edit. 2. Update your configuration and then select **Save**. Refer to [Async Workloads configuration settings](/async-workloads/optional-configuration/) for more information. [#](#uninstall-the-extension) Uninstall the extension ------------------------------------------------------ As a Team Owner, to uninstall the Async Workloads extension: 1. In the Netlify UI, navigate to the **Extensions** page for your team. 2. Search for `Async Workloads` and select it in the search results. 3. On the details page, navigate to the **Danger zone** section, and then select **Uninstall this extension**. Last updated: October 22, 2024 [Get started with Async Workloads](/async-workloads/get-started/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Async Workload Limitations | Netlify Docs This page captures all of the unique limitations of Async Workloads that run on Netlify Functions. [#](#payload-limitations) Payload limitations ---------------------------------------------- The internal router reduces invocations when possible by batching up to 10 requests at once. Given the [6 MB limit](/functions/overview/#default-deployment-options) for Netlify functions, the data limit for Async Workload event payloads should stay under 500 KB each to allow for overhead with metadata of the system. We recommend that you use the [claim check design pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/claim-check) to avoid sending large payloads in event-driven architectures [#](#functions-configuration) Functions configuration ------------------------------------------------------ Async Workloads brings durable, event-driven architecture to Netlify functions. Under the hood, they are still serverless functions and you can set configuration inline in function code. Because the Async Workloads system will handle all event routing, do not set the `path` or `schedule` [inline configuration](/functions/get-started/?fn-language=ts#route-requests) for a serverless function. At this time, there is no way to invoke Async Workload functions directly without using the `AsyncWorkloadClient` or the router API. Given this, if you would like to invoke the workload at a specific route, create a separate serverless function or edge function and then add the `client.send()` call to invoke it. This allows for the custom path while also keeping control over the authorization and event routing with Async Workloads. Last updated: October 2, 2024 ← [Optional configuration](/async-workloads/optional-configuration/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Lifecycle of Async Workloads | Netlify Docs As an asynchronous, durable, and event-based architecture, the lifecycle of Async Workloads has more considerations than a single client/server transaction. This page will cover the lifecycle of Async Workloads. Generally, this isn’t information you need to use Async Workloads effectively but it can be important for some application design considerations. [#](#guarantees) Guarantees ---------------------------- The default nature of Async Workloads is that events are immediately processed or they are enqueued if they are scheduled for the future. The queue strategy is “first in, first out ” (FIFO) — meaning it will pick up scheduled work based on the order it is enqueued. [Priorities](/async-workloads/sending-events/#prioritized-events) can be assigned to the event upon sending it. The default priority for all events is `0` and an event can be assigned a value between `-50` and `+50`, where the higher the number is, the higher the priority. In the event that two events are scheduled for the same time, the higher priority event will be sent first. You can decide to use FIFO, explicit priorities, or mix them. If you need more than one Async Workload system to have different queue strategies, we recommend creating separate Netlify sites with Async Workloads that have different strategies applied to them. Event data and states are persisted so that the events will automatically continue processing after unexpected issues are resolved. When it comes to throughput for non-scheduled events, the Netlify serverless platform does not put a hard limit on the number of events that can be processed concurrently. It can scale to handle thousands of events concurrently. The throughput for scheduled events has autoscaling capable of handling tens of thousands of events routing concurrently. There is no hard limit, the system will attempt to handle as many events as possible for each [scheduler interval](/async-workloads/optional-configuration/#scheduler-polling-interval) . [#](#retries) Retries ---------------------- Retries are the attempts to call a specific workload function again after it was unsuccessful with the initial attempt. The default number of retries is `4`. In total, with the initial attempt plus the number of retries, the total number of attempts for a workload is `5` by default. The max retries and backoff schedule can be [configured](/async-workloads/writing-workloads/#maxRetries) per workload. **When do retries happen?** If a workload function throws an error, has a timeout, or rejects a returned promise. A retry will be attempted if there are remaining retries attempts and the thrown error was not a [ErrorDoNotRetry](/async-workloads/writing-workloads/#ErrorDoNotRetry) type. [#](#failures) Failures ------------------------ When a workload function fails to process an event that it subscribes to and all retry attempts have also failed, it will be moved into the dead-letter state. This event will stay there for a retention period and then be deleted. During this retention period, a team can inspect, modify, and/or retry these events. The default retention period for dead letters is 30 days after it was enqueued. After 30 days, the events will be automatically deleted. You can inspect the events in the site’s **Blobs** store under `async-workloads-state-dead-lettered/*` To retry these events, use the [management API](/async-workloads/lifecycle/#management-apis) to target the events you want to re-trigger. [#](#management-apis) Management APIs -------------------------------------- In addition to the functions and state that Async Workloads adds to your site for the internal logic, it also provides an API for your systems to have programmatic access to managing events. The API comes in the form of JSON endpoints and as Async Workload events. These internal events can be sent by your system and Async Workloads will process them. When using the API endpoints, the `AWL_API_KEY` must be sent in an `Authorization` header. ### [#](#deleting-events) Deleting Events Kicks off an internal Async Workload to delete events by the criteria provided. The API accepts `eventIds` and/or `states` to filter which events to delete. * `eventIds` is an array of event IDs to delete. * `states` is an array of states; events with matching states will be deleted. * Loading error: Refresh the page to access this code sample fetch('SITE_ORIGIN/.netlify/functions/async-workloads-api/events', { headers: { 'Authorization': 'Bearer AWL_API_KEY' } method: 'DELETE', body: JSON.stringify({ eventIds: [], states: [] }) }) curl --header "Authorization: Bearer AWL_API_KEY" \ --request 'DELETE' \ --data '{ "eventIds": [], "states": [] }' \ 'SITE_ORIGIN/.netlify/functions/async-workloads-api/events' import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); await client.send('awl:delete-events', { data: { eventIds: [], states: [] } }); Available states to filter by: * `processing` - events that are currently being processed by a workload function * `pending` - events that are about to be processed by a workload function * `delayed` - events that are scheduled to be processed by a workload function in the near future * `hibernating` - events that are scheduled to be processed by a workload function in the future (24 hours or more from now) * `dead-lettered` - events that have failed to process and have been moved to the dead-letter state ### [#](#retrying-failed-events) Retrying Failed Events Kicks off an internal Async Workload to retry events that are failed/dead-lettered by the criteria provided. The API accepts `eventIds` or `eventNames` to be passed to filter which events to retry. * `eventIds` is an array of event IDs to retry. * `eventNames` is an array of event names to retry. If neither `eventIds` or `eventNames` are provided, then all failed events will be retried. * Loading error: Refresh the page to access this code sample fetch('SITE_ORIGIN/.netlify/functions/async-workloads-api/failed-events', { headers: { 'Authorization': 'Bearer AWL_API_KEY' } method: 'POST', body: JSON.stringify({ eventIds: [] }) }) curl --header "Authorization: Bearer AWL_API_KEY" \ --request 'POST' \ --data '{ "eventIds": [] }' \ 'SITE_ORIGIN/.netlify/functions/async-workloads-api/failed-events' import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); await client.send('awl:retry-failed-events', { data: { eventIds: [], eventNames: [], } }); [#](#local-and-branch-lifecycle) Local and branch lifecycle ------------------------------------------------------------ In production deploy contexts, the Async Workload schedule runs continuously based on the scheduler interval. In non-production deploy contexts (dev, branch deploys, etc.), the Async Workload scheduler runs only on “stateful” actions (for example, processing or retrying events). This prevents unnecessary compute usage on environments that do not serve production traffic. Once triggered, the scheduler runs briefly and exits. This behavior cannot be disabled. [#](#event-data-storage) Event data storage -------------------------------------------- Event data, persisted results, etc. are stored exclusively as [Blobs](/blobs/overview/) on the site that hosts the Async Workloads. The data stored there is allowed to be sensitive data. To keep your data secure, Netlify encrypts blobs at rest and in transit. This data can only be accessed through your own site. You are responsible for making sure the code you use to access blobs or Async Workload data doesn’t allow data to leak. Last updated: October 2, 2024 ← [Multi-step Async Workloads](/async-workloads/multi-step-workloads/) [Optional configuration](/async-workloads/optional-configuration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Optional Configuration | Netlify Docs While the Async Workload extension is installed on the team level, there are a few site-level configurations that can be set to customize the behavior of Async Workloads. [#](#modify-your-configuration) Modify your configuration ---------------------------------------------------------- To update the Async Workloads configuration settings for your site: For team-level configuration (not available for teams using the Starter plan): 1. In the Netlify UI, navigate to the [Async Workloads extension details page](https://app.netlify.com/extensions/async-workloads) . 2. Update your configuration and then select **Save**. For site-level configuration: 1. In the Netlify UI, navigate to **Site configuration \> Build & Deploy \> Async Workloads** for the site you want to edit. 2. Update your configuration and then select **Save**. Alternatively, you can update the environment variables directly. [#](#async-workloads-api-key) Async Workloads API key ------------------------------------------------------ To ensure that only allowed clients can invoke workloads and related APIs, requests must provide an `Authorization` header with an API key that’s known by Async Workloads. When you install the Async Workloads extension, a new randomly generated API key is created on the team level. This key is used to authenticate requests to the Async Workload API. For teams on the Starter plan, you must create an API key on each of the sites that will use the Async Workloads extension. This value is persisted under the `AWL_API_KEY` and `AWL_API_KEY_P{priority_integer}` convention environment variables. ### [#](#create-and-rotate-keys) Create and rotate keys For team-level API keys, navigate to the [Async Workloads extension details page](https://app.netlify.com/extensions/async-workloads) . Select **Create a new API key** to input and save a new API key. For customers using Starter plans, this option is not available and the configurations must be managed on the site level. For site-level API keys, navigate to **Site configuration \> Build & Deploy \> Async Workloads** in the Netlify UI. Select **Create a new API key** to input and save the new API key. When you create a new API key, you must provide an **API key priority** and an **API key value**. The **API key priority** is an integer that signals the priority of an API key - the higher the number, the higher the priority. Where the system automatically uses the API keys in making requests - like the router sending events to workloads - it will use the highest priority key available. The **API key value** is the actual key that will be used for authentication. Setting multiple keys allows teams to safely rotate keys and explicitly set priority for which keys to use internally. When rotating API keys, you can create a new key that has a higher priority than the existing keys. Once all clients are using the new keys, you can delete the older, lower priority keys. Redeploy the sites that Async Workloads runs on first, then any client-only sites. To aid in the safe rotations of keys, if the system detects that a key being used is not the highest priority key, it will log a warning like `Lower priority key named "${keyName}" is being used for this request`. If these warnings are not present then there are no lower priority keys being used. To delete API keys, delete the **API key value** field contents and save the changes. This will remove the API key from the site. [#](#pending-processor-upper-limit) Pending Processor Upper Limit ------------------------------------------------------------------ The pending processor is the system that picks up scheduled events and sends them to the Async Workloads router layer. To prevent your site from consuming a large amount of resources unexpectedly, Async Workloads will determine if the quantity of pending events is above a certain threshold limit. If it is, Async Workloads sees this as a potential infinite looping system. In that case, router layer will not be sent any more events from the pending processor until the number of pending events is below the limit. This limit can be configured if it's too low or too high for your sites needs. Async Workloads will still continue to allow events to be scheduled without data loss. Only the process of taking scheduled events and sending them to the router layer is disabled. The default is `2000`. This value is persisted under the `AWL_PENDING_UPPER_LIMIT` environment variable. [#](#serverless-timeout-limit) Serverless timeout limit -------------------------------------------------------- This is the max number of seconds Async Workloads should wait for timeout detection. This only applies to standard serverless functions as background functions use a 15 minute timeout. The [default deployment options](/functions/overview/#default-deployment-options) for standard serverless functions includes a 30 second timeout. If deployment options are changed to have a higher or lower execution limit, or if timeout detection should be more aggressive for a site, this where that timeout limit can be set. This value is persisted under the `AWL_SERVERLESS_TIMEOUT` environment variable. [#](#workload-chaining-limit) Workload chaining limit ------------------------------------------------------ Workload chains happen when one workload sends an event that triggers another workload. It's possible to have one workload invoke another workload which then re-invokes the original workload - causing an infinite loop of workload events. To avoid this from causing unexpected resource consumption, there is automatic chain limit detection. The default chain limit is 20. If it is necessary to have a larger limit, this limit can be set on this configuration. This value is persisted under the `AWL_EVENT_CHAIN_LIMIT` environment variable. [#](#scheduler-polling-interval) Scheduler polling interval ------------------------------------------------------------ To run an async event queue system, there are processes that run in the background to ensure retries happen, delayed events are triggered after the delay, etc. This is achieved by running a serverless scheduler function on the site at appropriate intervals of time. Adjustments to the polling interval of the scheduler will allow it to run more or less frequently. This only impacts the production scheduler. The default value is `60` second intervals between each scheduler run. The minimum value is `10` seconds. For example, if you want to run it once every 5 minutes, you would set the value to `300`. The max value is `900` or 15 minutes. Values greater than `60` are rounded to the nearest minute. ### [#](#which-interval-is-best) Which interval is best? The more events that are expected to be delayed, errored, etc. the lower the interval should be to process them promptly. The recommendation is to start with the default and use the function logs and stored state, to determine if the interval should be changed to process delayed events more or less often. ### [#](#local-and-branch-scheduler) Local and branch scheduler In production environments, the Async Workload scheduler runs continuously on an interval. In non-production environments (dev, branch deploys, etc.), the scheduler runs only on "stateful" actions (for example, when processing or retrying events). This prevents unnecessary compute usage on environments that are not serving production traffic. Once triggered, the scheduler runs briefly and exits. This behavior cannot be disabled. This value is persisted under the `AWL_SCHEDULER_INTERVAL` environment variable. Last updated: October 22, 2024 ← [Lifecycle](/async-workloads/lifecycle/) [Limitations](/async-workloads/limitations/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with Netlify CLI | Netlify Docs Netlify’s command line interface (CLI) lets you configure [continuous deployment](#continuous-deployment) straight from the command line. You can use Netlify CLI to [run a local development server](/cli/local-development/) that you can share with others, [run a local build and plugins](#run-builds-locally) , and [deploy your site](#manual-deploys) . The sections below describe how to perform common tasks with Netlify CLI. You can also access a [full command reference](https://cli.netlify.com) online, or get help [within Netlify CLI](/cli/get-started/#get-help) . [#](#installation) Installation -------------------------------- To install Netlify CLI, make sure you have [Node.js](https://nodejs.org/en/download/) version 18.14.0 or later. Then, run this command from any directory in your terminal: npm install netlify-cli -g This installs Netlify CLI globally, so you can run `netlify` commands from any directory. You can check the version and find out some basic information about the tool with the following command: netlify Global versus local Installing Netlify CLI globally means that your system always has the latest version, including any breaking changes. While global installation is appropriate for initial development and experimentation, for managing builds in a continuous integration (CI) environment, use [local CLI installation](#installation-in-a-ci-environment) instead. ### [#](#installation-in-a-ci-environment) Installation in a CI environment When using Netlify CLI in a continuous integration (CI) environment such as GitHub Actions, CircleCI, or Travis CI, we recommend installing it locally as a development dependency instead of globally. This binds a specific CLI version to your project repository. To install Netlify CLI locally, run the following command from the root directory of your project: npm install netlify-cli --save-dev For CI environments, we also recommend using a [lock file](https://docs.npmjs.com/cli/v7/commands/npm-ci) to guarantee reproducible builds and relying on an automated tool like [renovate](https://github.com/renovatebot/renovate) or [dependabot](https://dependabot.com/) to manage Netlify CLI version updates. [#](#authentication) Authentication ------------------------------------ Netlify CLI uses an access token to authenticate with Netlify. You can obtain this token using the command line or in the Netlify UI. SAML SSO If your team requires you to log in with [single sign-on (SSO)](/security/secure-netlify-access/configure-team-saml-sso/) , your tokens will be denied access to the team by default. You can choose to grant access to the team when you obtain a new token. You must be logged in to the team with SSO to grant access to it. ### [#](#obtain-a-token-with-the-command-line) Obtain a token with the command line To authenticate and obtain an access token using the command line, enter the following command from any directory: netlify login This will open a browser window, asking you to log in with Netlify and grant access to **Netlify CLI**. ![](/images/cli-authorize-ui.png) Once authorized, Netlify CLI stores your access token in a [`config.json`](#config-json-location) global configuration file. The Netlify CLI uses the token in this file automatically for all future commands. #### [#](#config-json-location) `config.json` location You can find the Netlify CLI global configuration file, `config.json`, under your user in these OS-specific locations: * macOS: `Library/Preferences/netlify/config.json` * Linux: `.config/netlify/config.json` * Windows: `AppData\Roaming\netlify\Config\config.json` ### [#](#obtain-a-token-in-the-netlify-ui) Obtain a token in the Netlify UI You can generate a personal access token (PAT) manually in your Netlify user settings: 1. Go to **Applications \> Personal access tokens** . 2. Select **New access token**. 3. Enter a descriptive name to help you remember what the token will be used for. 4. Select **Allow access to my SAML-based Netlify team** to authorize access to your SAML-based team data through the API. 5. Select an **Expiration** date for your token to help keep your information secure. 6. Select **Generate token**. 7. Copy the token to your clipboard and store it in a safe location. Once you navigate away from this page, you won’t be able to access the value again. 8. Select **Done**. 9. Save the token as a `NETLIFY_AUTH_TOKEN` environment variable in your terminal settings or in the UI of a Continuous Integration (CI) tool. ### [#](#cancel-access-tokens) Cancel access tokens To revoke your user access token for Netlify CLI, go to your Netlify user [**Applications settings**](https://app.netlify.com/user/applications) . The procedure for revoking access depends on how access was granted. * For access granted using the `netlify login` command, scroll to the [**Authorized applications**](https://app.netlify.com/user/applications#authorized-applications) section, and find **Netlify CLI**. Select **Options \> Revoke access** . * If you manually created a [personal access token](/cli/get-started/#obtain-a-token-in-the-netlify-ui) , you can find it in the [**Personal access tokens**](https://app.netlify.com/user/applications#personal-access-tokens) section. Select **Options \> Delete personal token** . [#](#usage-data-collection) Usage data collection -------------------------------------------------- By default, Netlify collects data on usage of Netlify CLI commands. We do this to improve the reliability and performance of Netlify CLI, and to help drive new features and improvements. If you’d like to opt out of sending usage data, you can do so by editing the `telemetryDisabled` property in the Netlify CLI [`config.json`](#config-json-location) . You can also do this with the command line: # opt out of sharing usage data netlify --telemetry-disable # allow your usage to help shape development netlify --telemetry-enable [#](#continuous-deployment) Continuous deployment -------------------------------------------------- With [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) , Netlify will automatically deploy new versions of your site when you push commits to your connected Git repository. This also facilitates features like [Deploy Previews](/site-deploys/deploy-previews/) , branch deploys, and [split testing](/site-deploys/split-testing/) . (Some of these features must be enabled in the Netlify UI.) To connect your local project to an existing Netlify site, use `link` If your site already has continuous deployment set up and you just want to associate a project on your local machine to an existing site on Netlify, use [`netlify link`](#link-and-unlink-sites) instead of `netlify init` or `netlify init --manual`. ### [#](#automated-setup) Automated setup For repositories stored on GitHub.com, you can use Netlify CLI to connect your repository by running the following command from your local repository: netlify init In order to connect your repository for continuous deployment, Netlify CLI will need access to create a deploy key and a webhook on the repository. When you run the command above, you’ll be prompted to log in to your GitHub account, which will create an account-level access token. The access token will be stored in the Netlify CLI [`config.json`](#config-json-location) . Your login password will never be stored. You can revoke the access token at any time from your GitHub account settings; however, this will disable continuous deployment on all sites that were configured with that access token. ### [#](#manual-setup) Manual setup For repositories stored on GitLab, Bitbucket, or Azure DevOps, you can connect your repository manually with the `--manual` flag. For repositories on GitHub, you can also connect your repository manually, if you prefer to give more limited, repository-only access for your repositories on GitHub. From your local repository, run the following command: netlify init --manual The Netlify CLI will prompt you to set your deploy settings and then provide you with a deploy/access key and a webhook URL. You’ll need to manually add the key and webhook URL to your Git provider. #### [#](#add-your-deploy-or-access-key) Add your deploy or access key Netlify uses a deploy or access key to fetch your repository using ssh for building and deploying. The deploy key does not require write access. ![Sample terminal output reads: 'Give this Netlify SSH public key access to your repository,' and displays a key code.](/images/cli-deploy-key.png) Copy the key printed in the command line, then add it to your Git provider. * **GitHub, GitLab, or Bitbucket.** Add the deploy key to your repository’s settings. If you have more than one site connected to a repository, you will need a unique key for each repository. * **Azure DevOps.** Add the Netlify SSH public key to your Azure DevOps user settings under **SSH Public Keys**. #### [#](#add-your-webhook-url) Add your webhook URL Your Git provider will send a message to this webhook when you push changes to your repository, triggering a new deploy on Netlify. ![Sample terminal output reads: 'Configure the following webhook for your repository,' and displays a URL.](/images/cli-webhook.png) Copy the webhook address printed in the command line, then add the URL and webhook details to your Git provider. If available, the **Content type** should be set to `application/json`. * **GitHub, GitLab, or Bitbucket.** Add the webhook address as the Payload URL for a new webhook in your repository’s settings. When selecting events to trigger the webhook, **Push** events will trigger production and branch deploys on watched branches, and **Pull/Merge request** events will trigger deploy previews. * **Azure DevOps.** In your project’s settings under **Service hooks**, add webhooks for these Azure DevOps events using the Netlify webhook address as the Payload URL: * Code pushed * Pull request created * Pull request merge attempted * Pull request updated Ensure that you set webhooks for your repository with the default `[Any]` branch setting. Once configured, these webhook events can trigger production and branch deploys on your watched branches. [#](#run-a-local-development-environment) Run a local development environment ------------------------------------------------------------------------------ [Netlify Dev](https://www.netlify.com/products/dev) brings the functionality of your Netlify production environment directly to your local machine. For more information on how to configure and use Netlify Dev, refer to our [local development with Netlify Dev](/cli/local-development) doc. [#](#run-builds-locally) Run builds locally -------------------------------------------- You can run builds in Netlify CLI to mimic the behavior of running a build on Netlify — including [Build Plugins](/build-plugins/) . To execute a build locally, run the following command from the root of your linked repository: netlify build The command will build your project using [environment variables](/environment-variables/overview/) set in `netlify.toml` and those set using the Netlify UI, CLI, or API. Note that environment variables apply to all scopes when running `netlify build` locally. Make sure your Node.js versions match If you are using the Netlify CLI to run a build locally, make sure the Node.js version installed in your local environment matches the version [set for your build on Netlify](/configure-builds/manage-dependencies/#node-js-and-javascript) . If the versions don’t match, you may encounter errors. If you’d like to get a summary of what a build will do without taking the time to do a full build, you can use the `--dry` flag: netlify build --dry This command will output a list of all the stages of the build and the behaviors that are configured to run during each stage. The default deploy context is `production` but you can also use the `--context` flag to run a build for a different [deploy context](/site-deploys/overview/#deploy-contexts) . netlify build --context deploy-preview This command will run the build as if it is a Deploy Preview, applying any settings and environment variable values specific to that context. [#](#manual-deploys) Manual deploys ------------------------------------ It’s also possible to deploy a site manually, without continuous deployment. This method uploads files directly from your local project directory to your site on Netlify. If [builds are stopped](/configure-builds/stop-or-activate-builds/) , manual deploys are the only way you can update your site. A common use case for this command is when you’re using a separate Continuous Integration (CI) tool, deploying prebuilt files to Netlify at the end of the CI tool tasks. To get started with manual deploys, run the following command from your project directory: netlify deploy The first time you run the command, Netlify CLI will prompt you to select an existing site or create a new one, linking the site for all future deploys. The following sections describe the requirements and options for manual deploys. ### [#](#deploy-directories) Deploy directories The `deploy` command needs to know which folder to publish. If your project includes serverless functions, it needs to know the location of the [functions folder](/functions/optional-configuration/#directory) as well. Netlify CLI will look for this information in three places, in the following order: * in [flags](https://cli.netlify.com/deploy) specified in the command itself. * in a [netlify.toml file](/configure-builds/file-based-configuration/) stored at the root of your project directory. * in your site configuration in the Netlify UI, if continuous deployment is set up for the site. Here is an example using command flags to set the publish folder and functions folder: netlify deploy --dir=_site --functions=functions In both cases, folder paths are relative to the current directory. Note that paths starting with `/` will begin at the computer’s root directory — not the base of your project directory. ### [#](#draft-deploys) Draft deploys By default, the `deploy` command deploys to a unique _draft_ URL for previewing and testing. ![](/images/cli-draft-deploy.png) The default draft URL uses random alphanumeric characters for the subdomain. To customize the subdomain of your draft URL with a unique string, use the `--alias` flag with the `deploy` command. netlify deploy --alias=YOUR_ALIAS ![](/images/cli-draft-deploy-alias.png) Avoid using `--alias` with any of your branch names Ensure the string you use after `--alias=` doesn’t match any existing branch names from your site’s repository. The `--alias` flag is designed to support draft deploy URLs only and doesn’t create a [branch deploy](/site-deploys/overview/#branches-and-deploys) or support our [branch subdomains](/domains-https/custom-domains/multiple-domains/#branch-subdomains) feature. Learn more about this flag in the [CLI reference docs](https://cli.netlify.com/commands/deploy/) . To create a branch deploy, use [continuous deployment](#continuous-deployment) . ### [#](#production-deploys) Production deploys To do a _production_ deploy to your main site URL, use the `--prod` flag (or `-p` for short): netlify deploy --prod ### [#](#node-js-function-dependencies) Node.js function dependencies Before manually deploying TypeScript or JavaScript functions with Netlify CLI, populate `node_modules` folders with your dependencies by running the following command in any folder containing `package.json`. * Loading error: Refresh the page to access this code sample npm install yarn When you deploy TypeScript or JavaScript functions using the `netlify deploy` command, Netlify CLI parses each function file to note its dependencies. For each function, the CLI then pulls the required dependencies from the associated `node_modules` folder and zips them with the function file for deployment. [#](#link-and-unlink-sites) Link and unlink sites -------------------------------------------------- If your site isn’t already on Netlify, use `init` or `deploy` instead If your site is not already on Netlify, you need to either set up [continuous deployment](#continuous-deployment) or [manually deploy](#manual-deploys) the site before you can link your local project to it. If you use the Netlify CLI to deploy your site, the CLI will automatically link the project on your local machine to the site on Netlify. If you want to connect your local project or repository to a site already on Netlify, you can skip the initial setup steps above and run the following command from the root of the local directory: netlify link This will add a `siteId` field to a new file inside your project folder, at `.netlify/state.json`. To unlink your folder from the site, you can remove this field, or you can run the following command from inside the project folder: netlify unlink ### [#](#link-with-an-environment-variable) Link with an environment variable Alternatively, you can link to a site by finding the site ID in the Netlify UI, then adding it to your local terminal environment: 1. Go to **Site configuration \> General \> Site details \> Site information** , and copy the value for **Site ID**. 2. Assign the ID to a `NETLIFY_SITE_ID` environment variable, in your terminal settings or in the UI of a Continuous Integration (CI) tool. [#](#manage-environment-variables) Manage environment variables ---------------------------------------------------------------- You can create and update site environment variables stored on Netlify with the CLI’s [`env` command](https://cli.netlify.com/commands/env) . Any changes made using the CLI will be reflected in the Netlify UI. Environment variable changes require a build and deploy to take effect. By default, the Netlify CLI deploy context is the [local development context](/environment-variables/overview/#value-per-deploy-context) (`dev`). Unless a different deploy context is specified, CLI commands will get and use variables that have values set specifically for use with the `dev` deploy context and variables that have a single value for use across `all` deploy contexts. Use the `--context` and `--scope` flags with your CLI commands to set contextual or scope values, or to filter results. You can use both flags in the same command, for example: netlify env:set API_KEY someValue --scope functions --context production branch-deploy netlify env:list --scope builds --context deploy-preview ### [#](#create-or-update-environment-variables) Create or update environment variables To create or update a site environment variable on Netlify, use `env:set` with the key followed by a space and then the value. You can only set one value at a time, but you can specify multiple deploy contexts and scopes in a space-separated list (no commas) using the `--context` and `--scope` flags. netlify env:set API_KEY someValue netlify env:set ANOTHER_API_KEY someValue --scope builds --context dev If you omit the `--scope` or `--context` flags when running the `env:set` command, the variable is set to all scopes and with the same value for all deploy contexts. To set one value for `production` and `deploy-preview` and another value for a branch named `staging`, run the command twice: netlify env:set API_KEY someValue --context production deploy-preview netlify env:set API_KEY someOtherValue --context branch:staging You can also import environment variables from a `.env` file into Netlify using `env:import` followed by the filename. The imported variables are set to all scopes and with the same value for all deploy contexts. netlify env:import .env To copy environment variables from one site to another, use `env:clone`. netlify env:clone --to destinationSiteId --from sourceSiteID If you are using environment variable secrets with Netlify’s [Secrets Controller](/environment-variables/secrets-controller) , you can flag that an environment variable value is secret using the `--secret` flag when creating or modifying a value. netlify env:set API_KEY someValue --context production --secret ### [#](#get-environment-variables) Get environment variables To retrieve a list of site environment variables stored on Netlify, use `env:list`. The CLI gets all variables that have values set for local development with the Netlify CLI (deploy contexts `dev` or `all`) and outputs a list of keys with an option to display their values. You can request other [contextual values](/environment-variables/overview/#value-per-deploy-context) using the `--context` flag and filter the list using the `--scope` flag. You can also use the `--json` and `--plain` flags to retrieve the list in JSON or plain text format, which can be helpful if you want to copy the values into a `.env` file locally. The list will only include shared environment variables if the command is run by a Team Owner. This list will not include raw, unmasked values of any environment variables marked as secret unless the `--context` is `dev`. Review the [environment variable secrets](/environment-variables/secrets-controller/#environment-variable-secrets-policy) policy for more details on the access restrictions. netlify env:list netlify env:list --context branch:staging netlify env:list --scope functions netlify env:list --plain To retrieve an individual environment variable’s value, use `env:get`. The CLI gets the values set for local development with the Netlify CLI (deploy contexts `dev` or `all`). You can use the `--context` flag to retrieve a value from another context or the `--scope` flag to retrieve a value only if the variable is available to a specific scope. netlify env:get API_KEY netlify env:get API_KEY --context production ### [#](#delete-environment-variables) Delete environment variables To delete environment variables from Netlify, use `env:unset`. This command deletes the specified variable and its values from all deploy contexts. Once unset, these variables will no longer be stored on Netlify or appear in the UI. You can use the `--context` flag to delete one value from a specific deploy context instead. netlify env:unset API_KEY netlify env:unset API_KEY --context dev [#](#work-with-monorepos) Work with monorepos ---------------------------------------------- Commands execute from the workspace root Starting with Netlify CLI version 16, all commands execute from the workspace root to mimic the build system behavior on Netlify. The workspace root is the directory that contains the highest-level `package.json` in your monorepo. Make sure any paths declared in `netlify.toml` are absolute paths relative to the [base directory](/configure-builds/overview/#definitions) . A monorepo is a repository that contains multiple sites or apps, each in its own subdirectory. When you use the Netlify CLI, Netlify automatically scans the repository to detect if you are using a monorepo. If you are, the Netlify CLI will ask you to specify the site to run a command on and you can choose from the list of detected sites. ![](/images/cli-get-started-monorepos-select.png) You also have the option to manually set the following flag: * `--filter`: to specify which site in your monorepo to use for a command. You can use the package name or the path to the package. This way you can run commands directly from the repository root for all projects in your monorepo. netlify dev --filter website netlify dev --filter packages/website Note that selecting a site with the Netlify CLI only applies to the command you are running and doesn’t influence the [build settings](/configure-builds/overview/) in the Netlify UI. Learn more about how to set up a site from a [monorepo](/configure-builds/monorepos/) . [#](#print-debugging-output) Print debugging output ---------------------------------------------------- To print the full debugging output for a command to the terminal, set the `DEBUG` variable before running the command. On Mac OS, Linux, and some common Windows terminals, add `DEBUG=*` to the beginning of the command: DEBUG=* netlify deploy If you are using the Windows command prompt (cmd.exe), use `set` to set the variable: set DEBUG=* & netlify deploy In Windows PowerShell, use `$env:` to set the variable: $env:DEBUG='*';netlify deploy [#](#get-help) Get help ------------------------ To get usage tips and learn more about available commands from within Netlify CLI, run the following: netlify help For more information about a specific command, run `help` with the name of the command. netlify help deploy This also works for sub-commands. netlify help sites:create If you have additional questions or ideas for new features, you can [start an issue](https://github.com/netlify/cli/issues) on Netlify CLI’s open source repository. You can also visit our [Support Forums](https://answers.netlify.com/categories) to start or join a conversation. We’d love to hear from you! [Local development with Netlify Dev: Get started with Netlify Dev](/cli/local-development/#get-started-with-netlify-dev) [Local development with Netlify Dev: Share a live development server](/cli/local-development/#share-a-live-development-server) [Local development with Netlify Dev: Configuration](/cli/local-development/#configuration) Last updated: October 2, 2024 [Local development with Netlify CLI](/cli/local-development/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Share Build Plugins | Netlify Docs If you’d like to share your plugin with others, you can [publish it to npm](#publish-to-npm) . All Netlify Build Plugins in the [npm Public Registry](https://npmjs.com) can be installed by any Netlify user through [file-based installation](/build-plugins/#file-based-installation) . [#](#publish-to-npm) Publish to npm ------------------------------------ To publish a Build Plugin to npm, follow npm’s documentation for [contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) . Be sure to add the following properties to your plugin’s `package.json` file: * [`name`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#name) should start with `netlify-plugin-` (such as `netlify-plugin-example` or `@scope/netlify-plugin-example`). It should match the plugin `name` field. It is recommended for the plugin repository to be named like this as well. * [`keywords`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#keywords) should contain the `netlify` and `netlify-plugin` keywords. The same applies to [GitHub topics](https://github.com/topics) . This helps users find your plugin. * [`repository`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#repository) and [`bugs`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#bugs) should be defined. Those are displayed to users when an error occurs inside your plugin. Last updated: October 2, 2024 ← [Create Build Plugins](/build-plugins/create-plugins/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Sending Async Workload events | Netlify Docs Async Workloads brings a durable, event-based architecture to Netlify functions. This means that workloads are centered around subscribing and broadcasting events. Unlike traditional client/server architecture patterns where a single URL corresponds to a specific function or logic, event-based architectures send events that could trigger many functions, and any function could correspond to many different events. This is why Async Workload functions [subscribe to events by name](/async-workloads/writing-workloads/#config-events) and why events are [sent by name](/async-workloads/sending-events/#send-eventName) . ### [#](#asyncworkloadsclient) AsyncWorkloadsClient The most common option for sending events is using the `AsyncWorkloadsClient` library. To use, ensure you have the `@netlify/async-workloads` library installed. * Loading error: Refresh the page to access this code sample npm install @netlify/async-workloads pnpm add @netlify/async-workloads yarn add @netlify/async-workloads #### [#](#client-usage-example) Client usage example To use the client library, it first needs to be instantiated with any settings and then all of the functions will use these settings in the actions they perform. import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); // sending event with no data await client.send('EVENT_NAME'); // sending event with data await client.send('EVENT_NAME', { data: { foo: true } }); You can also instantiate the client with options. import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient({ baseUrl: 'https://example.com', apiKey: '5555-555-555-5555', }); Available client options: * `baseUrl` - the origin for the site that hosts the Async Workload functions. If the site using this library is the same site that runs the Async Workloads, this field should be omitted. Otherwise, the client needs to know where to send requests to and this parameter is required. * `apiKey` - the API key used to send requests to the Async Workloads routing layer. If the site using this library is the same site that runs the Async Workloads, this field should be omitted. Otherwise, the client needs to know exactly what the API key is to send authorized requests. #### [#](#basic-events) Basic events With an instantiated client, specify the event name and any data needed. import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); const { eventId, sendStatus } = await client.send('event.first', { data: { plan: 'pro', id: '1234-abc' } }); // this event is invoked without data await client.send('event.second') Options for \`client.send(eventName, options)\`: * `eventName` (required) - the string name of this event being triggered. This is a case-insensitive field. * `options.data` (optional) - a JSON serializable value that will be passed along to subscribed Async Workload functions. * `options.delayUntil` (optional) - when this event should attempt to be fired, up to a maximum of one year from the current time. The value can be the absolute milliseconds of the future date (UTC) or the number of milliseconds to wait relative to now, or an [ms-compatible string](https://www.npmjs.com/package/@lukeed/ms) , relative to now. * `options.priority` (optional) - if this event should be processed before or after other events, specifying the priority informs when Async Workloads should process the event relative to others. Higher priority events are processed first when events are triggered at the same time. Allowed values range from `-50` to `+50`, where the default for all is `0`. This only applies to delayed functions, as all non-delayed events are immediately processed. The result from `client.send(event, options)` is an object with status and identifying details of the workload. * `eventId` - the unique identifier of this `client.send()` call. * `sendStatus` - the status of sending the event to the Async Workloads routing layer. This layer will acknowledge that the event was received or it will mark it as failed. The value will be `"succeeded"` or `"failed"`. #### [#](#scheduling-events) Scheduling events To trigger events to run in the future, the `delayUntil` field on the `client.send()` call accepts a few different patterns to suit different needs. import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); await client.send('EVENT_NAME', { // or you can use '1w', '7 days', 604_800_000 delayUntil: '1 week' }); await client.send('EVENT_NAME', { // 5 minutes relative to now delayUntil: 1000 * 60 * 5 }); await client.send('EVENT_NAME', { // exact UTC time of 30m in the future delayUntil: Date.now() + (1000 * 60 * 30) }); This is very handy for use cases such as refreshing oAuth tokens, sending notifications relative to a user timezone, and so much more. #### [#](#prioritized-events) Prioritized events When two or more events are scheduled to run at the same time in the future, it's sometimes important to identify which should happen first. This is where the `priority` field comes in. import { AsyncWorkloadsClient } from '@netlify/async-workloads' const client = new AsyncWorkloadsClient(); const user = getUser(); await client.send('EVENT_NAME', { priority: user.plan === 'enterprise' ? 25 : 0 }); In this example, the logic uses the user's plan field to determine if they should be higher in the ordering. If they are an "enterprise" plan user, then we want this event to run with a higher priority. Unless the event has some reason for delaying (like using the `delayUntil` send option), priorities aren't considered. When events are delayed and the Async Workloads scheduler layer is identifying which delayed work to process first, events with higher priority values will be processed before others that are available at the same time with lower priority values. ### [#](#send-using-the-router-api) Send using the router API The router layer for Async Workloads is accessible on sites using Async Workloads extension automatically. Under the hood, this is what the `AsyncWorkloadsClient#send()` method uses. This API gives developers the means to trigger Async Workloads from systems that can't use the `AsyncWorkloadsClient`. Using the API will require the `AWL_API_KEY` value. When installing the Async Workload extension, this value is automatically set as an Environment Variable on the team (if on a plan that allows this). It can be changed or set on the site configuration as well. Once you have access to the `AWL_API_KEY` use it within the headers to make requests as follows. * Loading error: Refresh the page to access this code sample await fetch('SITE_ORIGIN/.netlify/functions/async-workloads-router?events=EVENT_NAME', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer AWL_API_KEY' }, body: JSON.stringify({ eventName: 'EVENT_NAME', data: { foo: true } }) }) curl --header "Content-Type: application/json" \ --header "Authorization: Bearer AWL_API_KEY" \ --request 'POST' \ --data '{"eventName":"EVENT_NAME","data":{"foo":true}}' \ 'SITE_ORIGIN/.netlify/functions/async-workloads-router?events=EVENT_NAME' This API method accepts a JSON body with a single event or an array of events in the contents. The options for the events are the same as the `options` argument to the [`client.send(eventName, options)`](/async-workloads/sending-events/#basic-events) with one addition. The `eventName` should be in the `options` object as well. For example, `client.send('event-a', { delayUntil '1 day' })` would have a corresponding API body of `{"eventName": "event-a", "delayUntil": "1 day"}`. Last updated: October 2, 2024 ← [Write workloads](/async-workloads/writing-workloads/) [Multi-step Async Workloads](/async-workloads/multi-step-workloads/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Debug with VS Code and Netlify CLI | Netlify Docs You can use the VS Code debugger while you run your project with the Netlify CLI. This document outlines how to configure VS Code and how to launch the debugger. [#](#create-a-configuration-file) Create a configuration file -------------------------------------------------------------- Create a `launch.json` file under a `.vscode` directory in your project with the following content. { "version": "0.2.0", "configurations": [\ {\ "name": "netlify dev",\ "type": "node",\ "request": "launch",\ "skipFiles": ["/**"],\ "outFiles": ["${workspaceFolder}/.netlify/functions-serve/**/*.js"],\ "program": "${workspaceFolder}/node_modules/.bin/netlify",\ "args": ["dev"],\ "console": "integratedTerminal",\ "env": { "BROWSER": "none" },\ "serverReadyAction": {\ "pattern": "Server now ready on (https?://[\\w:.-]+)",\ "uriFormat": "%s",\ "action": "debugWithChrome"\ }\ },\ {\ "name": "netlify functions:serve",\ "type": "node",\ "request": "launch",\ "skipFiles": ["/**"],\ "outFiles": ["${workspaceFolder}/.netlify/functions-serve/**/*.js"],\ "program": "${workspaceFolder}/node_modules/.bin/netlify",\ "args": ["functions:serve"],\ "console": "integratedTerminal"\ }\ ] } [#](#launch-the-debugger) Launch the debugger ---------------------------------------------- After you create the configuration file, launch the debugger: 1. Select `Run and Debug` from the VS Code sidebar. To reduce noise, we recommend that you deactivate `Caught Exceptions`. 2. In the top menu, select the command to run — either `netlify dev` or `netlify functions:serve` 3. Run the debugger. If you select `netlify dev`, the CLI will start a local development environment and open a browser with the site URL. If you select `netlify functions:serve`, the CLI will start a [standalone Netlify Functions server](/cli/manage-functions/#serve-functions-with-a-standalone-server-locally) . ### [#](#debug-functions) Debug functions Use the `--inspect` Node.js option to debug functions. Visit [managing functions](/cli/manage-functions/#debug-functions-locally) for more information. Last updated: February 28, 2024 ← [Manage functions with Netlify CLI](/cli/manage-functions/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Build Plugins | Netlify Docs Netlify Build Plugins extend the functionality of the Netlify Build process. You can [install plugins](#install-a-plugin) made by others, or [write your own](/build-plugins/create-plugins/) . You can [save them locally](/build-plugins/create-plugins/#local-plugins) in your repository, or [share them with others](/build-plugins/share-plugins/) . Build Plugins expand what your Netlify builds are capable of. For example, you can use plugins to: * speed up builds by optimizing and debugging your build cache * import and convert data from external sources * check for broken links in a site after building * analyze and optimize site asset handling for better runtime performance * generate content like sitemaps, RSS feeds, and search indexes [#](#install-a-plugin) Install a plugin ---------------------------------------- To get a sampling of what plugins can do, navigate to **Site configuration \> Build & deploy \> Build plugins** for your site. You’ll find different types of plugins, including plugins from our partners and plugins from the community. Plugins can be [installed directly from the Netlify UI](#ui-installation) . They can also be [installed using the Netlify configuration file](#file-based-installation) , which allows more configuration options. Netlify [automatically installs](#automatic-installation) plugins or runtimes recommended for certain frontend frameworks when you link a repository for a new site. Use a compatible Node.js version For optimum compatibility while developing or running plugins, we recommend using the [default version](/configure-builds/available-software-at-build-time/) of Node.js installed by Netlify. However, you can also [specify a different version](/configure-builds/manage-dependencies/#node-js-and-javascript) for your project’s setup, if needed. ### [#](#ui-installation) UI installation 1. In the Netlify UI, navigate to **Site configuration \> Build & deploy \> Build plugins** for your site. 2. Search or browse for the plugin you want. 3. Select **Enable**. 4. Follow the installation guidance in the Netlify UI to install the plugin on a site. You may be prompted to add [build environment variables](/configure-builds/environment-variables/) required by the plugin. 5. To use your new plugin, visit the **Deploys** tab for your site and select **Trigger deploy**. Consider the context UI-installed plugins run in all [deploy contexts](/site-deploys/overview/#deploy-contexts) . To limit the context for the plugin, consider using [file-based installation](#file-based-installation) instead. #### [#](#required-environment-variables) Required environment variables Though many plugins listed in the Netlify UI require no configuration for default operation, some may require you to set one or more [build environment variables](/configure-builds/environment-variables/) for your site during or after installation. Refer to the plugin’s documentation, linked from **Options** menu in the plugin’s listing. ### [#](#file-based-installation) File-based installation File-based plugin installation allows advanced plugin configuration. You can use file-based installation for either of the following: * installing [local plugins](/build-plugins/create-plugins/#local-plugins) that you write and store in your repository * accessing a wide selection of plugins published by the community on [npm](https://www.npmjs.com/search?q=netlify-plugin) In both cases, you [configure settings](#configure-settings) in `netlify.toml`. For a plugin published to npm, you also [add it as a dependency](#add-dependency) . Then you can [test or run](#run-and-test) the plugin as part of a build. #### [#](#configure-settings) Configure settings To run a plugin during your build, add it to a [Netlify configuration file](/configure-builds/file-based-configuration/) stored in your site’s [base directory](/configure-builds/overview/#definitions-1) . A plugin configured globally with `[[plugins]]` runs in all [deploy contexts](/site-deploys/overview/#deploy-contexts) , but you can also [configure a plugin by deploy context](#configure-by-deploy-context) . Here’s a sample configuration with two plugins installed in all deploy contexts. # Configuration for a plugin published to npm [[plugins]] package = "netlify-plugin-lighthouse" [plugins.inputs] output_path = "reports/lighthouse.html" # Configuration for a local plugin [[plugins]] package = "/plugins/netlify-plugin-hello-world" Each `[[plugins]]` entry accepts two keys: * **`package`** (required)**:** * for a plugin installed from npm, the npm package name of the plugin. * for a [local plugin](/build-plugins/create-plugins/#local-plugins) , the absolute path to a directory containing the plugin’s `index.js` and `manifest.yml` files. The `package` value for a local plugin must start with `.` or `/`. * **`inputs`:** custom settings that the plugin author may specify as required or available for configuring the plugin. To specify `inputs` per deploy context, refer to [configure by deploy context](#configure-by-deploy-context) . For npm-published plugins, you can find these details in each plugin’s package documentation on the [npm Public Registry](https://www.npmjs.com/) . Sometimes order matters Different plugins run during different stages of your build. When multiple plugins are set to run in the same stage, they will run in the order they are listed in the Netlify configuration file. An npm-published plugin’s README should indicate if order is important to that plugin’s functionality. ##### [#](#configure-by-deploy-context) Configure by deploy context Using specific settings in your Netlify configuration file, you can limit a build plugin to run in a certain [deploy context](/site-deploys/overview/#deploy-contexts) only, or you can configure a plugin’s `inputs` settings differently per context. Here’s an example configuration that runs the Sitemap plugin in the context of production deploys only. # Use double brackets since `plugins` is an array of tables. [[context.production.plugins]] package = "@netlify/plugin-sitemap" And here’s an example configuration that runs the Cypress plugin differently based on deploy contexts. # Use Cypress plugin for this site. # This section, by itself, configures the plugin # for all deploy contexts (production, branch deploys, Deploy Previews). [[plugins]] package = "netlify-plugin-cypress" [plugins.inputs] record = true # Don’t record Cypress tests in Deploy Previews. # Since this entry is more specific, it overrides the entry above. # `context.deploy-preview.plugins` and `package` must be included. [[context.deploy-preview.plugins]] package = "netlify-plugin-cypress" # Use single brackets since `inputs` is an object property [context.deploy-preview.plugins.inputs] record = false This configuration records test results and artifacts on the Cypress Dashboard for production and branch deploys only, not Deploy Previews. UI-installed plugins run on all contexts To limit a plugin to certain deploy contexts, ensure that you’ve configured the plugin for your site using file-based installation only and not UI installation. ##### [#](#next-steps) Next steps If you’re installing a local plugin, you can [run and test it](#run-and-test) after configuration. Otherwise, you’ll [add a dependency](#add-dependency) to `package.json`. #### [#](#add-dependency) Add dependency For a plugin from npm, there’s an additional step beyond editing the Netlify configuration file. You must use [npm](https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file) , [yarn](https://classic.yarnpkg.com/en/docs/cli/add/) , or another Node.js package manager to add the plugin to `devDependencies` in your site’s `package.json`. Evaluate the plugin code Plugins available on npm but not yet listed in the Netlify UI have not been reviewed or approved by Netlify staff. We strongly recommend you review the plugin code and author for security concerns before installing. From your project’s base directory, use a command like this to add the dependency: * Loading error: Refresh the page to access this code sample # Replace `BUILD_PLUGIN_NAME` with a real plugin name, # like `netlify-plugin-lighthouse` npm install -D BUILD_PLUGIN_NAME # Replace `BUILD_PLUGIN_NAME` with a real plugin name, # like `netlify-plugin-lighthouse` yarn add -D BUILD_PLUGIN_NAME #### [#](#run-and-test) Run and test When you save your changes to your repository and push them to your Git provider, the build that’s triggered on Netlify will run with plugins installed for that deploy context. If you would like to test a plugin before running it in a production build, you can use a [branch deploy or Deploy Preview](/site-deploys/overview/#branches-and-deploys) , or you can [run the build locally with Netlify CLI](/cli/get-started/#run-builds-locally) . ### [#](#automatic-installation) Automatic installation When you link a repository for a new site, Netlify runs a [framework detection utility](https://github.com/netlify/build/tree/main/packages/framework-info) to determine whether your site uses a particular frontend framework. Certain frameworks have recommended Build Plugins or runtimes. These help extend the functionality of the Netlify Build process to support key framework-specific features. Recommended plugins and runtimes may have site conditions requirements, such as a minimum Node.js version. If your new site uses a framework with recommended plugins or runtimes, Netlify checks whether these are already [installed in a Netlify configuration file](#file-based-installation) . If not, Netlify automatically installs them. These automatically installed plugins run in all deploy contexts. For an existing site that’s already linked to Netlify, you can choose to install framework-specific recommended plugins yourself. [#](#manage-plugin-versions) Manage plugin versions ---------------------------------------------------- Netlify encourages plugin authors to regularly update functionality and release new versions using [semantic versioning](https://docs.npmjs.com/about-semantic-versioning) . Minor plugin version updates introduce only backward compatible new features, while major plugin version updates can introduce breaking changes. Refer to the plugin’s changelog, linked from the **Options** menu for the plugin listing in the Netlify UI, for version details. The steps for managing plugin versions for your site depend on the plugin installation method. For plugins [installed in the UI](#ui-installation) or [installed automatically](#automatic-installation) , Netlify updates your site for minor plugin version releases automatically. To manage major plugin updates for a site, take the following steps: 1. Navigate to **Site configuration \> Build & deploy \> Build plugins** for your site. 2. Search or browse to find the plugin you want to manage. 3. Select **Options \> Change version** . 4. Select the desired major version. 5. Select **Change version** to save. Subsequent builds will use the plugin version that you’ve chosen and confirmed. For plugins [installed through file-based installation](#file-based-installation) , you can [manage versions](https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept) in your site’s `package.json` file under `devDependencies`. [#](#remove-a-plugin) Remove a plugin -------------------------------------- The steps for removing a plugin depend on how it was installed or whether it is an Essential Gatsby or Next.js Runtime plugin. For plugins [installed in the UI](#ui-installation) or [installed automatically](#automatic-installation) : 1. For your selected site, go to **Site configuration \> Build & deploy \> Build plugins** . 2. Find the plugin you want to remove. 3. In the plugin’s card select **Disable**. Subsequent builds will not use the uninstalled plugin and environment variables entered for this integration **will not be deleted**. For plugins [installed through file-based installation](#file-based-installation) : 1. Open your site’s `netlify.toml`. 2. Delete or comment out the plugin’s configuration fields. When you push your committed changes, the resulting build will run without the plugin. If you’re removing an npm-published plugin and want to avoid installing code you won’t use, you can [uninstall the plugin package using npm](https://docs.npmjs.com/uninstalling-packages-and-dependencies) . Plugin not uninstalling correctly? Check for conflicting configurations It’s possible to configure a plugin both in the Netlify UI and your site’s `netlify.toml` — though the configuration file takes precedence. If you follow the above steps to remove a plugin from `netlify.toml` and the plugin is still installed, make sure it’s not also configured in the Netlify UI, and vice versa. Removing the plugin from one does not automatically remove it from the other. For the [Essential Gatsby](/frameworks/gatsby/?gatsby-version=essential#essential-gatsby-build-plugin) and [Next.js Runtime v4](/frameworks/next-js/runtime-v4/overview/#next-js-runtime-v4) plugins: 1. For your selected site, go to **Site configuration \> Build & deploy** . 2. In **Build settings**, find your plugin in the **Runtime** field and select **Remove**. [#](#create-a-plugin) Create a plugin -------------------------------------- Once you’ve had a chance to try out plugins, you may want to make one of your own. To learn how, visit the [create plugins doc](/build-plugins/create-plugins/) . A new way to build deep integrations and extensions Visit the [Netlify SDK docs](https://developers.netlify.app/sdk/get-started/introduction/) to learn about new tools and options for extending and integrating with Netlify. With the SDK, you can make an extension that interacts with more parts of the Netlify platform than a build plugin can. This new toolset also provides a streamlined experience for both developers and users. [#](#get-help) Get help ------------------------ Netlify Build Plugins are created by our partners and developers at Netlify and in the community. If you need help with a plugin, contact the plugin author by submitting an issue on the plugin repository. For plugins in the Netlify UI, you can find a link to the plugin issues under the **Options** menu for the plugin listing. If a plugin author doesn’t respond to an issue within a week, you can [request deactivation](https://github.com/netlify/plugins/issues/new) of the plugin from the Netlify UI. For more general questions, or to discuss Build Plugins with other members of the community, visit the [Netlify Support Forums](https://answers.netlify.com/c/netlify-support/build-plugins/49) . [#](#more-build-plugins-resources) More Build Plugins resources ---------------------------------------------------------------- * [Create Build Plugins](/build-plugins/create-plugins/) using [build events](/build-plugins/create-plugins/#plug-in-to-build-events) * [Share Build Plugins](/build-plugins/share-plugins/) * [Use the Netlify Blobs API in a build plugin](/blobs/overview/) Last updated: November 29, 2024 [Create Build Plugins](/build-plugins/create-plugins/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage functions with Netlify CLI | Netlify Docs The Netlify CLI offers the ability to create, serve, and test Netlify Functions locally. Once you create a serverless function, you have the option to invoke the function in a local development environment using Netlify Dev, or to invoke the functions with a local standalone server. To learn about all of the options available, review the [command reference for functions](https://cli.netlify.com/commands/functions) . [#](#create-serverless-functions-with-netlify-dev) Create serverless functions with Netlify Dev ------------------------------------------------------------------------------------------------ Netlify can create serverless functions for you locally as part of Netlify Functions with the `functions:create` command: netlify functions:create Follow the CLI prompts to select from a number of function templates that are available to get you started. You can also add your own utility functions to suit your project development needs. # Create a new function from one of the available templates offered # when prompted $ netlify functions:create # Create a new function with a given name using either of the # following options $ netlify functions:create hello-world $ netlify functions:create --name hello-world # Create a new function by cloning a template from a remote url # organised with dependencies installed into a subdirectory $ netlify functions:create hello-world --url https://my-remote-template-URL Git ignore the `node_modules` folder If your functions have `node_modules` in each function folder, make sure to add them to your `.gitignore` file. Don’t forget to add bash scripts to install the dependencies for production. #### [#](#deploy-unbundled-function-folders) Deploy unbundled function folders When a function has `node_modules` in its own folder, these packages need to be installed during deployment. The Netlify build system does not recursively install dependencies for your function folders but you can write `prebuild` or `postinstall` bash scripts to install them for production. [#](#invoke-functions-while-running-netlify-dev) Invoke functions while running Netlify Dev -------------------------------------------------------------------------------------------- Use `netlify dev` to start a local development environment and Netlify Dev will run the functions as they would run in the Netlify production environment. To get started, configure the [functions directory in your `netlify.toml`](/configure-builds/file-based-configuration/#sample-netlify-toml-file) and then run `netlify dev`. The functions will be accessible at `http://localhost:8888/.netlify/functions/function-name` in the browser. Accessing the function through the browser simulates a `GET` request but you can also use `netlify functions:invoke` to test other requests. For example, the CLI also models POST requests. You can use `netlify functions: list` to get a list of all detected functions. If you run functions in your local environment with Netlify Dev, you can then test sending payloads of data or authentication payloads: # with prompting netlify functions:invoke # we will prompt you at each step netlify functions:invoke myfunction # invoke a specific function netlify functions:invoke --name myfunction # invoke a specific function # no prompting (good for CI) netlify functions:invoke --name myfunction --identity # invoke a specific function with Netlify Identity headers netlify functions:invoke --name myfunction --no-identity # invoke a specific function without Netlify Identity headers # sending payloads netlify functions:invoke myfunction --payload '{"count": 1}' netlify functions:invoke myfunction --querystring "count=1" netlify functions:invoke myfunction --payload "./pathTo.json" There are special cases for [event-triggered functions](/functions/trigger-on-events/) that will also provide mock data for testing. This makes it possible to manually test event-triggered functions locally, such as on `identity-signup`, and improves the development experience. [#](#serve-functions-with-a-standalone-server-locally) Serve functions with a standalone server locally -------------------------------------------------------------------------------------------------------- While Netlify Dev will simulate the Netlify production environment, it can be useful to simulate Netlify Functions in a standalone server instead. If you serve functions with a standalone server, you can debug functions without the overhead of starting a framework server. To start a functions server locally, run `netlify functions:serve`. Your function will be available at `http://localhost:9999/.netlify/functions/` If you configure a functions directory, the server will serve functions from that directory. If not, the server will serve functions from `netlify/functions`. The default port for the functions server is `9999`. To override these settings, use the `--functions` and `--port` flags: netlify functions:serve --functions --port You can also configure the settings in a `netlify.toml`, under the `dev` block: [dev] functions = "netlify-functions" functionsPort = 7000 [#](#debug-functions-locally) Debug functions locally ------------------------------------------------------ Netlify CLI uses [Lambda-local](https://github.com/ashiina/lambda-local) to simulate serverless functions. Since the CLI invokes functions in the same process as the functions server, you can debug functions by inspecting the functions server process. To debug, set the `--inspect` Node.js option when starting the functions server: * On Windows, run `cmd /V /C "set NODE_OPTIONS=--inspect && netlify functions:serve"` * On Mac/Linux, run `NODE_OPTIONS=--inspect netlify functions:serve` Then, attach any Node.js debugger to the CLI process to debug your functions. To learn how to debug with Visual Studio Code while running the Netlify CLI, review [Debug with VS Code](/cli/debug-with-vscode/) . Last updated: December 6, 2023 ← [Local development with Netlify CLI](/cli/local-development/) [Debug with VS Code](/cli/debug-with-vscode/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Multi-step Async Workloads | Netlify Docs When using event-driven architectures, it’s common to break up the code into discrete steps so that those steps can run, fail, and retry on their own. While there are many patterns to solve this, Async Workloads has a built-in method of doing multi-step processes that allows developers to code workflows together without having to create separate workloads. To build these multi-step workloads, the `AsyncWorkloadEvent` provides a `step` field that includes methods for creating steps. The primary method for defining step functions is `step.run(id, callback)`. import { asyncWorkloadFn, AsyncWorkloadEvent } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({step}: AsyncWorkloadEvent) => { const results = await step.run('step-id', ()=>{ // logic for this step goes here // optionally, return the step data used for later parts // of the workload. return {}; }); }); All available methods for steps are documented on the [`AsyncWorkloadEvent` documentation](/async-workloads/writing-workloads/#event-step) . [#](#steps-in-practice) Steps in practice ------------------------------------------ To understand the application of this, compare the implementation of a common workflow with a workload implemented with a step function. The common workflow is: sign up a user, add them to an external billing system, sync that billing information with the site database, and send a welcome email. import { asyncWorkloadFn, AsyncWorkloadConfig } from "@netlify/async-workloads"; export default asyncWorkloadFn(async (event) => { const { accountId } = await doSignup(event.eventData); const { billingSystemId } = await setupBilling(accountId); const user = await updateUser({billingSystemId}); await sendEmail(user); }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['account.signup'], }; With this workload, `doSignup`, `setupBilling` , `updateUser` , and `sendEmail` functions could all run into transient issues - network outages, APIs are unavailable, etc. This could be attempted with error catching and in-code retrying, but if the issues take a very long time to resolve (that’s relative — a long time could mean 30 seconds, 3 days, etc.), then the options become much more limited or expensive to keep functions running indefinitely until issues resolve. In addition to handling failures, if something breaks, the workload will retry completely regardless of any work that was already successful. Given that workloads should aim to be idempotent, this shouldn’t be a major deal but it will consume resources and time for all involved systems. This is the same workload implemented using step functions. import { asyncWorkloadFn, AsyncWorkloadConfig, AsyncWorkloadEvent } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({eventData, step}: AsyncWorkloadEvent) => { const { accountId } = await step.run('signup-user', ()=>{ return doSignup(eventData); }); const { billingSystemId } = await step.run('add-to-billing', ()=>{ return setupBilling(accountId); }); const user = await step.run('sync-user-billing', ()=>{ return updateUser({billingSystemId}); }); await sendEmail(user); }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['account.signup'], }; This implementation is very similar to the original implementation. With steps, workloads can define the full scope of work that's needed but the durable execution will automatically retry these workloads. The steps will ensure only work that has not completed yet will run until it gets to the end. This workload function runs until it hits a step that it has not completed before or until the workload completes. After running a step function for the first time, the workload will be reinvoked. All previous steps will resolve their previous results without having to run the function again. This means that this workload will have 4 invocations to get to completion. The first invocation will run until it hits the `signup-user` step and will run that callback. Once completed, the full workload is invoked again. This next invocation will already have the results of `signup-user`, so it will resolve that result without running the step function and will continue the workload until it hits the `add-to-billing` step. It does this same process of running and invoking itself again as it accumulates the results of all step functions. If any steps fail, the workload will be retried but all steps that were completed before that failure will persist their respective results. So, if `sendEmail()` fails (the very last step in the workload), the workload will be retried according to the retry schedule but all of the step functions before it will not be invoked again. [#](#sleeping) Sleeping ------------------------ In addition to breaking up logic into discrete, isolated steps, Async Workloads provides the ability for workloads to “sleep” mid-execution and continue after that minimum duration has passed. This allows developers to represent full workflows, including their relationship to time within the workload. To update the above example to have a 24-hour waiting period before sending the welcome email, add a `step.sleep(id, duration)`: import { asyncWorkloadFn, AsyncWorkloadConfig, AsyncWorkloadEvent } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({eventData, step}) => { const { accountId } = await step.run('signup-user', ()=>{ return doSignup(eventData); }); const { billingSystemId } = await step.run('add-to-billing', ()=>{ return setupBilling(accountId); }); const user = await step.run('sync-user-billing', ()=>{ return updateUser({billingSystemId}); }); await step.sleep('24h-delay-for-email', '1 day'); await sendEmail(user); }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['account.signup'], }; [#](#parallelized-and-nested-steps) Parallelized and nested steps ------------------------------------------------------------------ Steps can also be triggered in parallel. In the standard step lifecycle, the workload will restart after a step is invoked, but if two or more steps start at the same time, it will let them complete before continuing and re-invoking the workload. Running steps in parallel allows you to start the steps once and just await their results. This can be done with loops or other collections as well. import { asyncWorkloadFn } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({step}) => { const step1Result = step.run('step1', ()=>{ return { foo: '1' }; }); const step2Result = step.run('step2', ()=>{ return { bar: '2' }; }); const parallelResults = await Promise.all([step1Result, step2Result]); await step.run('log-results', ()=>{ console.log(parallelResults); // outputs [{foo: '1'}, {bar: '2'}] }); }); Nesting steps works the same. The step lifecycle will not trigger re-invocation unless the all steps are complete. import { asyncWorkloadFn } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({step}) => { const step1Result = step.run('step1', ()=>{ const step3Result = step.run('step3', ()=>{ return { baz: '3' }; }); return { foo: '1', step3Result }; }); const step2Result = step.run('step2', ()=>{ return { bar: '2' }; }); const results = await Promise.all([step1Result, step2Result]); await step.run('log-results', ()=>{ console.log(results); // outputs [{foo: '1', step3Result: {baz: '3'}}, {bar: '2'}] }); }); [#](#step-invocation-lifecycle) Step invocation lifecycle ---------------------------------------------------------- It's important to understand that after each new step function that has not run yet, the complete workload is reinvoked. This will give each step a clean slate and as much time within the serverless runtime. This also means anything outside of a step function can be called multiple times for each step method. If you expect a process to run only once within a workflow, put the process inside of a step. To examine how logic outside of steps and logic inside of steps will run when executing a multi-step workload, review the following example. import { asyncWorkloadFn} from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({step}) => { console.log('outside logic A'); await step.run('step1', ()=>{ console.log('inside of step 1'); }); console.log('outside logic B'); await step.run('step2', ()=>{ console.log('inside of step 2'); }); await step.run('step3', ()=>{ console.log('inside of step 3'); }); }); This workload will have the following log pattern: outside logic A inside of step 1 outside logic A outside logic B inside of step 2 outside logic A outside logic B inside of step 3 outside logic A outside logic B This example demonstrates that the workload starts the function again each time but only runs the functions that it has not hit yet. It will re-invoke the workload after a new step method. Everything not inside of a step will be re-run. This is why it’s important to ensure everything outside of a step is ok to run again. The `step.sleep` method works the same. import { asyncWorkloadFn } from "@netlify/async-workloads"; export default asyncWorkloadFn(async ({step}) => { console.log('A'); await step.sleep('first-wait', '1 hour'); console.log('B'); await step.sleep('second-wait', '2 hours'); console.log('C'); }); After 3 hours, this workload will have the following log pattern: A A B A B C Last updated: October 2, 2024 ← [Sending events](/async-workloads/sending-events/) [Lifecycle](/async-workloads/lifecycle/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Writing Async Workloads | Netlify Docs This page will go deeper into creating Async Workload functions and the different capabilities available with them. [#](#installation) Installation -------------------------------- Enable the Async Workloads Netlify extension on the team settings. There's no additional, required settings needed after enabling. Once enabled, all sites on the team can build Async Workloads. Add the `@netlify/async-workloads` module to your project. This will provide the functionality and types for those using Typescript. * Loading error: Refresh the page to access this code sample npm install @netlify/async-workloads pnpm add @netlify/async-workloads yarn add @netlify/async-workloads [#](#async-workload-functions) Async Workload functions -------------------------------------------------------- Start by adding a function file to your project by creating the file in [your functions directory](/functions/optional-configuration/#directory) . * Loading error: Refresh the page to access this code sample import { asyncWorkloadFn, AsyncWorkloadEvent, AsyncWorkloadConfig } from "@netlify/async-workloads"; export default asyncWorkloadFn((event: AsyncWorkloadEvent) => { // logic goes here }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: [] }; import { asyncWorkloadFn } from "@netlify/async-workloads"; export default asyncWorkloadFn((event) => { // logic goes here }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: [] }; Async Workload functions are written similarly to serverless functions but the handler is wrapped with the `asyncWorkloadFn` wrapper. This wrapper ensures all of the necessary functionality and types are in place (e.g. ensuring the authentication checks are performed on all workloads automatically). Async Workloads operates as an event-based architecture so the inputs to the `asyncWorkloadFn` callback will be an event ([`AsyncWorkloadEvent`](/async-workloads/writing-workloads/#asyncworkloadevent) ) and the workload will specify the event names that it responds to. When a client sends an event with a name that matches, the workload callback is invoked and the event is passed. ### [#](#asyncworkloadevent) AsyncWorkloadEvent `asyncWorkloadFn` is invoked with an event argument of the type `AsyncWorkloadEvent`. On this event we have the following fields and methods: * `eventName` - name of the event that triggered the workload. * `eventId` - ID value assigned to this event when triggered. * `eventData` - data sent as the `data` field in the sent event. * `attempt` - retry attempt number. This number is `0` on the first invocation of the workload because that isn’t a retry attempt. * `sendEvent(eventName, options)` - an alias to `client.sendEvent()`. Because this method is running within an Async Workload function, it uses the same information (for example, `baseUrl`, `apiKey`, etc.) used to invoke this async workload to establish a client and send events. * `step` - object that groups all of the step-related functionality. Learn more about [multi-step workloads here](/async-workloads/multi-step-workloads) . * `step.run(stepId, callback)` - used to create a step function for discrete retryable logic. It returns a promise that will resolve to the value returned from the callback function. The returned value should be serializable to JSON. Identifiers must be unique for each step that needs to run within a workload. If a step matches an `id` that has already run, it will have the promise immediately resolve to the same response value. Learn more about [multi-step workloads here](/async-workloads/multi-step-workloads/) . * `step.sleep(sleepId, duration)` - used to delay the continuation of logic within a workload. `sleepId` should be unique across all steps and other sleep functions. `duration` can be the relative number of milliseconds to wait, a [ms-compatible string value](https://www.npmjs.com/package/@lukeed/ms) , or a UTC milliseconds timestamp value. Relative duration values are relative to the time the workload function was called. Learn more about [workload sleeping here](/async-workloads/multi-step-workloads/#sleeping) . ### [#](#asyncworkloadconfig) AsyncWorkloadConfig Within the Async Workload function module, an `asyncWorkloadConfig` field must be exported. This is the in code configuration for how the workload should operate. The config must implement the required fields of the `AsyncWorkloadConfig` type defined below. * Loading error: Refresh the page to access this code sample import type { AsyncWorkloadConfig } from "@netlify/async-workloads"; export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['event-a', 'event-b'], }; export const asyncWorkloadConfig = { events: ['event-a', 'event-b'], }; The fields and methods that can be defined on `AsyncWorkloadConfig` type are the following: * `events` (required) - the list of event name strings that this workload function should respond to. The names are case-insensitive. * `eventFilter` (optional) - a function that will receive the `AsyncWorkloadEvent` event and the router’s request context to determine if the event can be handled by this workload. It must return a boolean to determine if the workload should run this function. This is checked on the Async Workload routing layer and will not invoke this function if the event name or this filter does not match or return false. * Loading error: Refresh the page to access this code sample import type { AsyncWorkloadConfig, AsyncWorkloadEvent } from "@netlify/async-workloads"; export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['event-a', 'event-b'], eventFilter: (event: AsyncWorkloadEvent)=>{ // only call this workload if this is for an enterprise customer return event.eventData.plan === 'enterprise'; } }; export const asyncWorkloadConfig = { events: ['event-a', 'event-b'], eventFilter: (event)=>{ // only call this workload if this is for an enterprise customer return event.eventData.plan === 'enterprise'; } }; * `maxRetries` (optional) - when the event is to be handled by a workload function, it always attempts to retry failures. The value should be the number of attempts to be made after the initial retry attempt. The default is `4`, which means the total number of attempts for a function is the initial plus four retry attempts, or `5` total attempts. * `backoffSchedule` (optional) - provide a function that will be passed the attempt number and it should return the number of milliseconds to wait before processing the next value. Return value can be a number or an [ms-compatible string](https://www.npmjs.com/package/@lukeed/ms) of a relative time from now or the absolute UTC milliseconds. The maximum backoff is `1 week`. The backoff schedule will default to `5 seconds` and each attempt after will multiply the last backoff delay by `4`. The schedule default is `5s`, `20s`, `1m20s`, `8m`, and so on for the remaining retries and up to the max backoff time. * Loading error: Refresh the page to access this code sample import type { AsyncWorkloadConfig } from "@netlify/async-workloads"; export const asyncWorkloadConfig: AsyncWorkloadConfig = { events: ['event-a', 'event-b'], // a custom backoff schedule backoffSchedule: (attempt)=>{ if(attempt < 2){ return '5 minutes'; } return '2 hours'; } }; export const asyncWorkloadConfig = { events: ['event-a', 'event-b'], backoffSchedule: (attempt)=>{ if(attempt < 2){ return '5 minutes'; } return '2 hours'; } }; [#](#retries-and-errors) Retries and errors -------------------------------------------- Async Workload functions are considered successful if they do not timeout, if they do not throw an error, and if they do not reject a returned promise. If any of those conditions happen, the system looks to the retry process to determine what to do. The retrying process will consider the configured [`maxRetries`](/async-workloads/writing-workloads/#maxRetries) and the [`backoffSchedule`](/async-workloads/writing-workloads/#backoffSchedule) . Optionally, developers can override the workflow retry configuration by throwing explicit errors within the workload. These special error types will inform the system on how to handle this condition. import { asyncWorkloadFn, ErrorDoNotRetry, ErrorRetryAfterDelay } from "@netlify/async-workloads"; export default asyncWorkloadFn(function (event) { // error and explicitly prevent retries throw new ErrorDoNotRetry('do not retry this error'); // error and control future retry throw new ErrorRetryAfterDelay({message: 'retry this after some time', retryDelay: '10s'}); }); * `ErrorDoNotRetry` - should be used when the workload should not be retried even if there are more retry attempts remaining. This event will still go to the failed state. * `ErrorRetryAfterDelay` - should be used when the workload has a known delay that needs to be abided by. For example, if the workload is using a third-party API and the API provides a rate limit delay, the workload can turn that rate limit delay from the API into the retry delay. * `retryDelay` (required) - the number of milliseconds the system should wait relative to now before retrying. The value can be a number or a [ms](https://www.npmjs.com/package/@lukeed/ms) compatible string value or absolute UTC milliseconds of when the workload should be retried. * `forceDelayTime` (optional) - by default, the system will choose the delay that’s longer between the explicit `retryDelay` and the workload’s [backoff schedule](/async-workloads/writing-workloads/#backoffSchedule) . Setting `forceDelayTime` to `true` will always use the passed `retryDelay` time and will override the backoff schedule. Note, the max time must abide by the same max limits of the backoff schedules. [#](#type-safe-events) Type-safe events ---------------------------------------- For developers using TypeScript, the Async Workloads supports adding types to your events for both the workload functions and the AsyncWorkloadClient. To create a type-safe event, you can use the `CustomAsyncWorkloadEvent` interface and extend it with your own event properties. import type { CustomAsyncWorkloadEvent } from '@netlify/async-workloads'; // individual event types export interface FooEvent extends CustomAsyncWorkloadEvent { eventName: 'foo', eventData: { propA: string; probB: number[] } } export interface BarEvent extends CustomAsyncWorkloadEvent { eventName: 'bar', eventData: { prop1: boolean; } } // the collection of all of the site's types export type AllSiteEvents = FooEvent | BarEvent; Now, we can use these event types within our available clients and workload functions. const client = new AsyncWorkloadsClient(); client.send('foo', { data: { // throws type error because // this field is not on FooEvent or BarEvent otherField: true } }); Within the type specific workload functions, we can use the events that it operates on exclusively for type safety. // Type this event for the FooEvent export default asyncWorkloadFn((event)=> { // throws type error: // Property 'otherField' does not exist on type '{ propA: string; probB: number[]; } if(event.eventData?.otherField === true){ return; } }); export const asyncWorkloadConfig: AsyncWorkloadConfig = { // throws a type error: because FooEvent is named 'foo' events: ['bar'], // event filter is also typed eventFilter: (event) => { // throws type error: // Property 'otherField' does not exist on type '{ propA: string; probB: number[]; } if(event.eventData?.otherField === true){ return; } } } Last updated: October 2, 2024 ← [Get started](/async-workloads/get-started) [Sending events](/async-workloads/sending-events) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Local development with Netlify CLI | Netlify Docs The Netlify CLI brings the functionality of your Netlify production environment directly to your local machine through the `dev` command. This CLI functionality is also referred to as Netlify Dev. When you use Netlify Dev, the CLI provides a proxy server that includes edge logic for custom headers and redirects, environment variables, and Netlify Functions. It [automatically detects](#project-detection) tools and frameworks like Gatsby, Hugo, Eleventy, Next.js, and more to configure a local development server that mimics the Netlify production environment. The sections below describe how to get started with Netlify Dev, how to start and share a live development server, how project detection and ports work, and how to customize the configuration. You can also access the [command reference for `dev`](https://cli.netlify.com/commands/dev) for more information. [#](#get-started-with-netlify-dev) Get started with Netlify Dev ---------------------------------------------------------------- Before you begin, make sure you complete the following if you haven’t already: * [Install](/cli/get-started/#installation) the Netlify CLI. * [Authenticate](/cli/get-started/#authentication) with an access token. * Link your local project to a Netlify `siteID`. To do this, set up [continuous deployment](/cli/get-started/#continuous-deployment) with `netlify init` or [link an existing Netlify site](/cli/get-started/#link-and-unlink-sites) with `netlify link`. To start a local development server for the build tool you’re using, run the following command from the root of your linked repository: netlify dev By default, Netlify Dev runs your project using the configuration and [environment variables](/environment-variables/overview/) set for local development with the Netlify CLI. For environment variables, that means those with values set for `dev` or `all` deploy contexts. You can use the `--context` flag to run your project with a different deploy context’s settings and variables. netlify dev --context production Note that environment variables apply to all scopes when running `netlify dev`. To run a shell command within the Netlify Dev environment, use `exec`: netlify dev:exec YOUR_SHELL_COMMAND ### [#](#share-a-live-development-server) Share a live development server You can run the following command to share your live development server over HTTPS. This creates a tunnel from your local development server over the internet and allows you to share the resulting URL with anyone anywhere in the world. netlify dev --live Anyone can access the resulting URL as long as the session is open. [#](#project-detection) Project detection ------------------------------------------ Netlify Dev attempts to detect the site generator or build command that your project uses and run these on your behalf, while adding other development utilities. If you have a JavaScript project, it uses simple heuristics to search for the best `package.json` script to run for you, so you can use the full flexibility of npm scripts. You also have the option to override framework detection, if needed. The number of [frameworks that Netlify Dev can detect](https://github.com/netlify/build/tree/main/packages/framework-info/src/frameworks) is growing but, if the framework you use is not yet supported, you can instruct Netlify Dev to run the project on your behalf. Configure your project’s build command, port, and publish directory with the `[dev]` block in your `netlify.toml` file. # sample dev block in the toml # note: each of these fields are optional and should only be used if you need an override [dev] command = "yarn start" # Command to start your dev server targetPort = 3000 # The port for your application server, framework, or site generator port = 8888 # The port that the Netlify Dev will be accessible on publish = "dist" # If you use a _redirect file, provide the path to your static content folder If the CLI detects your project incorrectly or detects multiple frameworks, you can specify a `framework` option to test only one detector against your project. [dev] framework = "create-react-app" # or "#static" to force a static server Possible values of `framework`: * `#auto` (default) to check all [available frameworks](https://github.com/netlify/build/tree/main/packages/framework-info/src/frameworks) . * The ID for one of the available frameworks, as specified in [the `.json` file for that framework](https://github.com/netlify/build/tree/main/packages/framework-info/src/frameworks) in the Netlify Build repository. * `#static` for a static file server * `#custom` to use the `command` option to run an app server and `targetPort` option to connect to it [#](#project-ports) Project ports ---------------------------------- When you use Netlify Dev, you may encounter a few different ports — especially if your project uses a static site generator that has its own dev server, like Gatsby. Keep the following in mind when working with Netlify Dev: * If your project uses a [framework that we can detect](https://github.com/netlify/build/tree/main/packages/framework-info/src/frameworks) , Netlify Dev will use the framework’s conventional ports, so you don’t have to supply them yourself. If multiple detectors match your project, we’ll ask you to choose. * If your site generator runs on a specific port, such as port 8000, you need to [specify the port](#specify-custom-ports-for-netlify-dev) when you run `netlify dev`. Netlify Dev will connect to that port and route requests successfully to the site generator along with the rest of the local Netlify environment. * If you use an unrecognized site generator or framework, or have a server you want Netlify Dev to connect to, you need to [specify the port](#specify-custom-ports-for-netlify-dev) when you run `netlify dev`. To confirm which port to use for local development with Netlify Dev, search for this box in your console output: ┌──────────────────────────────────────────────────────────────┐ │ │ │ [Netlify Dev] Server now ready on http://localhost:8888 │ │ │ └──────────────────────────────────────────────────────────────┘ [#](#configuration) Configuration ---------------------------------- Netlify Dev works without configuration for the majority of users, but you can customize Netlify Dev settings in the `[dev]` section of the Netlify configuration file. The following sections outline some common configuration options. For a full list of the available properties, refer to the [Netlify Dev section of our file-based configuration](/configure-builds/file-based-configuration/#netlify-dev) doc. ### [#](#run-an-https-server-for-local-development) Run an https server for local development By default, `netlify dev` starts an HTTP server. If you require HTTPS, you can configure a certificate and key file for use by `netlify dev` in your `netlify.toml`: [dev] [dev.https] certFile = "cert.pem" keyFile = "key.pem" Self-signed certificates require extra configuration If you’re using a self-signed certificate, you might need to configure your browser to accept it when running on `localhost`. To enable this setting for Chrome, visit `chrome://flags/#allow-insecure-localhost` in your browser. ### [#](#specify-custom-ports-for-netlify-dev) Specify custom ports for Netlify Dev Netlify Dev allows you to specify custom ports using the following parameters as flags or in a Netlify configuration file (`netlify.toml`): * **`targetPort`**: the port for your application server, framework, or site generator * **`port`**: the port for the Netlify Dev server that you will open in the browser Netlify Dev tries to acquire these ports but if they are already in use by another application, it will throw an error and let you know. [dev] targetPort = 3000 port = 8888 [#](#more-netlify-dev-resources) More Netlify Dev resources ------------------------------------------------------------ * [Command reference for `dev`](https://cli.netlify.com/commands/dev) * [Configuration properties for Netlify Dev in `netlify.toml`](/configure-builds/file-based-configuration/#netlify-dev) * [Use Netlify CLI with monorepos](/cli/get-started/#work-with-monorepos) * [Manage Functions with Netlify CLI](/cli/manage-functions) Last updated: March 27, 2024 ← [Get started with Netlify CLI](/cli/get-started/) [Manage functions with Netlify CLI](/cli/manage-functions/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Create Build Plugins | Netlify Docs In addition to [installing plugins](/build-plugins/#install-a-plugin) written by others, you can create your own. To learn how, check out the detailed reference information below and our [Build Plugin template](https://github.com/netlify/build-plugin-template) . A new way to build deep integrations and extensions Visit the [Netlify SDK docs](https://developers.netlify.app/sdk/get-started/introduction/) to learn about new tools and options for extending and integrating with Netlify. With the SDK, you can make an extension that interacts with more parts of the Netlify platform than a build plugin can. This new toolset also provides a streamlined experience for both developers and users. While you can also create build plugins with TypeScript, this document currently demonstrates how to create build plugins with JavaScript. [#](#es-modules) ES modules ---------------------------- If you plan to use JavaScript, we recommend building new plugins with [ES modules](https://nodejs.org/api/packages.html) (ESM) but the examples below also include CommonJS (CJS) syntax for older plugins. To use ESM, Node.js requires `"type": "module"` in your plugin’s `package.json` file. [#](#plug-into-events) Plug into events ---------------------------------------- Build Plugins run JavaScript or TypeScript code in response to different events happening during the build-deploy lifecycle. For example, the `onPreBuild` event handler runs before your build command. The `onPostBuild` event handler runs after your site build has completed. The following event handlers are currently available: * **`onPreBuild`:** runs before the build command is executed. * **`onBuild`:** runs directly after the build command is executed and before Functions bundling. * **`onPostBuild`:** runs after the build command completes; after `onBuild` tasks and Functions bundling are executed; and before the deploy stage. This is when file-based uploads for Netlify Blobs occur. Can be used to prevent a build from being deployed. * **`onError`:** runs when an error occurs in the build or deploy stage, failing the build. Can’t be used to prevent a build from being deployed. * **`onSuccess`:** runs when the deploy succeeds. Can’t be used to prevent a build from being deployed. * **`onEnd`:** runs after completion of the deploy stage, regardless of build error or success; is useful for resources cleanup. Can’t be used to prevent a build from being deployed. There are also event handlers that are available when running [`netlify dev`](/cli/local-development/#get-started-with-netlify-dev) : * **`onPreDev`:** runs before `onDev`. * **`onDev`:** runs directly before the dev command. [#](#anatomy-of-a-plugin) Anatomy of a plugin ---------------------------------------------- A plugin consists of two files: * A `manifest.yml` file in the package root with the plugin’s name at minimum: # manifest.yml name: netlify-plugin-hello-world * A JavaScript or TypeScript object that hooks onto a build event. For example, in JavaScript: * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function() { console.log("Hello world from onPreBuild event!"); } // index.js module.exports = { onPreBuild: () => { console.log("Hello world from onPreBuild event!"); }, } The plugin defined above will output `Hello world from onPreBuild event!` right before the site’s build command is run. The `index.js` file runs in a regular Node.js environment and can use any [Node.js core methods](https://nodejs.org/api/) and [modules](https://www.npmjs.com/) . Environment variables, redirects, headers, and build configuration can be accessed and modified with [`netlifyConfig`](#netlifyconfig) . Store both files together in a single folder. You can store this folder with your site code to run as a [local plugin](#local-plugins) , or you can [publish the plugin](/build-plugins/share-plugins/#publish-to-npm) to npm. Use a compatible Node.js version For optimum compatibility while developing or running plugins, we recommend using the [default version](/configure-builds/available-software-at-build-time/) of Node.js installed by Netlify. However, you can also [specify a different version](/configure-builds/manage-dependencies/#node-js-and-javascript) for your project’s setup, if needed. [#](#local-plugins) Local plugins ---------------------------------- You can run your own custom plugins from within your site repository without publishing to npm. To do this, save your plugin `index.js` and `manifest.yml` files into a folder in the repository. Then, using the [file-based installation](/build-plugins/#file-based-installation) method, specify the absolute path to your plugin folder in the `package` field. The following example installs a local plugin stored in `/plugins/netlify-plugin-hello-world`: # netlify.toml [[plugins]] package = "/plugins/netlify-plugin-hello-world" Take care with formatting Each plugin you add to the `netlify.toml` file must have its own `[[plugins]]` line. For a local plugin, the `package` value must start with `.` or `/`. With a local plugin declared, you can verify it’s loading correctly by using the [Netlify CLI](/cli/get-started/) to [run the build locally](/cli/get-started/#run-builds-locally) . [#](#plugin-values) Plugin values ---------------------------------- When a plugin runs, it can receive certain data: * [constants](#constants) : values generated by the plugin event * [inputs](#inputs) : values configured by the plugin user * [netlifyConfig](#netlifyconfig) : the site’s Netlify configuration * [packageJson](#packagejson) : the contents of the site’s `package.json` file * [environment variables](#environment-variables) : values available in the Netlify build environment ### [#](#constants) `constants` Each event handler includes a `constants` key. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ constants }) { console.log(constants); } // index.js module.exports = { onPreBuild: ({ constants }) => { console.log(constants); }, } The `constants` key contains the following values: * **`CONFIG_PATH`:** path to the Netlify configuration file. `undefined` if none was used. * **`PUBLISH_DIR`:** directory that contains the deploy-ready HTML files and assets generated by the build. Its value is always defined, but the target might not have been created yet. * **`FUNCTIONS_SRC`:** directory where function source code lives. `undefined` if no `netlify/functions` directory exists in the base directory and if not specified by the user. * **`FUNCTIONS_DIST`:** directory where built serverless functions are placed before deployment. Its value is always defined, but the target might not have been created yet. * **`IS_LOCAL`:** boolean indicating whether the build was [run locally](/cli/get-started/#run-builds-locally) or on Netlify. * **`NETLIFY_BUILD_VERSION`:** version of Netlify Build as a `major.minor.patch` string. * **`SITE_ID`:** Netlify site ID. Along with these constants, plugins can also access any of the [environment variables](#environment-variables) that are available in the build environment. ### [#](#inputs) `inputs` If your plugin requires additional values from the user, you can specify these requirements in an `inputs` array in the plugin’s [`manifest.yml` file](#anatomy-of-a-plugin) : # manifest.yml name: netlify-plugin-lighthouse inputs: - name: output_path description: Path to save the generated HTML Lighthouse report - name: fail_deploy_on_score_thresholds description: Fail deploy if minimum threshold scores are not met - name: thresholds description: Key value mapping of thresholds that will fail the build when not passed When you or a user install the plugin, the input names are used as keys with user-supplied values in the site `netlify.toml` file: # netlify.toml [[plugins]] package = "./plugins/netlify-plugin-lighthouse" [plugins.inputs] output_path = "reports/lighthouse.html" fail_deploy_on_score_thresholds = "true" [plugins.inputs.thresholds] performance = 0.9 accessibility = 0.9 best-practices = 0.9 seo = 0.9 pwa = 0.9 These `inputs` values are passed into the plugin when the event handlers are being executed. To access them in your plugin code you can use the following pattern: * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ inputs }) { console.log(inputs.output_path); console.log(inputs.thresholds); } // index.js module.exports = { onPreBuild: ({ inputs }) => { console.log(inputs.output_path); console.log(inputs.thresholds); }, } Plugin inputs cannot be set through the Netlify UI Currently, users cannot set inputs when [installing plugins from the Netlify UI](/build-plugins/#ui-installation) . If you would like your plugin to be listed under **Site configuration \> Build & deploy \> Build plugins** , we recommend setting [zero-config defaults](https://github.com/netlify/plugins/blob/main/docs/guidelines.md) where possible, falling back to accepting values from [build environment variables](/configure-builds/environment-variables) if needed. #### [#](#input-validation) Input validation Plugin inputs can be validated using the `inputs` property in the plugin `manifest.yml` file: # manifest.yml name: netlify-plugin-lighthouse inputs: - name: output_path required: false description: Path to save the generated HTML Lighthouse report default: "reports/lighthouse.html" - name: fail_deploy_on_score_thresholds required: false description: Fail deploy if minimum threshold scores are not met - name: thresholds required: false description: Key value mapping of thresholds that will fail the build when not passed The `inputs` property is an array of objects with the following members: * **`name` `{string}`:** name of the input. Required. * **`description` `{string}`:** description of the input. * **`required` `{boolean}`** * **`default` `{any}`:** default value. Always use `inputs` for validation We recommended using the `inputs` property to validate your plugin inputs and assign default values. This works more consistently and efficiently than coding your own validation inside event handlers. ### [#](#netlifyconfig) `netlifyConfig` When an event handler executes, a site’s Netlify configuration is normalized by [@netlify/config](https://github.com/netlify/build/tree/main/packages/config) and passed as a `netlifyConfig` object. Normalization includes applying context-specific or branch-specific settings and combining settings from `netlify.toml` with build settings configured in the Netlify UI. After normalization, plugins can access and modify most `netlifyConfig` properties during a site’s build. These include redirects, headers, and build configuration. If a site doesn’t use `netlify.toml` or build settings selections in the Netlify UI, `netlifyConfig` and its properties contain default build settings. Here’s a list of modifiable properties: * **`redirects`:** array of [redirects](/routing/redirects/) with their modifiable options * **`headers`:** array of [headers](/routing/headers/) with their modifiable options * **`functions`:** object with options for modifying [functions](/configure-builds/file-based-configuration/#functions) * **`functions.directory`:** string that includes the path to a site’s [functions directory](/functions/optional-configuration/#directory) * **`edge_functions`:** array of [edge functions](/edge-functions/overview/) with their modifiable options * **`build.command`:** string that includes a site’s [build command](/configure-builds/overview/#definitions) * **`build.environment`:** object that contains a subset of a site’s [environment variables](#environment-variables) * **`build.edge_functions`:** string that includes the path to a site’s [edge functions directory](/edge-functions/optional-configuration/#edge-functions-directory) * **`build.processing`:** object that includes options for [post processing](/configure-builds/file-based-configuration/#post-processing) HTML And here’s a plugin code sample that modifies several of the above properties. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ netlifyConfig }) { const newCommand = `node YOUR_SCRIPT.js`; // Run a script after the build command netlifyConfig.build.command = netlifyConfig.build.command ? `${netlifyConfig.build.command} && ${newCommand}` : newCommand; // Modify build command's environment variables netlifyConfig.build.environment.DATABASE_URI = getDatabaseUri(); // Add redirects netlifyConfig.redirects.push({ from: "/ORIGIN_PATH", to: "/DESTINATION_PATH", }); // Add headers netlifyConfig.headers.push({ for: "/YOUR_PATH", values: { YOUR_HEADER_NAME: "YOUR_HEADER_VALUE" }, }); // Add edge functions netlifyConfig.edge_functions ? netlifyConfig.edge_functions.push({ path: '/YOUR_PATH', function: 'YOUR_EDGE_FUNCTION' }) : (netlifyConfig.edge_functions = [{ path: '/YOUR_PATH', function: 'YOUR_EDGE_FUNCTION' }]) } // index.js module.exports = { onPreBuild({ netlifyConfig }) { const newCommand = `node YOUR_SCRIPT.js`; // Run a script after the build command netlifyConfig.build.command = netlifyConfig.build.command ? `${netlifyConfig.build.command} && ${newCommand}` : newCommand; // Modify build command's environment variables netlifyConfig.build.environment.DATABASE_URI = getDatabaseUri(); // Add redirects netlifyConfig.redirects.push({ from: "/ORIGIN_PATH", to: "/DESTINATION_PATH", }); // Add headers netlifyConfig.headers.push({ for: "/YOUR_PATH", values: { YOUR_HEADER_NAME: "YOUR_HEADER_VALUE" }, }); // Add edge functions netlifyConfig.edge_functions ? netlifyConfig.edge_functions.push({ path: '/YOUR_PATH', function: 'YOUR_EDGE_FUNCTION' }) : (netlifyConfig.edge_functions = [{ path: '/YOUR_PATH', function: 'YOUR_EDGE_FUNCTION' }]) }, }; ### [#](#packagejson) `packageJson` Each plugin event handler includes a `packageJson` argument. When an event handler executes, the contents of the `package.json` in a site’s [base directory](/configure-builds/overview/#definitions-1) get passed to a plugin. The data fields are [normalized](https://github.com/npm/normalize-package-data#what-normalization-currently-entails) to prevent plugin errors. If the site has no `package.json`, the argument is an empty object. To access the `packageJson` object in your plugin code, use the following pattern: * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ packageJson }) { console.log(packageJson); } // index.js module.exports = { onPreBuild: ({ packageJson }) => { console.log(packageJson); }, } ### [#](#environment-variables) Environment variables Plugins can access [build environment variables](/configure-builds/environment-variables/) two different ways: * [`process.env`](https://nodejs.org/api/process.html#processenv) : includes all Netlify build environment variables and any variables you declare using the Netlify UI or TOML. We recommend you use this when you only need to **get** values during the build process. * [`netlifyConfig.build.environment`](#netlifyconfig) : includes only the variables you declare using the Netlify UI or TOML. We recommend you use this when you need to **modify** values during the build process. Visit our Forums for a verified Support Guide on [how to access environment variables during your site build](https://answers.netlify.com/t/support-guide-using-environment-variables-on-netlify-correctly/267) . [#](#plugin-methods) Plugin methods ------------------------------------ We’ve provided a number of utilities and API methods to assist you in writing plugins. ### [#](#utilities) Utilities Several utilities are provided with the `utils` argument to event handlers: * **[`build`](#error-reporting) :** used to report errors or cancel builds * **[`status`](#logging) :** used to display information in the deploy summary * **[`cache`](https://github.com/netlify/build/blob/main/packages/cache-utils/README.md) :** used to cache files between builds * **[`run`](https://github.com/netlify/build/blob/main/packages/run-utils/README.md) :** used to run commands and processes * **[`git`](https://github.com/netlify/build/blob/main/packages/git-utils/README.md) :** used to retrieve Git-related information such as the list of modified/created/deleted files * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = async function({ utils: { build, status, cache, run, git } }) { await run.command("eslint src/ test/"); } // index.js module.exports = { onPreBuild: async ({ utils: { build, status, cache, run, git } }) => { await run.command("eslint src/ test/"); }, } ### [#](#error-reporting) Error reporting Exceptions thrown inside event handlers are reported in logs as bugs. Instead of using the `onError` event to handle exceptions, plugins should rely on `try`/`catch`/`finally` blocks and use `utils.build`: * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ utils }) { try { badMethod(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE"); } } // index.js module.exports = { onPreBuild: ({ utils }) => { try { badMethod(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE"); } }, } The following methods are available depending on the error’s type: * **`utils.build.failBuild("YOUR_MESSAGE")`:** method that fails the build - the build in your dashboard would show “Failed”. Use this to indicate something went wrong. * **`utils.build.failPlugin("YOUR_MESSAGE")`:** method that fails the plugin but not the build. * **`utils.build.cancelBuild("YOUR_MESSAGE")`:** method that cancels the build - the dashboard would show “Cancelled” for that build. Use this to indicate that the build is being cancelled as planned. `utils.build.failBuild()`, `utils.build.failPlugin()` and `utils.build.cancelBuild()` can specify an options object with the following properties: * **`error`:** original `Error` instance. Its stack trace will be preserved and its error message will be appended to the `"YOUR_MESSAGE"` argument. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ utils }) { try { badMethod(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE", { error }); } } // index.js module.exports = { onPreBuild: ({ utils }) => { try { badMethod(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE", { error }); } }, } ### [#](#logging) Logging Anything logged to the console will be printed in the build logs. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function() { console.log("This is printed in the build logs"); } // index.js module.exports = { onPreBuild() { console.log("This is printed in the build logs"); }, } If you’d prefer to make the information more visible, `utils.status.show()` can be used to display them in the [deploy summary](/site-deploys/overview/#deploy-summary) instead. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = function({ utils }) { utils.status.show({ // Optional. Default to the plugin’s name followed by a generic title. title: "Main title", // Required. summary: "Message below the title", // Optional. Empty by default. text: "Detailed information shown in a collapsible section", }); } // index.js module.exports = { onPreBuild({ utils }) { utils.status.show({ // Optional. Default to the plugin’s name followed by a generic title. title: "Main title", // Required. summary: "Message below the title", // Optional. Empty by default. text: "Detailed information shown in a collapsible section", }); }, } Only one status is shown per plugin. Calling `utils.status.show()` twice overrides the previous status. This is meant for successful information. Errors should be reported [with `utils.build.*` instead](#error-reporting) . ### [#](#asynchronous-code) Asynchronous code Asynchronous code can be achieved by using `async` methods: * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = async function({ utils }) { try { await doSomethingAsync(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE", { error }); } } // index.js module.exports = { onPreBuild: async ({ utils }) => { try { await doSomethingAsync(); } catch (error) { utils.build.failBuild("YOUR_FAILURE_MESSAGE", { error }); } }, } Any thrown `Error` or rejected `Promise` that is not handled by [`utils.build`](#error-reporting) will be shown in the build logs as a plugin bug. * Loading error: Refresh the page to access this code sample // index.js export const onPreBuild = async function({ utils }) { // Any error thrown inside this function will be shown // in the build logs as a plugin bug. await doSomethingAsync(); } // index.js module.exports = { onPreBuild: async ({ utils }) => { // Any error thrown inside this function will be shown // in the build logs as a plugin bug. await doSomethingAsync(); }, } Plugins end as soon as their methods end. Therefore you should `await` any asynchronous operation. The following examples show invalid code and the way to fix it. * Loading error: Refresh the page to access this code sample // index.js // Example of how to use callbacks. const { promisify } = require("util"); // VALID EXAMPLE: please use this. // This callback will be awaited. export const onPostBuild = async function({ utils }) { const response = await promisify(doSomethingAsync)(); console.log(response); } // INVALID EXAMPLE: do not use this. // This callback will not be awaited. export const onPostBuild = function({ utils }) { doSomethingAsync((error, response) => { console.log(response); }) } // index.js // Example of how to use callbacks. const { promisify } = require("util"); module.exports = { // VALID EXAMPLE: please use this. // This callback will be awaited. onPostBuild: async ({ utils }) => { const response = await promisify(doSomethingAsync)(); console.log(response); }, // INVALID EXAMPLE: do not use this. // This callback will not be awaited. onPreBuild: ({ utils }) => { doSomethingAsync((error, response) => { console.log(response); }) }, } * Loading error: Refresh the page to access this code sample // index.js // Example of how to use events. const pEvent = require("p-event"); // VALID EXAMPLE: please use this. // This event will be awaited. export const onPreBuild = async function({ utils }) { const emitter = doSomethingAsync(); emitter.start(); const response = await pEvent(emitter, "response"); console.log(response); } // INVALID EXAMPLE: do not use this. // This event will not be awaited. export const onPreBuild = function({ utils }) { const emitter = doSomethingAsync(); emitter.on("response", response => { console.log(response) }); emitter.start() } // index.js // Example of how to use events. const pEvent = require("p-event"); module.exports = { // VALID EXAMPLE: please use this. // This event will be awaited. onPreBuild: async ({ utils }) => { const emitter = doSomethingAsync(); emitter.start(); const response = await pEvent(emitter, "response"); console.log(response); }, // INVALID EXAMPLE: do not use this. // This event will not be awaited. onPreBuild: ({ utils }) => { const emitter = doSomethingAsync(); emitter.on("response", response => { console.log(response) }); emitter.start(); }, } * Loading error: Refresh the page to access this code sample // index.js // Example of how to use `Array.forEach()`. // VALID EXAMPLE: please use this. // This callback will be awaited. export const onPostBuild = async function({ utils }) { await Promise.all( array.map(async () => { await doSomethingAsync() }), ); } // INVALID EXAMPLE: do not use this. // This callback will not be awaited. export const onPostBuild = function({ utils }) { array.forEach(async () => { await doSomethingAsync(); }); } // index.js // Example of how to use `Array.forEach()`. module.exports = { // VALID EXAMPLE: please use this. // This callback will be awaited. onPostBuild: async ({ utils }) => { await Promise.all( array.map(async () => { await doSomethingAsync(); }), ); }, // INVALID EXAMPLE: do not use this. // This callback will not be awaited. onPreBuild: ({ utils }) => { array.forEach(async () => { await doSomethingAsync(); }); }, } ### [#](#dynamic-events) Dynamic events Some plugins trigger different events depending on the user’s `inputs`. This can be achieved by returning the plugin object from a function instead. * Loading error: Refresh the page to access this code sample // index.js export default function helloWorldPlugin(inputs) { if (inputs.before) { return { onPreBuild: () => { console.log("Hello world from onPreBuild event!"); }, } } else { return { onPostBuild: () => { console.log("Hello world from onPostBuild event!"); }, } } }; // index.js module.exports = function helloWorldPlugin(inputs) { if (inputs.before) { return { onPreBuild: () => { console.log("Hello world from onPreBuild event!"); }, } } else { return { onPostBuild: () => { console.log("Hello world from onPostBuild event!"); }, } } } Last updated: October 2, 2024 ← [Build Plugins](/build-plugins/) [Share Build Plugins](/build-plugins/share-plugins/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Netlify Blobs | Netlify Docs With Netlify Blobs, you can store and retrieve [blobs](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and unstructured data. You can also use this feature as a simple key/value store or basic database. Netlify Blobs is a highly-available data store optimized for frequent reads and infrequent writes. For maximum flexibility, it offers a [configurable consistency model](/blobs/overview/#consistency) . If multiple write calls to the same key are issued, the last write wins. We automatically handle provisioning, configuration, and access control for you. This integrated zero-configuration solution helps you focus on building business value in your project rather than toil on setting up and scaling a separate blob storage solution. [#](#overview) Overview ------------------------ Each blob belongs to a single site. A site can have multiple namespaces for blobs. We call these _stores_. This allows you to, for example, have the key `nails` exist as an object in a store for `beauty` and separately as an object in a store for `construction` with different data. Every blob must be associated with a store, even if a site is not using multiple namespaces. You can perform CRUD operations for Netlify Blobs from the following Netlify features: * [Functions](/functions/overview/) * [Edge Functions](/edge-functions/overview/) * [Build Plugins](/build-plugins/) - note that though a plugin can read from any stores on the site, a plugin can write to only [deploy-specific stores](#deploy-specific-stores) * [Netlify CLI](/cli/get-started/) - visit the [CLI command reference](https://cli.netlify.com/commands/blobs/) for details You can also: * write to deploy-specific stores using [file-based uploads](#file-based-uploads) * browse and download blobs in the [Netlify Blobs UI](#netlify-blobs-ui) [#](#use-cases) Use cases -------------------------- Netlify Blobs is a platform primitive that developers and frameworks can use as a building block for many different purposes. Here are a few [examples of powerful patterns](https://www.netlify.com/blog/introducing-netlify-blobs-beta/) that you can use: * **Data store for functions.** With [Background Functions](/functions/background-functions/) , you can trigger asynchronous serverless workflows for long-running operations like generating a site map, processing media assets, or sending emails in bulk. You can then use Netlify Blobs to persist the output of those computations. * **Processing user uploads.** If your application takes user submissions, like reviews on a product page or image files for a gallery, Netlify Blobs can store that data. When paired with Functions or Edge Functions, you can create an endpoint to receive an upload, validate the contents, and persist the validated data. For more advanced use cases — such as those that require complex queries, concurrency control, or a relational data model — explore our [integrations with the best-in-class database vendors](https://www.netlify.com/integrations/database-and-backend/) . [#](#netlify-blobs-api) Netlify Blobs API ------------------------------------------ To use the Netlify Blobs API, first install the `@netlify/blobs` module using the [package manager of your choice](/configure-builds/manage-dependencies/#javascript-dependencies) : npm install @netlify/blobs Then use the below methods in your functions, edge functions, or build plugins. ### [#](#set) `set` Creates an object with the given key and value. If an entry with the given key already exists, its value is overwritten. set(key, value, { metadata? }) It takes the following parameters: * **`key`:** a string representing the object key * **`value`:** the value as an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) , [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) , or string * **`metadata`** (optional)**:** a JSON object with arbitrary metadata to attach to the object * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.set("nails", "For general carpentry"); const beauty = getStore("beauty"); await beauty.set("nails", "For formal events", { metadata: { material: "acrylic", sale: true }, }); return new Response("Nail blobs set for Construction and Beauty stores"); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.set("nails", "For general carpentry"); const beauty = getStore("beauty"); await beauty.set("nails", "For formal events", { metadata: { material: "acrylic", sale: true }, }); return new Response("Nail blobs set for Construction and Beauty stores"); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const construction = getDeployStore("construction"); await construction.set("nails", "For general carpentry"); const beauty = getDeployStore("beauty"); await beauty.set("nails", "For formal events", { metadata: { material: "acrylic", sale: true }, }); console.log("Nail blobs set for this deploy in Construction and Beauty stores"); }; ### [#](#setjson) `setJSON` Convenience method for creating a JSON-serialized object. If an entry with the given key already exists, its value is overwritten. setJSON(key, value, { metadata? }) It takes the following parameters: * **`key`:** a string representing the object key * **`value`:** any value that is [serializable to JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) * **`metadata`** (optional)**:** a JSON object with arbitrary metadata to attach to the object * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.setJSON("nails", { type: "common", finish: "bright" }); return new Response("Nail blob set in JSON for Construction store"); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.setJSON("nails", { type: "common", finish: "bright" }); return new Response("Nail blob set in JSON for Construction store"); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const construction = getDeployStore("construction"); await construction.setJSON("nails", { type: "common", finish: "bright" }); console.log("Nail blob set in JSON for this deploy"); }; ### [#](#get) `get` Retrieves an object with the given key. get(key, { consistency?, type? }) It takes the following parameters: * **`key`:** a string representing the object key * **`consistency`** (optional)**:** a string representing the [consistency model](#consistency) for the operation * **`type`** (optional)**:** the format in which the object should be returned — the default format is a string but you can specify one of the following values instead: * **`arrayBuffer`:** returns the entry as an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) * **`blob`:** returns the entry as a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) * **`json`:** parses the entry as JSON and returns the resulting object * **`stream`:** returns the entry as a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) * **`text`:** default, returns the entry as a string of plain text It returns the blob in the format specified by `type`. If an object with the given key is not found, `null` is returned. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); const entry1 = await construction.get("nails"); const beauty = getStore("beauty"); const entry2 = await beauty.get("nails"); const text = [entry1, entry2].join(" "); return new Response(text); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); const entry1 = await construction.get("nails"); const beauty = getStore("beauty"); const entry2 = await beauty.get("nails"); const text = [entry1, entry2].join(" "); return new Response(text); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const construction = getDeployStore("construction"); const entry1 = await construction.get("nails"); const beauty = getDeployStore("beauty"); const entry2 = await beauty.get("nails"); const text = [entry1, entry2].join(" "); console.log(text); }; ### [#](#getwithmetadata) `getWithMetadata` Retrieves an object along with its metadata. getWithMetadata(key, { consistency?, etag?, type? }) It takes the following parameters: * **`key`:** a string representing the object key * **`consistency`** (optional)**:** a string representing the [consistency model](#consistency) for the operation * **`etag`** (optional)**:** an opaque quoted string, possibly prefixed by a weakness indicator, representing the [`ETag` value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) of any version of this blob you may have cached — this allows you to do [conditional requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests) * **`type`** (optional)**:** the format in which the object should be returned — the default format is a string but you can specify one of the following values instead: * **`arrayBuffer`:** returns the entry as an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) * **`blob`:** returns the entry as a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) * **`json`:** parses the entry as JSON and returns the resulting object * **`stream`:** returns the entry as a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) * **`text`:** default, returns the entry as a string of plain text It returns an object with the following properties: * **`data`:** the blob contents in the format specified by the `type` parameter, or `null` if the `etag` property is the same as the `etag` parameter (meaning the cached object is still fresh) * **`etag`:** an opaque quoted string, possibly prefixed by a weakness indicator, representing the [`ETag` value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) of the object * **`metadata`:** object with arbitrary metadata If an object with the given key is not found, `null` is returned. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const { data, etag, metadata } = await beauty.getWithMetadata("nails"); return Response.json({ data, etag, metadata }); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const { data, etag, metadata } = await beauty.getWithMetadata("nails"); return Response.json({ data, etag, metadata }); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const beauty = getDeployStore("beauty"); const entry = await beauty.getWithMetadata("nails"); console.log(entry.data, entry.etag, entry.metadata); }; * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { // Mock implementation of a system for locally persisting blobs and their etags const cachedETag = getFromMockCache("nails"); const beauty = getStore("beauty"); // Get entry from the blob store only if its ETag is different from the one you // have locally, which means the entry has changed since you last retrieved it. // Compare the whole value including surrounding quotes and any weakness prefix. const { data, etag } = await beauty.getWithMetadata("nails", { etag: cachedETag, }); if (etag === cachedETag) { // `data` is `null` because the local blob is fresh return new Response("Still fresh"); } // `data` contains the new blob, store it locally alongside the new ETag writeInMockCache("nails", data, etag); return new Response("Updated"); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { // Mock implementation of a system for locally persisting blobs and their etags const cachedETag = getFromMockCache("nails"); const beauty = getStore("beauty"); // Get entry from the blob store only if its ETag is different from the one you // have locally, which means the entry has changed since you last retrieved it. // Compare the whole value including surrounding quotes and any weakness prefix. const { data, etag } = await beauty.getWithMetadata("nails", { etag: cachedETag, }); if (etag === cachedETag) { // `data` is `null` because the local blob is fresh return new Response("Still fresh"); } // `data` contains the new blob, store it locally alongside the new ETag writeInMockCache("nails", data, etag); return new Response("Updated"); }; You can use object metadata to create client-side expiration logic. To delete blobs you consider expired, do the following: 1. [`set` your objects with metadata](#set) that you can base the expiration logic on, such as a timestamp 2. `getWithMetadata` to check if an object is expired 3. [`delete`](#delete) the expired object * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); // Set the entry with an `expiration` metadata property await beauty.set("nails", "For formal events", { metadata: { expiration: new Date("2024-01-01").getTime() } }); // Read the entry and compare the `expiration` metadata // property against the current timestamp const entry = await beauty.getWithMetadata("nails"); if (entry === null) { return new Response("Blob does not exist"); } const { expiration } = entry.metadata; // If the expiration date is in the future, it means // the blob is still fresh, so return it if (expiration && expiration < Date.now()) { return new Response(entry.data); } // Delete the expired entry await beauty.delete("nails"); return new Response("Blob has expired"); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); // Set the entry with an `expiration` metadata property await beauty.set("nails", "For formal events", { metadata: { expiration: new Date("2024-01-01").getTime() } }); // Read the entry and compare the `expiration` metadata // property against the current timestamp const entry = await beauty.getWithMetadata("nails"); if (entry === null) { return new Response("Blob does not exist"); } const { expiration } = entry.metadata; // If the expiration date is in the future, it means // the blob is still fresh, so return it if (expiration && expiration < Date.now()) { return new Response(entry.data); } // Delete the expired entry await beauty.delete("nails"); return new Response("Blob has expired"); }; ### [#](#getmetadata) `getMetadata` Retrieves the metadata for an object, if the object exists. This method is useful to check if a blob exists without actually retrieving it and having to download a potentially large blob over the network. getMetadata(key, { consistency?, etag?, type? }) It takes the following parameters: * **`key`:** a string representing the object key * **`consistency`** (optional)**:** a string representing the [consistency model](#consistency) for the operation * **`etag`** (optional)**:** an opaque quoted string, possibly prefixed by a weakness indicator, representing the [`ETag` value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) of any version of this blob you may have cached — this allows you to do [conditional requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests) * **`type`** (optional)**:** the format in which the object should be returned — the default format is a string but you can specify one of the following values instead: * **`arrayBuffer`:** returns the entry as an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) * **`blob`:** returns the entry as a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) * **`json`:** parses the entry as JSON and returns the resulting object * **`stream`:** returns the entry as a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) * **`text`:** default, returns the entry as a string of plain text It returns an object with the following properties: * **`metadata`:** object with arbitrary metadata * **`etag`:** an opaque quoted string, possibly prefixed by a weakness indicator, representing the [`ETag` value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) of the object If an object with the given key is not found, `null` is returned. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const entry = await beauty.getMetadata("nails"); if (entry === null) { return new Response("Blob does not exist"); } return Response.json({ etag: entry.etag, metadata: entry.metadata }); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const entry = await beauty.getMetadata("nails"); if (entry === null) { return new Response("Blob does not exist"); } return Response.json({ etag: entry.etag, metadata: entry.metadata }); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const beauty = getDeployStore("beauty"); const entry = await beauty.getMetadata("nails"); console.log(entry.etag, entry.metadata); }; ### [#](#list) `list` Returns a list of blobs in a given store. list({ directories?, paginate?, prefix? }) It takes the following parameters: * **`directories`** (optional)**:** a boolean that indicates whether keys with the `/` character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them * **`paginate`** (optional)**:** a boolean that specifies whether you want to [handle pagination manually](#manual-pagination) — by default, it is handled automatically * **`prefix`** (optional)**:** a string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned It returns an object with the following properties: * **`blobs`:** an array of blobs that match the query parameters, shown as objects with `etag` and `key` properties, which represent an object’s [`ETag` value](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) and key, respectively * **`directories`:** an array of strings representing any directories matching the query parameters * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const { blobs } = await beauty.list(); // [ { etag: "\"etag1\"", key: "nails" }, { etag: "W/\"etag2\"", key: "hair" } ] console.log(blobs); return new Response(`Found ${blobs.length} blobs`); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const beauty = getStore("beauty"); const { blobs } = await beauty.list(); // [ { etag: "\"etag1\"", key: "nails" }, { etag: "W/\"etag2\"", key: "hair" } ] console.log(blobs); return new Response(`Found ${blobs.length} blobs`); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const beauty = getDeployStore("beauty"); const { blobs } = await beauty.list(); // [ { etag: "\"etag1\"", key: "nails" }, { etag: "W/\"etag2\"", key: "hair" } ] console.log(blobs); }; Optionally, you can group blobs together under a common prefix and then browse them hierarchically when listing a store. This is similar to grouping files in a directory. To browse hierarchically, do the following: 1. Group keys hierarchically with the `/` character in your key names. 2. List entries hierarchically with the `directories` parameter. 3. Drill down into a specific directory with the `prefix` parameter. Take the following set of keys as an example: cats/shorthair.jpg cats/longhair.jpg dogs/beagle.jpg dogs/corgi.jpg bird.jpg By default, `list` will return all five keys. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs } = await animals.list(); // [\ // { etag: "\"etag1\"", key: "cats/shorthair.jpg" },\ // { etag: "\"etag2\"", key: "cats/longhair.jpg" },\ // { etag: "\"etag3\"", key: "dogs/beagle.jpg" },\ // { etag: "\"etag4\"", key: "dogs/corgi.jpg" },\ // { etag: "\"etag5\"", key: "bird.jpg" },\ // ] console.log(blobs); return new Response(`Found ${blobs.length} blobs`); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs } = await animals.list(); // [\ // { etag: "\"etag1\"", key: "cats/shorthair.jpg" },\ // { etag: "\"etag2\"", key: "cats/longhair.jpg" },\ // { etag: "\"etag3\"", key: "dogs/beagle.jpg" },\ // { etag: "\"etag4\"", key: "dogs/corgi.jpg" },\ // { etag: "\"etag5\"", key: "bird.jpg" },\ // ] console.log(blobs); return new Response(`Found ${blobs.length} blobs`); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const animals = getDeployStore("animals"); const { blobs } = await animals.list(); // [\ // { etag: "\"etag1\"", key: "cats/shorthair.jpg" },\ // { etag: "\"etag2\"", key: "cats/longhair.jpg" },\ // { etag: "\"etag3\"", key: "dogs/beagle.jpg" },\ // { etag: "\"etag4\"", key: "dogs/corgi.jpg" },\ // { etag: "\"etag5\"", key: "bird.jpg" },\ // ] console.log(blobs); }; To list entries hierarchically, set the `directories` parameter to `true`. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs, directories } = await animals.list({ directories: true }); // [ { etag: "\"etag5\"", key: "bird.jpg" } ] console.log(blobs); // [ "cats", "dogs" ] console.log(directories); return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs, directories } = await animals.list({ directories: true }); // [ { etag: "\"etag5\"", key: "bird.jpg" } ] console.log(blobs); // [ "cats", "dogs" ] console.log(directories); return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const animals = getDeployStore("animals"); const { blobs, directories } = await animals.list({ directories: true }); // [ { etag: "\"etag5\"", key: "bird.jpg" } ] console.log(blobs); // [ "cats", "dogs" ] console.log(directories); }; To drill down into a directory and get a list of its items, set the `prefix` parameter to the directory name. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs, directories } = await animals.list({ directories: true, prefix: "cats/", }); // [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ] console.log(blobs); // [ ] console.log(directories); return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const animals = getStore("animals"); const { blobs, directories } = await animals.list({ directories: true, prefix: "cats/", }); // [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ] console.log(blobs); // [ ] console.log(directories); return new Response(`Found ${blobs.length} blobs and ${directories.length} directories`); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const animals = getDeployStore("animals"); const { blobs, directories } = await animals.list({ directories: true, prefix: "cats/", }); // [ { etag: "\"etag1\"", key: "cats/shorthair.jpg" }, { etag: "\"etag2\"", key: "cats/longhair.jpg" } ] console.log(blobs); // [ ] console.log(directories); }; Note that the prefix includes a trailing slash. This ensures that only entries under the `cats` directory are returned. Without a trailing slash, other keys like `catsuit` would also be returned. For performance reasons, the server groups results into pages of up to 1,000 entries. By default, the `list` method automatically retrieves all pages, meaning you’ll always get the full list of results. To handle pagination manually, set the `paginate` parameter to `true`. This makes `list` return an [`AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator) , which lets you take full control over the pagination process. This means you can fetch only the data you need when you need it. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const store = getStore("animals"); let blobCount = 0; for await (const entry of store.list({ paginate: true })) { blobCount += entry.blobs.length; console.log(entry.blobs); } return new Response(`Found ${blobCount} blobs`); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const store = getStore("animals"); let blobCount = 0; for await (const entry of store.list({ paginate: true })) { blobCount += entry.blobs.length; console.log(entry.blobs); } return new Response(`Found ${blobCount} blobs`); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const store = getDeployStore("animals"); let blobCount = 0; for await (const entry of store.list({ paginate: true })) { blobCount += entry.blobs.length; console.log(entry.blobs); } console.log(`Found ${blobCount} blobs`); }; ### [#](#liststores) `listStores` Returns a list of stores for a site. Does not include [deploy-specific stores](/blobs/overview/#deploy-specific-stores) . listStores({ paginate? }) It takes the following parameter: * **`paginate`** (optional)**:** a boolean that specifies whether you want to [handle pagination manually](#manual-store-pagination) — by default, it is handled automatically It returns an object with the following array: * **`stores`:** an array of strings representing any stores matching the query parameters * Loading error: Refresh the page to access this code sample import { listStores } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const { stores } = await listStores(); // [ "beauty", "construction" ] console.log(stores); return new Response(`Found ${stores.length} stores`); }; import { listStores } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const { stores } = await listStores(); // [ "beauty", "construction" ] console.log(stores); return new Response(`Found ${stores.length} stores`); }; import { listStores } from "@netlify/blobs"; export const onPostBuild = async () => { const { stores } = await listStores(); // [ "beauty", "construction" ] console.log(stores); }; For performance reasons, the server groups results into pages of up to 1,000 stores. By default, the `listStores` method automatically retrieves all pages, meaning you’ll always get the full list of results. To handle pagination manually, set the `paginate` parameter to `true`. This makes `listStores` return an [`AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator) , which lets you take full control over the pagination process. This means you can fetch only the data you need when you need it. * Loading error: Refresh the page to access this code sample import { listStores } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { let storeCount = 0; for await (const entry of listStores({ paginate: true })) { storeCount += entry.stores.length; console.log(entry.stores); } return new Response(`Found ${storeCount} stores`); }; import { listStores } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { let storeCount = 0; for await (const entry of listStores({ paginate: true })) { storeCount += entry.stores.length; console.log(entry.stores); } return new Response(`Found ${storeCount} stores`); }; import { listStores } from "@netlify/blobs"; export const onPostBuild = async () => { const { stores } = await listStores({ paginate: true, }); let storeCount = 0; for await (const entry of stores) { storeCount += entry.stores.length; console.log(entry.stores); } console.log(`Found ${storeCount} stores`); }; ### [#](#delete) `delete` Deletes an object with the given key, if one exists. delete(key) It takes the following parameters: * **`key`:** a string representing the object key The return value is always `undefined`, regardless of whether an object was actually deleted. * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.delete("nails"); const beauty = getStore("beauty"); await beauty.delete("nails"); return new Response("Nail blobs deleted from Construction and Beauty stores"); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const construction = getStore("construction"); await construction.delete("nails"); const beauty = getStore("beauty"); await beauty.delete("nails"); return new Response("Nail blobs deleted from Construction and Beauty stores"); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const construction = getDeployStore("construction"); await construction.delete("nails"); const beauty = getDeployStore("beauty"); await beauty.delete("nails"); console.log("Nail blobs deleted for this deploy from Construction and Beauty stores"); }; [#](#file-based-uploads) File-based uploads -------------------------------------------- With file-based uploads, you can write blobs to [deploy-specific stores](#deploy-specific-stores) after the build completes and before the deploy starts. This can be useful for authors of frameworks and other tools integrating with Netlify as it does not require a build plugin. To make file-based uploads, place blob files in `.netlify/blobs/deploy` in your site’s [base directory](/configure-builds/overview/#definitions) . Netlify uploads these files to blob storage maintaining their directory structure. Here is an example file tree: .netlify/ ├─ blobs/ | ├─ deploy/ │ | ├─ beauty/ │ │ | └─ nails.jpg │ | ├─ construction/ │ │ | └─ nails.jpg │ | └─ dog.jpg This uploads the following blobs: * `beauty/nails.jpg` * `construction/nails.jpg` * `dog.jpg` To attach metadata to a blob, include a JSON file that prefixes the corresponding blob filename with `$` and has a `.json` extension. For example: .netlify/ ├─ blobs/ | ├─ deploy/ │ | ├─ beauty/ │ │ | ├─ nails.jpg │ │ | └─ $nails.jpg.json │ | ├─ construction/ │ │ | └─ nails.jpg │ | ├─ dog.jpg │ | ├─ mouse.jpg │ | └─ $mouse.jpg.json This uploads the following blobs: * `beauty/nails.jpg` with the metadata from `beauty/$nails.jpg.json` * `construction/nails.jpg` without metadata * `dog.jpg` without metadata * `mouse.jpg` with the metadata from `$mouse.jpg.json` Metadata files must contain valid JSON or the deploy will fail. Here’s an example of valid JSON metadata: { "type": "common", "finish": "bright" } [#](#consistency) Consistency ------------------------------ By default, the Netlify Blobs API uses an [eventual consistency](https://en.wikipedia.org/wiki/Eventual_consistency) model, where data is stored in a single region and cached at the edge for fast access across the globe. When a blob is added, it becomes globally available immediately. Updates and deletions are guaranteed to be propagated to all edge locations within 60 seconds. You can configure this behavior and opt-in to strong consistency with the [Netlify Blobs API](#netlify-blobs-api) , either for an entire store or for individual read operations. [Netlify CLI](https://cli.netlify.com/commands/blobs/) always uses strong consistency. Choosing the right consistency model depends on your use case and each option comes with tradeoffs: * if it’s important for your application that updates and deletions become immediately available to all readers, you should consider using `strong` consistency, which comes with the cost of slower reads * if that is not a hard requirement and you’re optimizing for fast reads, you should consider using `eventual` consistency * Loading error: Refresh the page to access this code sample import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const store = getStore({ name: "animals", consistency: "strong" }); await store.set("dog", "🐶"); // This is a strongly-consistent read. const dog = await store.get("dog"); return new Response(dog); }; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const store = getStore("animals"); await store.set("dog", "🐶"); // This is an eventually-consistent read. const dog1 = await store.get("dog"); // This is a strongly-consistent read. const dog2 = await store.get("dog", { consistency: "strong" }); return new Response(dog1 + dog2); }; [#](#netlify-blobs-ui) Netlify Blobs UI ---------------------------------------- In addition to using the Netlify Blobs API to [list](#list) and [get](#get) blobs, you can use the Netlify UI to browse and download blobs. To explore and retrieve your site’s blobs: 1. In the Netlify UI, go to the **Blobs** page for your site. 2. If your site has more than one store, select the store of interest. ![](/images/blobs-select-store.png) 3. Then, drill into directories to explore the blobs in the store or **Download** an individual blob to examine it. [#](#sensitive-data) Sensitive data ------------------------------------ You can store sensitive data with Netlify Blobs. To keep your data secure, we encrypt your blobs at rest and in transit. Your blobs can only be accessed through your own site. You are responsible for making sure the code you use to access your blobs doesn’t allow data to leak. We recommend that you consider the following best practices: * Do not allow incoming requests for arbitrary keys if you have sensitive data. Treat user input as unsafe and scope your keys with something that callers cannot tamper with. * Review the code of any [build plugin you install from the npm public registry](/build-plugins/#file-based-installation) to make sure it doesn’t have malicious blob interactions. Visit our [security checklist](/platform/security-checklist/#recommended-security-measures) for general security measures we recommend you consider for your site. [#](#deploy-specific-stores) Deploy-specific stores ---------------------------------------------------- The namespaces you make with `getStore` are shared across all deploys of your site. This is required when using Netlify CLI and desirable for most use cases with functions and edge functions because it means that a new production deploy can read previously written data without you having to replicate blobs for each new production deploy. This also means you can test your Deploy Previews with production data. This does, however, mean that you should be careful to avoid scenarios such as a branch deploy deleting blobs that your published deploy depends on. As mentioned above, build plugins and file-based uploads must write to deploy-specific stores. This requirement makes it so that a deploy that fails cannot overwrite production data. To make a deploy-specific namespace with the Netlify Blobs API, use the `getDeployStore` method. * Loading error: Refresh the page to access this code sample import { getDeployStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const store = getDeployStore("construction"); await store.set("nails", "For general carpentry"); return new Response("Nail blob set for this deploy"); }; import { getDeployStore } from "@netlify/blobs"; import type { Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { const store = getDeployStore("construction"); await store.set("nails", "For general carpentry"); return new Response("Nail blob set for this deploy"); }; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const store = getDeployStore("construction"); await store.set("nails", "For general carpentry"); console.log("Nail blob set for this deploy"); }; In general, blobs in deploy-specific stores are managed by Netlify like other atomic deploy assets. This means they’re kept in sync with their relative deploys if you do a [rollback](/site-deploys/manage-deploys/#rollbacks) and that they’re cleaned up with [automatic deploy deletion](/site-deploys/manage-deploys/#automatic-deploy-deletion) . However, [downloading a deploy](/site-deploys/manage-deploys/#download-a-deploy) does not download deploy-specific blobs, and [locking a published deploy](/site-deploys/manage-deploys/#lock-a-published-deploy) does not prevent you from writing to associated deploy-specific stores. [#](#requirements-and-limitations) Requirements and limitations ---------------------------------------------------------------- Keep the following requirements in mind while working with Netlify Blobs: * Netlify Blobs uses the [web platform `fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) to make HTTP calls, so Fetch API support is required. This is included with Node.js 18. If for some reason you can’t use Node.js 18, you can provide your own Fetch API support by supplying a `fetch` property to the `getStore` or `getDeployStore` method. * File-based uploads require [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) or [CLI deploys](/cli/get-started/#manual-deploys) . * Loading error: Refresh the page to access this code sample import { fetch } from "whatwg-fetch"; import { getStore } from "@netlify/blobs"; import type { Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const construction = getStore({ fetch, name: "construction" }); const entry = await construction.get("nails"); return new Response(entry); }; import { fetch } from "whatwg-fetch"; import { getDeployStore } from "@netlify/blobs"; export const onPostBuild = async () => { const construction = getDeployStore({ name: "construction", fetch }); const entry = await construction.get("nails"); console.log(entry); }; Keep the following rules in mind when creating namespaces and blobs: * Store names cannot include the `/` character. * Store names cannot include the `:` character. * Store names cannot exceed 64 bytes. * Empty keys are not supported. * Object keys can include any Unicode characters. * Object keys cannot start with the `/` character. * Object keys cannot exceed 600 bytes. * An individual object’s total size cannot exceed 5 GB. * An individual object’s metadata size cannot exceed 2 KB. Most characters use 1 byte Most Unicode characters with UTF-8 encoding take 1 byte. So, for convenience, you can think of the above size limits as roughly a 64-character limit for store names and a 600-character limit for object keys. But, be aware that some characters take more than one byte. For example, `à` takes 2 bytes. Keep the following limitations in mind when working with Netlify Blobs: * Functions written in Go cannot access Netlify Blobs. * Cross-site blob access is not allowed. To share data between sites, you can use a [rewrite](/routing/redirects/rewrites-proxies/) on site A to a path on site B that pulls data from site B’s blobs. * Local development with Netlify Dev uses a sandboxed local store that does not support [file-based uploads](#file-based-uploads) . You cannot read production data during local development. * [Deploy deletion](/site-deploys/manage-deploys/#automatic-deploy-deletion) deletes deploy-specific stores only. For other stores, you can create [custom expiration logic](#expiration-logic) or [delete objects manually](#delete) as needed. * Netlify Blobs is not currently supported as part of our HIPAA-compliant hosting offering. For more information, visit our [Trust Center](https://trust-center.netlify-corp.com) and download our reference architecture for HIPAA-compliant composable sites on Netlify. [#](#troubleshooting-tips) Troubleshooting tips ------------------------------------------------ * **Last write wins.** If two overlapping calls try to write the same object, the last write wins. Netlify Blobs does not include a concurrency control mechanism. To manage the potential for race conditions, you can build an object-locking mechanism into your application. * **Store access depends on `@netlify/blobs` module version.** If you wrote to site-wide stores with `@netlify/blobs` version 6.5.0 or earlier, and you then upgrade the module to a more recent version, you will no longer be able to access data in those stores. This is due to an internal change to namespacing logic. You can migrate affected stores by running the following command in the project directory using the latest version of the [Netlify CLI](/cli/get-started/) . netlify recipes blobs-migrate YOUR_STORE_NAME This makes the migrated store accessible with `@netlify/blobs` module version 7.0.0 and later. Last updated: October 2, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Build hooks | Netlify Docs Build hooks are URLs you can use to trigger new builds and deploys. You can find them in **Site configuration \> Build & deploy \> Continuous deployment \> Build hooks** . ![](/images/configure-builds-build-hooks.png) Select **Add build hook** to create a new build hook. The build hook name is for your reference, and will display in your list of build hooks, as well as in the default deploy message for each deploy triggered by the hook. Select a branch to build by default. Only branches which have been deployed at least once will appear in this list. Upon saving your build hook settings, Netlify will give you a unique URL for that build hook. To trigger this hook, you need to send a POST request to that URL. In most cases, this POST request will be sent from a service you want to integrate with Netlify, but you can also send these requests yourself. For example, you can run a [curl](https://curl.haxx.se/) command from your terminal: curl -X POST -d '{}' https://api.netlify.com/build_hooks/5c23354f454e1350f8543e78 You can also test build hook requests with tools like [Postman](https://www.postman.com/) . Note Builds must be [active](/configure-builds/stop-or-activate-builds/) for build hooks to trigger builds of your site. [#](#parameters) Parameters ---------------------------- Build hooks accept the following optional URL query parameters to alter the behavior of the triggered build: * `trigger_branch`: parameter that specifies which repository branch the build will use. If the branch does not exist in your repository at the time of the build, the build will fail, with an error message in the build log. * `trigger_title`: parameter that specifies a title to replace the default deploy message in your site deploy list. * `clear_cache`: when set to `true`, this parameter triggers a build with a cleared cache. Here is an example build hook URL using these parameters: https://api.netlify.com/build_hooks/5c23354f454e1350f8543e78?trigger_branch=testing&trigger_title=triggered+by+This+Awesome+Service&clear_cache=true This would trigger a deploy from an existing branch called `testing`, with a custom message: `triggered by This Awesome Service`. ![Deploy list item for a branch deploy from the 'testing' branch, with message, 'triggered by This Awesome Service'.](/images/configure-builds-custom-hook-deploy.png) [#](#payload) Payload ---------------------- You can send a custom payload in your build hook POST request. The contents must be passed as a string, which will be URL-encoded and made available in the triggered build as an [environment variable](/configure-builds/environment-variables/#build-hook-metadata-and-payload) . You can access it in the build by using the variable `INCOMING_HOOK_BODY`. [#](#build-hooks-for-netlify-connect) Build hooks for Netlify Connect ---------------------------------------------------------------------- This product is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. When you [connect a site](/connect/manage-data-layers/manage-connected-sites/) to a data layer in [Netlify Connect](/connect/overview/) , Netlify automatically creates a build hook for that site. When data changes in that data layer, Netlify notifies the build hook and that automatically triggers a build and deploy of the site’s [production branch](/site-deploys/overview/#definitions) . Once you connect a site, the build hooks for the site include a `Netlify Connect - Data layer` build hook with the data layer ID as the value. This provides a convenient way on the site level to check whether a site is connected to a data layer. Expanding the build hook details reveals a link back to the data layer settings page. ![](/images/configure-builds-build-hooks-connect.png) Any deploys triggered by this build hook are labelled with `Deploy triggered by Netlify Connect` and include a link to the data layer that triggered the hook. ![](/images/configure-builds-build-hooks-connect-deploy.png) Build hooks created for Connect are not customizable or editable from the **Build Hooks** page. To delete a Connect-related build hook, [disconnect the site](/connect/manage-data-layers/manage-connected-sites/#disconnect-a-site) from your data layer. Last updated: May 29, 2024 ← [On-demand Builders](/configure-builds/on-demand-builders/) [Stop or activate builds](/configure-builds/stop-or-activate-builds/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Available software at build time | Netlify Docs These are the languages and tools available to your build during the build process. Our current build is based on Ubuntu version 24.04 (also called Noble Numbat) and includes the languages and software versions listed below. There are multiple ways to set the software and language version used for your builds. Learn more about [managing your build dependencies](/configure-builds/manage-dependencies/) . [#](#languages) Languages -------------------------- | | Default version | Available versions | Set the version using | | --- | --- | --- | --- | | [Node.js](https://nodejs.org/en) | `18` | Any version that `nvm` can install | In order of precedence: `.nvmrc` file, `.node-version` file, `NODE_VERSION` build environment variable, or the

**Dependency management**

section in the Netlify UI. For example, a node version set in `.nvmrc` will override the node version set in the Netlify UI. | | [Ruby](https://www.ruby-lang.org/en/) | `3.x` | Any [official Ruby version](https://www.ruby-lang.org/en/downloads/releases/) | Build environment variable `RUBY_VERSION` or `.ruby-version` file | | [Python](https://www.python.org/) | `3.x` | Any [official Python version](https://www.python.org/downloads/) | Build environment variable `PYTHON_VERSION`, `Pipfile` file, or `runtime.txt` file | | [PHP](https://www.php.net/) | `8.3` | `7.4`, `8.0`, `8.1`, `8.2`, `8.3` | Build environment variable `PHP_VERSION` | | [Go](https://go.dev/) | `1.x` | Any [official Go version](https://golang.org/dl/) | Build environment variable `GO_VERSION` | | [Java](https://www.java.com/en/) | `8` | | | | [Elixir](https://elixir-lang.org/) | `1.9.1` | | | | [Emacs](https://www.gnu.org/software/emacs/) | `26.3` | | | | [Erlang](https://www.erlang.org/) | `22.2` | | | | [Swift](https://developer.apple.com/swift/) | `N/A` | Any version that `swiftenv` can install `>= 5.0` | Build environment variable `SWIFT_VERSION`, or
`.swift-version` file | | [Rust](https://www.rust-lang.org/) | `N/A` | Any version that `rustup` can install | `Cargo.toml` file | [#](#tools) Tools ------------------ | | Available versions | Set the version using | | --- | --- | --- | | [Bun](https://bun.sh/) | `1.x` | | | [Cask](https://cask.readthedocs.io/en/latest/) | `latest` | | | [Composer](https://getcomposer.org/) | `latest` | | | [Deno](https://deno.com/) | `1.x` | | | [Doxygen](http://www.doxygen.org) | `1.9.8` | | | [GNU Make](https://www.gnu.org/software/make/) | `4.3` | | | [Hugo](https://gohugo.io/) | [Any version](https://github.com/gohugoio/hugo/releases) | Build environment variable `HUGO_VERSION` | | [Leiningen](https://leiningen.org/) | `stable` | | | [libvips](https://www.libvips.org) | `8.15.1` | | | [npm](https://www.npmjs.com/) | Corresponds with the installed Node.js version. | Build environment variable `NPM_VERSION` | | [pip](https://pip.pypa.io/en/stable/) | Corresponds with the installed Python version. | | | [Pipenv](https://pipenv.pypa.io/en/latest/) | Corresponds with the installed Python version. Defaults to `latest` | | | [pnpm](https://pnpm.io/) | Any version corepack can install. Defaults to `9.x` | `packageManager` field in your `package.json` file | | [Yarn](https://classic.yarnpkg.com/lang/en/) | Any version corepack can install. Defaults to `1.x` | `packageManager` field in your `package.json` file | | [Zola](https://www.getzola.org/) | Any version `binrc` can install. | Build environment variable `ZOLA_VERSION` | [#](#request-support-for-a-language-or-tool) Request support for a language or tool ------------------------------------------------------------------------------------ We love hearing from you and using your input to help us build a better web! Let us know about any missing tools and languages. You can reach us by opening a new request on [our Forums](https://answers.netlify.com/c/features/50) . [#](#report-a-bug) Report a bug -------------------------------- If you find an issue, let our support team know by opening a [support request](https://answers.netlify.com/c/netlify-support/48) in our Forums. For anything else, you can use the Docs feedback form on the bottom of this docs page as well to provide us feedback and tell us how we can improve! Last updated: January 6, 2025 ← [Build troubleshooting tips](/configure-builds/troubleshooting-tips/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Ignore builds | Netlify Docs With continuous deployment, Netlify attempts to ignore builds when they’re not required, only building when your site requires it. Depending on your [**Branches** settings](/site-deploys/overview/#branch-deploy-controls) , any time there is a change in a linked repository, Netlify tries to determine whether there are changes in the site’s [base directory](/configure-builds/overview/#definitions-1) by comparing the last known version of the files in that directory. If no change is detected, the build system cancels and essentially skips the build, returning early from the build process. To override the default behavior described above, you can use the `ignore` attribute in the [Netlify configuration file](/configure-builds/file-based-configuration/) . This setting allows you to specify a Node.js or Bash command that runs from the base directory and determines whether or not the site needs rebuilding. [#](#custom-ignore-command) Custom `ignore` command ---------------------------------------------------- The `ignore` command provides custom, programmatic control over builds. It can prevent bot-triggered builds, for example, or limit production deploys to certain days of the week. It can also account for times when you may still want to run a build when there’s a change outside of a base directory, for example, if there’s a change to `package.json` in the root directory. Things to note when constructing an `ignore` command: * An exit code of `1` indicates the contents have changed and the build process continues as usual. An exit code of `0` indicates that there are no changes and the build should stop. * The command is run with Bash. You can also [use Node.js](/configure-builds/ignore-builds/#skip-builds-based-on-branch-name) . * If the command references a separate file, the file path must start with `./`. * The `ignore` command won’t cancel a build triggered by a [build hook](/configure-builds/build-hooks/) , regardless of exit code. * Netlify can run an `ignore` command even if a [base directory](/configure-builds/overview/#definitions-1) isn’t set. * All paths in your `ignore` command should be absolute paths relative to the [base directory](/configure-builds/overview/#definitions) , which is the root by default (`/`). ### [#](#ignore-examples) `ignore` examples Want to customize the default ignore behavior? Check out the examples of custom `ignore` commands below. For more `ignore` examples, head over to our verified Support Guide on [using the `ignore` command](https://answers.netlify.com/t/support-guide-how-to-use-the-ignore-command/37517) . #### [#](#mimic-default-behavior) Mimic default behavior The Bash example below is an `ignore` command that roughly approximates the default ignore builds behavior. You can add to or adjust it to update the default check. The commands use read-only [environment variables for Git metadata](/configure-builds/environment-variables/#git-metadata) as well as the `CI` and `NETLIFY` [build environment variables](/configure-builds/environment-variables/) . [build] ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF" For this next example, consider a monorepo project set up like this, where `packages/blog-1` is the [package directory](/configure-builds/overview/#definitions) and the base directory is the repository root (`/`), by default. / ├─ package.json └─ packages/ ├─ blog-1/ │ ├─ package.json │ └─ netlify.toml ├─ common/ │ └─ package.json └─ blog-2/ ├─ package.json └─ netlify.toml The following `ignore` command example adapts the default behavior so that the build proceeds only if there are changes within the `blog-1` or `common` directories. [build] ignore = "git diff --quiet $CACHED_COMMIT_REF $COMMIT_REF packages/blog-1 packages/common" #### [#](#skip-builds-based-on-branch-name) Skip builds based on branch name The `ignore` command has access to a Node.js environment. This means if you want to prevent builds based on logic that’s hard to handle in Bash, you can use Node.js. This example skips builds for a specific branch by adding a Node.js script to the `ignore` command in `netlify.toml`. [build] ignore = "node ignore_build.js" `ignore_build.js` executes before any build logs run. If the branch name is `debug`, the exit code is set to `0`, which stops the build. // ignore_build.js process.exitCode = process.env.BRANCH.includes("debug") ? 0 : 1 There are a few things you should keep in mind when using Node.js with an `ignore` command. * [Node.js dependencies](/configure-builds/manage-dependencies/#javascript-dependencies) from the site’s `package.json` are not available. * `ignore` commands use Node.js 18. This Node.js version can’t be customized. This means if your site has a [custom Node.js version](/configure-builds/manage-dependencies/#node-js-and-javascript) , the custom version is not used in the `ignore` command. [#](#more-build-configuration-resources) More build configuration resources ---------------------------------------------------------------------------- * [Common framework configurations](/frameworks/) * [Monorepos](/configure-builds/monorepos/) * [JavaScript SPAs](/configure-builds/javascript-spas/) Last updated: July 19, 2024 ← [Monorepos](/configure-builds/monorepos/) [Manage dependencies](/configure-builds/manage-dependencies/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Build environment variables | Netlify Docs Netlify [environment variables](/environment-variables/overview/) are accessible during your build. This allows you to change behaviors based on deploy parameters or to include information you don’t want to save in your repository, such as API keys. This page describes how to create environment variables, the specific configuration and read-only variables that are available in the Netlify build environment, and how to use environment variables during the build process. [#](#declare-variables) Declare variables ------------------------------------------ You can [declare and set environment variables](/environment-variables/get-started/#create-environment-variables) using the Netlify UI, CLI, API, or a Netlify configuration file. If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** to be available to the build system. Visit the [environment variables overview](/environment-variables/overview/) to learn more about environment variables at Netlify. [#](#netlify-configuration-variables) Netlify configuration variables ---------------------------------------------------------------------- By setting custom values for certain reserved environment variables, you can change some aspects of your build, such as [language and dependency versions](/configure-builds/manage-dependencies/) . Links in the variable descriptions below provide more information about requirements, defaults, and accepted values. * **`NODE_VERSION`:** value that sets the [Node.js version](/configure-builds/manage-dependencies/#node-js-and-javascript) . * **`NODE_ENV`:** value that sets the [Node.js environment](/configure-builds/manage-dependencies/#node-js-environment) . * **`NPM_VERSION`:** value that sets the [npm version](/configure-builds/manage-dependencies/#npm) . * **`NPM_FLAGS`:** value passed as [flags on the `npm install` command](/configure-builds/manage-dependencies/#npm) . * **`NPM_TOKEN`:** used for [fetching private npm modules](/configure-builds/manage-dependencies/#npm) . If you use Yarn, use `YARN_NPM_AUTH_TOKEN` instead. * **`NETLIFY_USE_YARN`:** used to override the [default behavior for installing and running Yarn](/configure-builds/manage-dependencies/#yarn) . * **`YARN_VERSION`:** used to set the [Yarn version](/configure-builds/manage-dependencies/#yarn) . * **`YARN_FLAGS`:** passed as [flags on the `yarn` command](/configure-builds/manage-dependencies/#yarn) . * **`YARN_NPM_AUTH_TOKEN`:** used for [fetching private npm modules](/configure-builds/manage-dependencies/#yarn) with Yarn. * **`BUN_FLAGS`:** passed as [flags on the `bun install` command](/configure-builds/manage-dependencies/#bun) . * **`RUBY_VERSION`:** used to set the [Ruby version](/configure-builds/manage-dependencies/#ruby) . * **`PHP_VERSION`:** value that sets the PHP version. Default and available values are determined by the site [build-image](/configure-builds/overview/#build-image-selection) . * **`PNPM_FLAGS`:** passed as [flags on the `pnpm install` command](/configure-builds/manage-dependencies/#pnpm) . * **`PYTHON_VERSION`:** value that sets the [Python version](/configure-builds/manage-dependencies/#python) . * **`HUGO_VERSION`:** value that sets the [Hugo version](/frameworks/hugo/#hugo-version) . * **`SWIFT_VERSION`:** value that sets the [Swift version](/configure-builds/manage-dependencies/#swift) . * **`GO_VERSION`:** value that sets the Go version. Default and available values are determined by the site [build-image](/configure-builds/overview/#build-image-selection) . * **`NETLIFY_NEXT_PLUGIN_SKIP`:** when set to `true` for a Next.js site using Runtime v4, the build doesn’t use the [Next.js Runtime](https://github.com/netlify/next-runtime#readme) . Use this variable with projects that generate static HTML using `next export`. * **`DISABLE_IPX`:** when set to `true` for a Next.js site using Runtime v4, the build will not generate a function for the `next/image` loader bundled into Next.js Runtime. This may break some sites unless another [image loader](https://nextjs.org/docs/pages/api-reference/components/image#loader) is also specified. * **`NETLIFY_SKIP_GATSBY_FUNCTIONS`**: when set to `true` for a Gatsby site, the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby#readme) will not [automatically generate Netlify Functions](/frameworks/gatsby/#auto-generated-netlify-functions) . This will disable some Gatsby features and may break some sites. * **`NETLIFY_IMAGE_CDN`**: value defaults to `false`. When set to `true`, the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby/blob/main/docs/image-cdn.md) or [Gatsby adapter for Netlify](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-adapter-netlify/README.md#imagecdn) will use Netlify Image CDN instead of processing images at build time for Gatsby sites. Not supported for Gatsby version 5.12.x. * **`GATSBY_CLOUD_IMAGE_CDN`**: deprecated variable that is supported but no longer recommended — use `NETLIFY_IMAGE_CDN` instead. Value defaults to `false`. When set to `true`, the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby/blob/main/docs/image-cdn.md) will use Netlify Image CDN instead of processing images at build time. * **`GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE`:** value that defaults to `false`. When set to `true`, the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby#readme) loads the Gatsby datastore from the CDN instead of bundling it with a function. * **`AWS_LAMBDA_JS_RUNTIME`:** value that sets the [Node.js runtime version for Netlify Functions](/functions/optional-configuration/?fn-language=js#node-js-version-for-runtime-2) . This environment variable must be set using the Netlify UI, CLI, or API, and not with a Netlify configuration file (`netlify.toml`). * **`CI`:** value that defaults to `true`, indicating that the build is running in a Continuous Integration (CI) environment. If this [causes issues for your build](/configure-builds/troubleshooting-tips/#build-fails-on-warning-message) , you can override the variable by adding `CI=''` to the beginning of your site [build command](/configure-builds/overview/#build-settings) . The following variables should be set in the Netlify UI rather than in `netlify.toml`. This is because the Netlify configuration file is read after your repository has been cloned. * **`GIT_LFS_ENABLED`:** value that is undefined by default. If set, we’ll use `git lfs clone` to check out your repository — otherwise we use `git clone`. * **`GIT_LFS_FETCH_INCLUDE`:** if `GIT_LFS_ENABLED` is set, this specifies by file extension which Git LFS files will be downloaded when cloning your repository. Any other file extensions will have only text pointer files downloaded instead of the original media files. * **`NETLIFY_BUILD_DEBUG`:** set this to `true` to print additional debugging information in the build logs. The output does not contain sensitive information. To disable debugging, delete the variable. Alternatively, delete everything in the variable’s **Value** field. [#](#read-only-variables) Read-only variables ---------------------------------------------- In addition to the variables you choose to declare, Netlify has a number of pre-defined variables built in. **The following variables are automatically set for your builds, and their values are not changeable.** ### [#](#build-metadata) Build metadata * **`NETLIFY`:** always `true`. Can be used to check if the build is running on Netlify. * **`BUILD_ID`:** unique ID for the build; for example: `5d4aeac2ccabf517d2f219b8`. * **`CONTEXT`:** name of the build’s [deploy context](/site-deploys/overview/#deploy-contexts) . It can be `production`, `deploy-preview`, `branch-deploy`, or `dev`. ### [#](#git-metadata) Git metadata * **`REPOSITORY_URL`:** URL for the [linked Git repository](/git/repo-permissions-linking/) . * **`BRANCH`:** reference to check out after fetching changes from the Git repository. Can be useful for [split testing](/site-deploys/split-testing/#expose-branch-information-in-your-site) . * **`HEAD`:** name of the head branch received from a Git provider. * **`COMMIT_REF`:** reference ID (also known as “SHA” or “hash”) of the commit we’re building. * **`CACHED_COMMIT_REF`:** reference ID (also known as “SHA” or “hash”) of the last commit that we built before the current build. When a build runs without cache, `CACHED_COMMIT_REF` will be the same as the `COMMIT_REF`. * **`PULL_REQUEST`:** whether the build is from a pull/merge request (`true`) or not (`false`). * **`REVIEW_ID`:** ID of the request and the Deploy Preview it generated (for example, `1211`) if from a pull/merge request. These two numbers will always match. (For example, `deploy-preview-12` is for PR #12 in your repository.) ### [#](#deploy-urls-and-metadata) Deploy URLs and metadata * **`URL`:** URL representing the main address to your site. It can be either a Netlify subdomain or your own custom domain if you set one; for example, `https://petsof.netlify.app` or `https://www.petsofnetlify.com`. * **`DEPLOY_URL`:** URL representing the unique URL for an individual deploy. It starts with a unique ID that identifies the deploy; for example, `https://5b243e66dd6a547b4fee73ae--petsof.netlify.app`. * **`DEPLOY_PRIME_URL`:** URL representing the primary URL for an individual deploy, or a group of them, like branch deploys and Deploy Previews; for example, `https://feature-branch--petsof.netlify.app` or `https://deploy-preview-1--petsof.netlify.app`. If you set up an [automatic deploy subdomain](/domains-https/custom-domains/automatic-deploy-subdomains/) , this URL will update. * **`DEPLOY_ID`:** unique ID for the deploy; for example, `578ab634d6865d5cf960d620`. Matches the beginning of `DEPLOY_URL`. * **`SITE_NAME`:** name of the site, its Netlify subdomain; for example, `petsof`. * **`SITE_ID`:** unique ID for the site; for example, `1d01c0c0-4554-4747-93b8-34ce3448ab95`. ### [#](#build-hook-metadata-and-payload) Build hook metadata and payload If your build is triggered from a custom [build hook](/configure-builds/build-hooks/) , Netlify also has three build-hook-specific variables: * **`INCOMING_HOOK_TITLE`:** title of the build hook. * **`INCOMING_HOOK_URL`:** URL of the build hook. * **`INCOMING_HOOK_BODY`:** [payload](/configure-builds/build-hooks/#payload) of the request sent to the build hook URL. [#](#access-variables) Access variables ---------------------------------------- Build environment variables are available in the build system they’re set in and are available for use by build plugins and scripts run during the build step for a site. This section outlines how to access these variables during the build process. Note that, as these are build variables specifically, you will need to take extra steps if you want your site to have [access to these values after the build is complete](#use-variables-in-a-site-after-it-s-built) . Check your variable scope If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** to be available to the Netlify build system. ### [#](#prepare-your-build-environment) Prepare your build environment To use these environment variables, you need to ensure they’re set in the environment where the build will run - on Netlify through continuous deployment or in your local development environment. #### [#](#build-on-netlify) Build on Netlify If you have continuous deployment set up, Netlify will automatically start a build and deploy whenever you push code to your Git repo. While the build runs on Netlify, the build system already has access to all of the [variables set in the Netlify build environment](/environment-variables/get-started/#create-environment-variables) and can use them during the build process. Note that when you build on Netlify, the build system doesn’t read `.env` files. To use variables declared in a `.env` file, we recommend you [import the variables](/environment-variables/get-started/#import-variables-from-env-files) into Netlify before you build. This way the variables in your `.env` file remain secure and out of your shared repository. #### [#](#build-locally) Build locally When you build in your local development environment, you need to ensure these environment variables are set in the local environment before you run the build command. The best way to build locally is to use the [Netlify CLI](/cli/get-started/#run-builds-locally) . Building locally with the CLI mimics the behavior of running a build on Netlify and will give you access to the environment variables you’ve already set there. netlify build You can also use [Netlify Dev](/cli/local-development/) with `--context production` to run a local development environment that mimics the Netlify production environment. Netlify Dev will automatically pull down environment variables stored on Netlify and read any variables stored in a `.env` file on your machine. If you don’t want to use the Netlify CLI or Netlify Dev, you need to set the variables in your local development environment yourself. There are a few different ways to do this, including declaring variables directly in the command line or using a `.env` file and [dotenv](https://www.npmjs.com/package/dotenv) . Just remember not to commit any sensitive values to your repository. Visit our Forums for a verified Support Guide on [how to access environment variables during your site build](https://answers.netlify.com/t/support-guide-using-environment-variables-on-netlify-correctly/267) for more tips. ### [#](#use-variables-during-the-build) Use variables during the build Once the variables are set correctly in the environment you want to build in, you can access them in a few different ways depending on the context. * [Use variables in the `netlify.toml` or Netlify UI](#use-variables-in-the-netlify-toml-or-netlify-ui) * [Use variables to install private npm modules](#use-variables-to-install-private-npm-modules) * [Use variables in Node.js script files](#use-variables-in-node-js-script-files) * [Use variables in build plugins](#use-variables-in-build-plugins) * [Use variables in a site after it’s built](#use-variables-in-a-site-after-it-s-built) #### [#](#use-variables-in-the-netlify-toml-or-netlify-ui) Use variables in the `netlify.toml` or Netlify UI Netlify commands use the Bash shell, so you can use Bash syntax to select the environment variable: `$VARIABLE_NAME`. You can use this format in the Netlify UI and in the `netlify.toml` with the `build.command` and `ignore.command`. For example, to print a **not-sensitive** variable (`GREETING = "hi there"`) to the deploy log at the end of the build step, set the build command in the Netlify UI to `npm run build && echo $GREETING`. ![](/images/configure-builds-environment-variables-build-command-ui.png) The next time you build and deploy the site, the build process will print the variable to the deploy log at the end of the build step. ![](/images/configure-builds-environment-variables-ui-example-deploy-log.png) Note that if you would like to use environment variable values in the `[[headers]]` and `[[redirects]]` sections of the `netlify.toml`, you need to [inject the values as part of your build command](/configure-builds/file-based-configuration/#inject-environment-variable-values) . #### [#](#use-variables-to-install-private-npm-modules) Use variables to install private npm modules To use an environment variable for private npm module installs, you can [set an `NPM_TOKEN` value](/configure-builds/manage-dependencies/#npm) in your build environment. Whenever Netlify runs an install and build, npm will automatically check the environment for an `NPM_TOKEN` to use for authentication. This way, you can avoid declaring or accessing this sensitive variable value directly in your `package.json`. If you use Yarn to manage dependencies, [set `YARN_NPM_AUTH_TOKEN`](/configure-builds/manage-dependencies/#yarn) instead of `NPM_TOKEN`. #### [#](#use-variables-in-node-js-script-files) Use variables in Node.js script files To access environment variables in script files that Node.js runs during the build process, you need to use the format `process.env.VARIABLE_NAME`. For example, create a file `sayHello` in TypeScript or JavaScript that will log your **non-sensitive** variable (`GREETING = "hi there"`) to the console when run: * Loading error: Refresh the page to access this code sample const greetPerson: string = process.env.GREETING; console.log(`Say hello: ${greetPerson}`); const greetPerson = process.env.GREETING; console.log(`Say hello: ${greetPerson}`); Then, update the build command in the `package.json` or in the `netlify.toml` to include the instruction to run the script file: * Loading error: Refresh the page to access this code sample # Replace ts-node with the appropriate command # for your TypeScript compiler for node.js [build] command = "npm run build && ts-node ./sayHello.ts" [build] command = "npm run build && node ./sayHello.js" The next time you build and deploy the site, the build process will print the variable to the deploy log at the end of the build step. ![](/images/configure-builds-environment-variables-script-example-deploy-log.png) #### [#](#use-variables-in-build-plugins) Use variables in build plugins There are two ways to access environment variables in build plugins: [using `process.env.VARIABLE_NAME` or using `netlifyConfig`](/build-plugins/create-plugins/#environment-variables) . #### [#](#use-variables-in-a-site-after-it-s-built) Use variables in a site after it’s built If you want to use environment variable values in a site after it’s built, you need to take further action to provide access. Here are a few options: * Use a [function or edge function](/functions/environment-variables/) to access values during runtime. This is the best option to avoid revealing sensitive values. * Use [snippet injection](/site-deploys/post-processing/snippet-injection/) to access values during post-processing. * Use a custom script or framework-specific variables to [copy values into the site](/frameworks/environment-variables/#embed-variable-values-in-the-site-build) code during the build process. If you inject values into the site using a build script or snippet injection, make sure to only include non-sensitive values. More details are available in our verified Support Guide on [how to access environment variables](https://answers.netlify.com/t/support-guide-using-environment-variables-on-netlify-correctly/267) . [#](#more-environment-variables-resources) More environment variables resources -------------------------------------------------------------------------------- * [Overview of environment variables](/environment-variables/overview/) at Netlify * Verified Support Guide on [how to use environment variables](https://answers.netlify.com/t/support-guide-using-environment-variables-on-netlify-correctly/267) * [Injecting environment variable values in your `netlify.toml` file](/configure-builds/file-based-configuration/#inject-environment-variable-values) * [Environment variables for different deploy contexts](/site-deploys/overview/#deploy-contexts) * [Hugo version environment variable](/frameworks/hugo/#hugo-version) * [Node.js functions runtime settings](/functions/optional-configuration/?fn-language=js#node-js-version-for-runtime-2) [Environment variables overview: Sensitive variable policy](/environment-variables/get-started/#sensitive-variable-policy) Last updated: October 2, 2024 ← [Manage dependencies](/configure-builds/manage-dependencies/) [File-based configuration](/configure-builds/file-based-configuration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Build configuration overview | Netlify Docs Netlify lets you link a GitHub, GitLab, Bitbucket, or Azure DevOps repository to a site for [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) . Each time you push to your Git provider, Netlify runs a build with your tool of choice and deploys the result to our powerful CDN. [#](#build-settings) Build settings ------------------------------------ With continuous deployment configured, you can specify how Netlify will build your site. You can specify these settings when you first [add your site from an existing repository](/welcome/add-new-site/#import-from-an-existing-repository) and anytime afterwards by going to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . Missing **Build settings**? If **Build settings** aren’t available for your site, you may not have continuous deployment set up. You can [link a Git repository](/git/repo-permissions-linking/#link-a-git-repository) to enable continuous deployment and access these settings. For basic site configurations, you may need to [set the build command](#set-the-build-command) and [publish directory](#set-the-publish-directory) . For more advanced configurations, such as sites that build from a subdirectory of a repository or a monorepo, you may also need to [set the base directory](#set-the-base-directory) and [package directory](#set-the-package-directory) . If Netlify automatically detects that your site is a monorepo or uses a framework that Netlify is able to identify, Netlify will automatically fill in some of these configuration fields for you when you first [create your site](/welcome/add-new-site/) . You can update the fields afterwards as needed. Learn more about [commonly used build settings for frameworks](/frameworks/) and how to [configure sites from monorepos](/configure-builds/monorepos/) . For public repositories, you can also toggle your deploy log visibility. With continuous deployment, builds are active by default. You can [stop or activate builds](/configure-builds/stop-or-activate-builds/) at will for more control of your workflow. ![](/images/configure-builds-edit-build-settings-ui.png) You can also specify some of these build settings and others in a [configuration file](/configure-builds/file-based-configuration/) , which allows you to change your settings depending on the [deploy context](/site-deploys/overview/#deploy-contexts) . For an example, refer to this [sample `netlify.toml` file](/configure-builds/file-based-configuration/#sample-netlify-toml-file) that illustrates how to configure some of the available build settings. The configuration file settings override build settings specified in the UI. ### [#](#definitions) Definitions The following definitions highlight terms related to build configuration. For definitions regarding branches and site deploys, visit the [site deploys overview](/site-deploys/overview/#definitions) . * **Base directory:** directory where Netlify checks for [dependency management](/configure-builds/manage-dependencies/) files such as `package.json` or `.nvmrc`, installs dependencies, and runs your build command. The build system will use this directory to perform caching during the build process. If not set, the base directory defaults to the root of the repository. * **Site files:** source files in your repository that represent the code for your site and any related configurations. Also known as your site’s package. * **Package directory:** typically used for monorepos, the directory that contains your site files, including the `netlify.toml`. Set this only if the location is different from the base directory. Learn more about how Netlify searches for your [configuration files in monorepos](/configure-builds/monorepos/#how-netlify-finds-your-configuration-files) . * **Build command:** the command to run to build your site if you are using a static site generator or other build tool. For example, `npm run build`. The build command runs in the Bash shell, allowing you to add Bash-⁠compatible syntax to the command. Visit the [frameworks](/frameworks/) doc to learn about typical build commands for popular tools. * **Publish directory:** directory that contains the deploy-ready HTML files and assets generated by the build. The directory is relative to the base directory, which is root by default (`/`). Visit the [frameworks](/frameworks/) doc to learn about typical publish directories for popular tools. Only files in the publish directory are deployed Files and assets located outside of the publish directory won’t be included in site deploys. * **Functions directory:** directory that contains function files and optional subdirectories for organizing function files. Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function. Default is `netlify/functions`. The functions directory is relative to the base directory. * **Netlify configuration file:** optional configuration file (`netlify.toml`) that specifies how Netlify builds and deploys your site — including redirects, branch and context-specific settings, and more. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . * **Deploy log visibility:** privacy level for the [deploy logs](/site-deploys/overview/#deploy-log) for a site linked to a public repo. The default setting **Public logs** makes deploy logs available to anyone with a deploy detail URL. You can limit deploy log access to site members by selecting **Private logs**. * **Active builds:** used to indicate when [builds are active](/configure-builds/stop-or-activate-builds/) . Netlify builds your site according to your continuous deployment settings when you push to your Git provider. * **Stopped builds:** used to indicate when [builds are stopped](/configure-builds/stop-or-activate-builds/#stop-builds) . Netlify will never build your site. You can [build your site locally](/cli/get-started/#run-builds-locally) instead using Netlify CLI and then publish new deploys manually [with the CLI](/cli/get-started/#manual-deploys) or [the API](/api/get-started/#deploy-with-the-api) . ### [#](#set-the-build-command) Set the build command You can manually set the [build command](#definitions) in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) . Use the `command` property under `[build]` settings. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . * using [Netlify CLI](/cli/get-started/) when setting up continuous deployment for a site. To find the typical build command for your framework, refer to the [frameworks](/frameworks/) doc. ### [#](#set-the-publish-directory) Set the publish directory You can manually set the [publish directory](#definitions) in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) . Use the `publish` property under `[build]` settings. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . * using [Netlify CLI](/cli/get-started/) when setting up continuous deployment for a site. To find the typical publish directory for your framework, refer to the [frameworks](/frameworks/) doc. ### [#](#set-the-base-directory) Set the base directory If not explicitly set, the [base directory](#definitions) defaults to the root of the repository. If you want to install dependencies and build your site in a subdirectory rather than root, you can specify this by setting a base directory. You can set a base directory in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) stored at the root of your repository. Use the `base` property under `[build]` settings, and Netlify will use that value to set the base directory when you first set up the site. * if you’re creating a [Deploy to Netlify](/site-deploys/create-deploys/#deploy-to-netlify-button) button for other people to easily clone and deploy your site, use the [`base` query parameter](/site-deploys/create-deploys/#set-a-base-directory-for-monorepos) to set the base directory for that button. You can create different buttons for each site in your monorepo by setting a different `base` value for each button. A base directory specified in a root-level `netlify.toml` overrides the UI setting. ### [#](#set-the-package-directory) Set the package directory If you use a [monorepo](/configure-builds/monorepos/) and store your [site files](#definitions) in a different directory from your base directory, you can specify the location using the **Package directory** field in the Netlify UI. This is helpful if you want to install dependencies and run builds in the root but want to store your site’s source files, including the corresponding `netlify.toml`, in separate project directories. If you don’t set this value, Netlify will [search for the `netlify.toml`](/configure-builds/monorepos/#how-netlify-finds-your-configuration-files) in the base and root directories. In addition, if you don’t [set an explicit publish directory](#set-the-publish-directory) , Netlify uses the package directory to search for the directory that contains the output of your build (for example, a `dist` folder) and any related `_headers` and `_redirects` files within that directory. To set the package directory for a site: 1. Navigate to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . 2. Select **Configure**. 3. Enter the **Package directory**. For example, `/packages/website`. 4. Select **Save**. [#](#recommendations-for-specific-setups) Recommendations for specific setups ------------------------------------------------------------------------------ Consider the following suggestions based on your project configuration. * If your repository contains only the site you want to deploy, stored in the repository root, Netlify will automatically detect the build settings for you. In most cases, you can proceed with these default settings. But, if you do need to manually configure any settings, these would likely be the [build command](#set-the-build-command) and the [publish directory](#set-the-publish-directory) . * If your site is a [monorepo](/configure-builds/monorepos) , Netlify will automatically detect each site directory in your repository and configure the build settings automatically based on the site you select. But, you also have the option to manually configure the build settings. For monorepos, this will include setting the [package directory](/configure-builds/monorepos/#set-the-package-directory) . Refer to our documentation on the [recommended monorepo setup](/configure-builds/monorepos/#recommended-monorepo-setup) to learn more. * If you have a larger repository that includes more than just your site files, you may need to deploy a self-contained site or monorepo workspace from a specific subdirectory. For example, a documentation site from the `/docs` subdirectory of your Python library. Or, a monorepo workspace set up in a `/frontend` subdirectory. To work from a specific subdirectory, update the [base directory](#set-the-base-directory) . The [publish directory](#definitions) is relative to the base directory by default. For larger repositories and monorepos, note that you can customize the default [ignore builds](/configure-builds/ignore-builds/) behavior to determine whether or not your site builds as changes are made. [#](#build-image-selection) Build image selection -------------------------------------------------- When a build is triggered on Netlify, our build system starts a Docker container running a build image. The build image is a snapshot of an operating system that has [various software tools and other settings](/configure-builds/available-software-at-build-time/) preinstalled and configured. Although all new Netlify sites use a default build image, you may be able to select from multiple images with different operating system and software versions. You might choose a different build image to meet a software requirement for your build tool, to try out experimental pre-release build features, or to keep up-to-date with the included operating system environment. Build image selection also enables Netlify to release breaking changes into the build image while allowing you to accommodate those changes with time to upgrade. We recommend upgrading to the most recent build image regularly to take advantage of the latest features and security enhancements. To change the build image for a site, go to **Site configuration \> Build & deploy \> Continuous deployment \> Build image selection** , and select the build image you would like to use. Our build system will use this image for all production deploys, branch deploys, and Deploy Previews. ### [#](#build-image-defaults-and-project-dependencies) Build image defaults and project dependencies Each build image has a set of [software with pre-defined default versions](/configure-builds/available-software-at-build-time/) . You can [customize these defaults](/configure-builds/manage-dependencies/) . During your project’s first build, we pin a version of [Node](/configure-builds/manage-dependencies/#node-js-and-javascript) , [Ruby](/configure-builds/manage-dependencies/#ruby) , [Go](/configure-builds/manage-dependencies/#go) , and [Yarn](/configure-builds/manage-dependencies/#yarn) that matches the default version installed on the build image. These pinned versions are stored in your project’s repository object, associating those pinned versions with your project’s Git repository. This ensures your project’s software versions will not be affected if the build image’s defaults change. [#](#more-build-configuration-resources) More build configuration resources ---------------------------------------------------------------------------- * [Common framework configurations](/frameworks/) * [Monorepos](/configure-builds/monorepos/) * [JavaScript SPAs](/configure-builds/javascript-spas/) * [Ignore builds](/configure-builds/ignore-builds/) * [Manage build dependencies](/configure-builds/manage-dependencies/) * [Build environment variables](/configure-builds/environment-variables/) * [File-based configuration](/configure-builds/file-based-configuration/) * [Example `netlify.toml` file](/configure-builds/file-based-configuration/#sample-netlify-toml-file) * [On-demand Builders](/configure-builds/on-demand-builders/) * [Build hooks](/configure-builds/build-hooks/) * [Stop or activate builds](/configure-builds/stop-or-activate-builds/) * [Build troubleshooting tips](/configure-builds/troubleshooting-tips/) * [Available software at build time](/configure-builds/available-software-at-build-time/) * [Private Connectivity](/security/private-connectivity/) * [Compiled build and deploy resources - start here!](https://answers.netlify.com/t/support-guide-compiled-build-and-deploy-resources-start-here/50679) Last updated: July 19, 2024 [JavaScript SPAs](/configure-builds/javascript-spas/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # JavaScript SPAs | Netlify Docs Netlify supports many frameworks and project architectures. On this page, you'll find generic common configuration information for JavaScript single-page applications (SPAs). For framework-specific configurations, refer to our [frameworks page](/frameworks/) . [#](#build-configuration-for-javascript-spas) Build configuration for JavaScript SPAs -------------------------------------------------------------------------------------- Most SPAs declare a build command in the `scripts` array of the project’s `package.json` file. To run this script in Netlify, set the **Build command** to `npm run YOUR_BUILD_SCRIPT` or `yarn YOUR_BUILD_SCRIPT`, depending on your chosen [JavaScript dependency manager](/configure-builds/manage-dependencies/#javascript-dependencies) . The **Publish directory** for single-page apps is often called `dist` but varies by framework and build tool. You can check the framework documentation, or try running the build script locally, then check what folder was created as a result. Avoid 404s for SPAs If your project is a single page app (SPA) that uses the history `pushState` method to get clean URLs, you must add a [rewrite rule](/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to serve the `index.html` file no matter what URL the browser requests. [#](#code-splitting-or-hashed-filenames) Code splitting or hashed filenames ---------------------------------------------------------------------------- If your SPA (single-page application) uses code splitting or hashed filenames with our atomic deploys, filename changes may break asset references on your site and result in an `Uncaught SyntaxError: Unexpected token` error. To ensure your assets work across deploys, consider disabling hashed filenames, using permalinks, or using a service worker. For more details and solutions, check out our [official Support Guide on handling code-splitting issues on Netlify](https://answers.netlify.com/t/support-guide-handling-code-splitting-issues-on-netlify/113158) . [#](#more-build-configuration-resources) More build configuration resources ---------------------------------------------------------------------------- * [Common framework configurations](/frameworks/) * [Monorepos](/configure-builds/monorepos/) * [Ignore builds](/configure-builds/ignore-builds/) Last updated: March 14, 2024 ← [Build configuration](/configure-builds/overview/) [Monorepos](/configure-builds/monorepos/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # API authentication in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. To ensure secure access to your data, configure API authentication settings for your data layer using API tokens and scopes. You must authenticate all requests to your data layer’s [GraphQL API](/connect/access-data/#use-the-graphql-api) using a token. However, API tokens and scopes do not apply to the [GraphQL sandbox](/connect/access-data/#use-the-graphql-sandbox) — an environment that is already limited to those in your Netlify team. To support security tracking and auditing, Netlify records all activities related to generating, updating, and revoking API tokens and scopes in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . [#](#manage-api-tokens) Manage API tokens ------------------------------------------ To restrict access to sensitive data, create API scopes first By default, API tokens have unrestricted access to all of your data. If you plan to restrict access to certain fields and types, you have to create the [API scope](#add-an-api-scope) first. You cannot edit an API token after you create it. Team Owners and Developers can generate multiple API tokens for each data layer, as needed. ### [#](#generate-an-api-token) Generate an API token To generate an API token for your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API tokens** section, select **Add an API token**. 5. Enter an **API token name**. 6. Select the **API scope(s)** for the token. You can add more than one scope to provide access to multiple data sets. If you leave this blank, the token will have unrestricted access. Unscoped types and fields are accessible to all API tokens. 7. Select **Generate token**. 8. After Netlify generates a token for you, select the clipboard icon to copy your token and then store it in a safe place. To protect your data, you won’t be able to reveal this token again. Make sure to include the API token with all API requests. If you use the [Connect client](/connect/access-data/#use-the-connect-client) , you can store the token in an environment variable and the client will automatically apply it for you. If not, you need to ensure you manually add the token to the API request’s authorization header: `Authorization: Bearer `. Keep your API token secure To keep your API token secure, we recommend that you store it in an [environment variable](/environment-variables/get-started/#create-environment-variables) on Netlify instead of in your repository. You can also avoid revealing the token in the browser by using the [Connect client](/connect/access-data/#use-the-connect-client) , a [serverless function](/connect/access-data/#query-in-a-function) , or an [edge function](/connect/access-data/#query-in-an-edge-function) to access the variable and query the GraphQL API during runtime. ### [#](#revoke-an-api-token) Revoke an API token After you revoke an API token, any client applications or scripts that use that token will no longer be able to access the data layer’s GraphQL API. This action cannot be reversed. To revoke an API token: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API tokens** section, find the token you want to revoke and select **Revoke**. 5. In the confirmation prompt that appears, review the details and then select **Revoke** to confirm. [#](#manage-api-scopes) Manage API scopes ------------------------------------------ API scopes are available for select data sources Support for API scopes is currently available for data layers that use the following data source types: Contentful, Contentstack, Drupal, Shopify, and WordPress. Additional support is coming soon. API scopes allow you to restrict access to sensitive data. The first step is to create a scope for the types and fields you want to restrict. Then, you can create an API token with access to that scope. Only API requests made with the correctly scoped API tokens can access restricted types and fields. Unscoped types and fields are accessible to all API tokens. Note that API tokens created without a scope have unrestricted access and it’s not possible to edit their scope after you generate them. Team Owners and Developers can add multiple API scopes for each data layer, as needed. ### [#](#add-an-api-scope) Add an API scope To add an API scope to your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API scopes** section, select **Add an API scope**. 5. Enter a **Name** for the scope. 6. Select the types and fields for the scope. You can use the **Filter** field to search for specific ones. ![](/images/connect-api-authentication-add-scope.png) 7. Select **Save**. When you add an API scope, Netlify automatically starts a data sync to apply the scope to the types and fields in your data layer’s schema. You can now [generate an API token](#generate-an-api-token) and apply the new scope to it. ### [#](#edit-an-api-scope) Edit an API scope To edit an API scope on your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API scopes** section, find the scope you want to modify, and select it to reveal the details. 5. Select **Options \> Edit** . 6. Update the scope as needed and then select **Save**. When you edit an API scope, the changes immediately apply to all API tokens that use the scope, and Netlify automatically starts a data sync to update your data layer’s schema. ### [#](#delete-an-api-scope) Delete an API scope When you delete an API scope, the following access changes occur: * If you delete a scope and another one doesn’t already apply to the types and fields, the data included in the scope will be accessible by all API tokens. * If this is the only scope on an API token, the token will only have access to unscoped types and fields moving forward. Only Team Owners can delete API scopes. This action cannot be reversed. To delete an API scope from your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API scopes** section, find the scope you want to delete, and select it to reveal the details. 5. Select **Options \> Delete** . 6. In the confirmation prompt that appears, review the details and then select **Delete API scope** to confirm. When you delete an API scope, Netlify automatically starts a data sync to remove the specified scope from the types and fields in your data layer’s schema. Last updated: October 2, 2024 ← [Data revisions](/connect/data-revisions/) [Access data](/connect/access-data/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # File-based configuration | Netlify Docs In addition to using the Netlify UI to configure [build settings](/configure-builds/overview/#build-settings) , [deploy settings](/site-deploys/post-processing/) , and [environment variables](/environment-variables/overview/) , you can also configure many of these settings in a `netlify.toml` file. File-based configuration settings take precedence Be aware that if you have conflicting configuration values, settings specified in `netlify.toml` override any corresponding settings in the Netlify UI. The `netlify.toml` is a configuration file that specifies how Netlify builds and deploys your site — including redirects, branch and context-specific settings, and more. Its goal is to describe much of your site configuration alongside your code — with two goals: * When someone forks your repository, they can instantly create a Netlify site using the new repo. They don’t have to configure anything in the UI, and they’ll still get an identical site configuration. * You can track configuration changes using version control and configure some things that aren’t customizable in our UI. There are other ways to accomplish some of the things you would use the `netlify.toml` for. For example, you can use [`_headers`](/routing/headers/) and [`_redirects`](/routing/redirects/) files to accomplish what the filename suggests, but having these settings all live in the same file can greatly simplify maintaining them. There are also certain settings that you can only configure using the Netlify UI, CLI, or API. The `netlify.toml` file is not a fully comprehensive configuration method. Declare environment variables in the Netlify UI for more options While you can use `netlify.toml` to declare environment variables, we recommend that you use the [Netlify UI](/environment-variables/get-started/#create-environment-variables) to avoid storing sensitive values in your repository, and for the option to set [scopes](/environment-variables/overview/#scopes) , track changes in the [team audit log](/accounts-and-billing/team-management/team-audit-log/) , and access values with the Netlify [CLI](/cli/get-started/#manage-environment-variables) and [API](/api/get-started/#environment-variables) . The following sections will go through where to store the `netlify.toml`, each thing you’ll be able to do in the file, and some examples that you could use in your code. For more information on TOML syntax, visit the [TOML website](https://toml.io/en/) . [#](#file-location) File location ---------------------------------- The `netlify.toml` is normally stored in the root of your site repository. You also have the option to include different configuration files in other directories for special cases such as [monorepos](/configure-builds/monorepos/#use-a-netlify-configuration-file) . If you store the Netlify configuration file in a directory other than the root, you will need to set either the [base directory](/configure-builds/overview/#set-the-base-directory) or the [package directory](/configure-builds/overview/#set-the-package-directory) to indicate where it is located. Learn more about [how Netlify searches for your configuration file](/configure-builds/monorepos/#how-netlify-finds-your-configuration-files) in our monorepos doc. [#](#configuration-details) Configuration details -------------------------------------------------- The following sections provide details for some commonly used configuration settings. All paths configured in the `netlify.toml` should be absolute paths relative to the [base directory](/configure-builds/overview/#definitions) , which is the root by default (`/`). ### [#](#build-settings) Build settings The `[build]` command runs in the Bash shell, allowing you to add Bash-⁠compatible syntax to the command. Netlify also supports these properties (keys) for the `[build]` command: * `base`: to specify the [base directory](/configure-builds/overview/#definitions) * `publish`: to specify the [publish directory](/configure-builds/overview/#definitions) * `command`: to specify the [build command](/configure-builds/overview/#definitions) * `environment`: to declare [build environment variables](/configure-builds/environment-variables/) * `processing`: to configure [post-processing settings](#post-processing) If a key has a list of key/value pairs as its value, you can set that key in its own block like this: [build.environment] VARIABLE = "value" ### [#](#ignore-builds) Ignore builds Netlify tries to determine if there are any changes in the site’s base directory by comparing the last known version of the files within that directory. If no change is detected, the build system skips the build, returning early from the build process. To override the default check with a custom workflow, you can use the `ignore` attribute in `netlify.toml`. This allows you to specify a Bash or Node.js command to determine whether the site needs rebuilding or not. Check out our [ignore builds](/configure-builds/ignore-builds/) doc for more information on the default ignore behavior and details about constructing a custom `ignore` command. ### [#](#build-plugins) Build Plugins Netlify [Build Plugins](/build-plugins/) extend the functionality of the build process. In addition to installing plugins through the **Site configuration \> Build & deploy \> Build plugins** section in the Netlify UI, you can also add them to a site using [file-based installation](/build-plugins/#file-based-installation) . Here’s an example `[[plugins]]` section in `netlify.toml`: [[plugins]] package = "netlify-plugin-check-output-for-puppy-references" [plugins.inputs] breeds = ["pomeranian", "chihuahua", "bulldog"] For more detailed information about installing and removing plugins, configuration options, and building and sharing different types of plugins, check out our [Build Plugins](/build-plugins/) docs. ### [#](#extensions) Extensions Some [extensions](/integrations/overview/) run during the build-deploy lifecycle for a site — for example, to analyze your build or to inject edge functions and serverless functions. If you install an extension that runs during the build process, you can configure the extension in `netlify.toml` for the sites that use it. 1. Follow the instructions to [install the extension](/integrations/overview/#install-an-extension) on your team. 2. Use `[[integrations]]` in your `netlify.toml` to configure the extension settings for each site that uses the extension. Here is an example: [[integrations]] name = "abc-performance-extension" [integrations.config] output_path = "reports/performance-reports.html" fail_deploy_on_score_thresholds = "true" [integrations.config.thresholds] performance = 0.9 accessibility = 0.9 best-practices = 0.9 seo = 0.9 pwa = 0.9 The extension author defines the format of the configuration options you can provide in `netlify.toml`, so we recommend reviewing the extension’s documentation for detailed instructions. ### [#](#deploy-contexts) Deploy contexts Certain keys, such as `[build]` and `[[plugins]]` but not `[[redirects]]` or `[[headers]]`, allow you to set `[context]` properties based on the [kind of deploy](/site-deploys/overview/#deploy-contexts) . These keys are _context-aware_. During a build, the following ordering determines which context covers a particular deploy: * UI settings are overridden if a `netlify.toml` file is present and a setting for the same property/redirect/header exists in the UI and the TOML file. * any property of a context-aware key, such as `[build]` or `[[plugins]]`, will be applied to all contexts unless the same property key is present in a more specific context. * any property in `[context.production]`, `[context.deploy-preview]`, `[context.branch-deploy]`, or `[context.dev]` will override less specific contexts: * production — a deploy generated from the production branch set in the UI under **Site configuration \> Build & deploy \> Continuous deployment \> Branches and deploy contexts** * deploy-preview — a deploy generated from a pull request or merge request * branch-deploy — a deploy generated from a branch that is not your production branch * dev — local development environments run using [Netlify Dev](/cli/local-development/) . Use `[context.dev]` to set environment variables and use the [`[dev]`](/configure-builds/file-based-configuration/#netlify-dev) section to configure all other local development properties. * any property in `[context.branchname]`, for a given branchname, is the most specific, and thus overrides all the less specific contexts. # Production context: all deploys from the Production branch # set in your site’s Branches settings in the UI will inherit # these settings. [context.production] publish = "output/" command = "make publish" # Deploy Preview context: all deploys generated from # a pull/merge request will inherit these settings. [context.deploy-preview] publish = "dist/" ### [#](#post-processing) Post processing You can manage the Pretty URLs post processing setting with the `processing` property. #### [#](#pretty-urls) Pretty URLs This setting overrides the corresponding setting under **Site configuration \> Build & deploy \> Post processing \> Pretty URLs** . [build.processing.html] pretty_urls = true ### [#](#redirects) Redirects You can manage your [redirects](/routing/redirects/) directly in your `netlify.toml`. For each redirect you want to declare, add an entry with the `[[redirects]]` heading: [[redirects]] from = "/old-path" to = "/new-path" status = 301 force = false query = {path = ":path"} # apply this rule for /old-path?path=example conditions = {Language = ["en","es"], Country = ["US"]} [[redirects]] from = "/news" to = "/blog" Here’s a [proxy redirect](/routing/redirects/rewrites-proxies/#proxy-to-another-service) : [[redirects]] from = "/api/*" to = "https://us-central1-netlify-intercom.cloudfunctions.net/readHeaders/:splat" status = 200 force = true conditions = {Role = ["admin", "cms"]} [redirects.headers] X-From = "Netlify" X-Api-Key = "some-api-key-string" You can redirect your netlify subdomain to your custom domain. Note that the `force = true` is equivalent to the `!` (for [shadowing](/routing/redirects/rewrites-proxies/#shadowing) ) in the `_redirects` file: [[redirects]] from = "https://somenetlifysite.netlify.app" to = "https://mycustomdomain.com" status = 301 force = true For more details on options to use with your redirects, review the [redirect options](/routing/redirects/redirect-options/) doc. ### [#](#headers) Headers You can define custom [headers](/routing/headers/) in `netlify.toml`. Here is an example of some headers you could configure: [[headers]] for = "/*" [headers.values] X-Frame-Options = "DENY" # Multi-value headers are expressed with multi-line strings cache-control = ''' max-age=0, no-cache, no-store, must-revalidate''' # The Basic-Auth header may not be available on all plans. Basic-Auth = "someuser:somepassword anotheruser:anotherpassword" By default, headers set in the `netlify.toml` are global for all builds and cannot be scoped for specific branches or deploy contexts. However, there is a workaround you can use to [set unique headers for each deploy context](/routing/headers/#custom-headers-for-different-branch-or-deploy-contexts) . ### [#](#functions) Functions Although there are default settings for [Netlify Functions](/functions/overview/) to help you get started, you can use the `[functions]` section in `netlify.toml` for optional, custom configuration. The following property applies for all functions: * **`directory`:** custom absolute path to your functions. The default location is `YOUR_BASE_DIRECTORY/netlify/functions`. Meanwhile, the following properties apply only for functions written in TypeScript or JavaScript. You can set them for all functions in your project or filter them by name, including using [glob patterns](https://www.npmjs.com/package/glob#glob-primer) . If a function matches several configuration blocks containing one of these properties, the values are concatenated. * **`node_bundler`:** function bundling method used in [@netlify/zip-it-and-ship-it](https://github.com/netlify/zip-it-and-ship-it) . Valid values: * **`esbuild`:** method that leverages [esbuild](https://esbuild.github.io/) to bundle functions, resulting in shorter bundling times and smaller artifacts. TypeScript functions always use `esbuild`. Currently available as an opt-in beta for JavaScript functions. * **`zisi`:** default function bundling method for JavaScript functions. * **`external_node_modules`:** list of Node.js modules that are copied to the bundled artifact without adjusting their source or references during the bundling process; only applies when `node_bundler` is set to `esbuild`. This property helps handle dependencies that can’t be inlined, such as modules with native add-ons. * **`included_files`:** list of additional paths to include in the function bundle. Although our build system includes statically referenced files (like `require("./some-file.js")`) by default, `included_files` lets you specify additional files or directories and reference them dynamically in function code. You can use `*` to match any character or prefix an entry with `!` to exclude files. Paths are absolute paths relative to the [base directory](/configure-builds/overview/#definitions-1) . For more context, check out our blog post about [including files in Netlify Functions](https://www.netlify.com/blog/2021/08/12/how-to-include-files-in-netlify-serverless-functions/) with caveats for the `esbuild` bundler. [functions] # Sets a custom directory for Netlify Functions directory = "myfunctions/" # Specifies `esbuild` for functions bundling node_bundler = "esbuild" # Flags "package-1" as an external node module for all functions external_node_modules = ["package-1"] # Includes all Markdown files inside the "files/" directory. included_files = ["files/*.md"] [functions."api_*"] # Flags "package-2" as an external node module for functions # with a name beginning with "api_". Functions matching this # pattern have both "package-1" and "package-2" as # external modules, because modules from this object # are concatenated with any from the top-level object. external_node_modules = ["package-2"] # Includes all Markdown files previously defined in the # top-level object, except for "post-1.md". included_files = ["!files/post-1.md"] [functions.api_payment] # Flags "package-3" and "package-4" as external node modules # for a function named "api_payment". # This function has 4 external node modules: # "package-1" from the top-level object # "package-2" from the "api_*" object # "package-3" and "package-4" from this object external_node_modules = ["package-3", "package-4"] # Includes all Markdown files inside "files/", except for # "post-1.md" (excluded in the "api_*" object) # and "post-2.md" (excluded in this object). # Also includes "package.json" and any files # inside "images/" or any of its subdirectories. included_files = ["!files/post-2.md", "package.json", "images/**"] ### [#](#netlify-dev) Netlify Dev [Netlify Dev](/cli/local-development/) uses [detectors](/cli/local-development/#project-detection) to enable a local development environment for most tools and frameworks without any additional setup. You can use the `[dev]` section in `netlify.toml` for optional configuration. Note that `[dev]` doesn’t run in the Bash shell, however, so you won’t be able to use Bash-⁠compatible syntax with the command. All paths configured in the `[dev]` section should be absolute paths relative to the [base directory](/configure-builds/overview/#definitions) , which is the root by default (`/`). Netlify Dev also makes use of the [functions directory setting](#functions) to scaffold and serve your functions in a local development environment. `[dev]` includes optional properties such as these: * **`command`:** command that starts your development server or runs a command such as a compiler watch in the background. If no `targetPort` is specified, it runs the command in the background in addition to the static file server. * **`port`:** port that Netlify Dev is accessible from in the browser. * **`targetPort`:** port for your application server, framework, or site generator. If provided, the CLI will wait until the provided `targetPort` is reachable and then proxy requests to it. If you specify values for both `command` and `targetPort`, `framework` must be `#custom`. * **`functionsPort`**: the port where Netlify Dev serves functions. * **`publish`:** path to your static content folder. * **`jwtRolePath`:** object path that points to role values for JWT-based redirects. * **`jwtSecret`:** secret used to verify tokens for JWT-based redirects. * **`autoLaunch`:** boolean value that determines whether Netlify Dev launches the local server address in your browser. * **`framework`:** setting to use if a project is detected incorrectly, flagged by multiple detectors, or requires a `command` and `targetPort`. Valid values: * **`#auto`:** default, tests all available detectors. * **`#static`:** property that specifies a static file server. * **`#custom`:** property that uses the `command` value to run an app server and the `targetPort` value to connect to it. Required if `command` and `targetPort` are both set. * **`https`:** property that specifies an SSL/TLS certificate and key file for the Netlify Dev local server. By default, Netlify Dev starts an HTTP server, but you can configure a certificate and key file if you require HTTPS. The `https` configuration is an object with the following properties: * **`certFile`:** path to the certificate file. * **`keyFile`:** path to the private key file. Note that an **`environment`** property doesn’t exist for `[dev]`. If you would like to set environment variables for use locally with the Netlify CLI, use [`context.dev`](/configure-builds/file-based-configuration/#deploy-contexts) instead. Here’s an example `[dev]` section for Netlify Dev configuration overrides: [dev] command = "yarn start" port = 8888 targetPort = 3000 publish = "dist" jwtRolePath = "app_metadata.authorization.roles" jwtSecret = "MY_JWT_SECRET_VALUE" autoLaunch = true framework = "#custom" [dev.https] certFile = "cert.pem" keyFile = "key.pem" ### [#](#templates) Templates While a template repository can make use of other `netlify.toml` settings, you can use the `[template]` section of a `netlify.toml` to provide template-specific configuration for [Deploy to Netlify buttons](/site-deploys/create-deploys/#deploy-to-netlify-button) . [template] incoming-hooks = ["Contentful"] [template.environment] SECRET_TOKEN = "change me for your secret token" CUSTOM_LOGO = "set the url to your custom logo here" Visit our [template configuration](/site-deploys/create-deploys/#template-configuration) docs to learn more about setting up templates and the configuration options in the example above. [#](#inject-environment-variable-values) Inject environment variable values ---------------------------------------------------------------------------- Using environment variables directly as values in your `netlify.toml` isn’t supported. For example, `key = "$VARIABLENAME"` will not inject `$VARIABLENAME`’s value into `netlify.toml`. One exception to this rule is [signed proxy redirects](/routing/redirects/rewrites-proxies/#signed-proxy-redirects) . For all other cases, you have two options for working with environment variable values in a file-based or programmatic way. Note that if you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** for the following options to work. ### [#](#use-a-local-build-plugin) Use a local build plugin We recommend [creating a local build plugin](/build-plugins/create-plugins/#local-plugins) to use environment variable values in a programmatic way because it’s the most versatile approach. It enables you to [read environment values](/build-plugins/create-plugins/#environment-variables) and change many aspects of your build configuration (including redirects and headers) through [the `netlifyConfig` object](/build-plugins/create-plugins/#netlifyconfig) . ### [#](#use-the-build-command-to-substitute-environment-variable-values) Use the `[build]` command to substitute environment variable values Substituting values using the `[build]` command in `netlify.toml` only works for the `[[headers]]` and `[[redirects]]` sections, as they are read after the build is complete. Note that substitutions made in the configuration file using this approach will not be available to build plugins, as build plugins run before the build command. The [`[build]` command](/configure-builds/file-based-configuration/#build-settings) is a Bash command and so it has access to variables set in the build environment. You can use the following steps to substitute values in the file with environment variable values during the build step, **but only if you are changing headers or redirects**. 1. Add a placeholder like `HEADER_PLACEHOLDER` somewhere in the `[[headers]]` or `[[redirects]]` sections of your TOML file. 2. Create an environment variable, for example `PROD_API_LOCATION`, with the desired value in the Netlify UI. 3. Prepend a replacement `sed` command to your build command in `netlify.toml`. The `sed` command must use double quotation marks, not single ones. Here’s an example for a site using `yarn build` to build: [build] command = "sed -i \"s|HEADER_PLACEHOLDER|${PROD_API_LOCATION}|g\" netlify.toml && yarn build" [#](#sample-netlify-toml-file) Sample `netlify.toml` file ---------------------------------------------------------- This example `netlify.toml` demonstrates how you can combine multiple settings in a single file. It’s not a comprehensive example of all available configuration options. # Settings for the [build] key are global and are applied to # all deploy contexts unless overridden by a context-specific setting. [build] # Directory where the build system installs dependencies # and runs your build. Store your package.json, .nvmrc, etc here. # If not set, defaults to the root directory. base = "project/" # Directory that contains the deploy-ready HTML files and # assets generated by the build. This is an absolute path relative # to the base directory, which is the root by default (/). # This sample publishes the directory located at the absolute # path "root/project/build-output" publish = "build-output/" # Default build command. command = "echo 'default context'" [[plugins]] # Installs the Lighthouse Build Plugin for all deploy contexts package = "@netlify/plugin-lighthouse" # Production context: all deploys from the Production branch # set in your site’s Branches settings in the UI will inherit # these settings. You can define environment variables # here but we recommend using the Netlify UI for sensitive # values to keep them out of your source repository. [context.production] publish = "output/" command = "make publish" environment = { NODE_VERSION = "14.15.3" } # Deploy Preview context: all deploys generated from # a pull/merge request will inherit these settings. [context.deploy-preview] publish = "dist/" # Here is an example of how to define context-specific # environment variables. To avoid committing sensitive # values to public source repositories, set variables # with the Netlify UI, CLI, or API instead. [context.deploy-preview.environment] NOT_PRIVATE_ITEM = "not so secret" # Branch Deploy context: all deploys that are not from # a pull/merge request or from the Production branch # will inherit these settings. [context.branch-deploy] command = "echo branch" [context.branch-deploy.environment] NODE_ENV = "development" # Dev context: environment variables set here # are available for local development environments # run using Netlify Dev. These values can be # overwritten on branches that have a more specific # branch context configured. [context.dev.environment] NODE_ENV = "development" # Specific branch context: all deploys from # this specific branch will inherit these settings. [context.staging] # “staging” is a branch name command = "echo 'staging'" base = "staging" # For contexts of branches with special characters, # enclose the branch name with quotes. [context."feat/branch"] command = "echo 'special branch'" base = "branch" # Redirects and headers are GLOBAL for all builds – they do not # get scoped to contexts no matter where you define them in the file. # For context-specific rules, use _headers or _redirects files, # which are PER-DEPLOY. # A basic redirect rule [[redirects]] from = "/*" to = "/blog/:splat" # A redirect rule with many of the supported properties [[redirects]] from = "/old-path" to = "/new-path" # The default HTTP status code is 301, but you can # define a different one. status = 302 # By default, redirects won’t be applied if there’s a file # with the same path as the one defined in the `from` property. # Setting `force` to `true` will make the redirect rule # take precedence over any existing files. force = true # Redirect from /old-path?id=123 to /new-path. # Each combination of query params needs to be # defined in a separate [[redirects]] block. # More information at https://docs.netlify.com/routing/redirects/redirect-options/#query-parameters query = {id = ":id"} # Redirect based on conditions including browser language, # geolocation, identity role, and/or cookie presence. conditions = {Language = ["en"], Country = ["US"]} # Sign each request with a value defined in an environment variable signed = "API_SIGNATURE_TOKEN" # You can also define custom headers within your redirects blocks. [redirects.headers] X-From = "Netlify" X-Api-Key = "some-api-key-string" # Redirects for role-based access control don’t use the 'to' property. [[redirects]] from = "/gated-path" status = 200 conditions = {Role = ["admin"]} force = true # The following redirect is intended for use with most SPAs # that handle routing internally. [[redirects]] from = "/*" to = "/index.html" status = 200 [[headers]] # Define which paths this specific [[headers]] block will cover. for = "/*" [headers.values] X-Frame-Options = "DENY" Content-Security-Policy = "frame-ancestors https://www.facebook.com" # Multi-value headers are expressed with multi-line strings. cache-control = ''' max-age=0, no-cache, no-store, must-revalidate''' # Basic-Auth allows you to password protect your whole site. # This feature may not be available on all plans. Basic-Auth = "someuser:somepassword anotheruser:anotherpassword" [functions] # Directory with serverless functions, including background # functions, to deploy. This is an absolute path relative to the # base directory, which is the root by default (/). directory = "functions/" # Use [dev] to set configuration overrides for local # development environments run using Netlify Dev - except # for environment variables. Environment variables for Netlify # Dev should be set under [context.dev.environment] instead. [dev] command = "yarn start" port = 8888 publish = "dist" [Edge Functions](/edge-functions/overview/) [Asset optimization end of service](/asset-optimization-bridge/) Last updated: November 12, 2024 ← [Build environment variables](/configure-builds/environment-variables/) [On-demand Builders](/configure-builds/on-demand-builders/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with the Netlify API | Netlify Docs Netlify is a hosting service for the programmable web. It understands your documents and provides an API to handle atomic deploys of websites, manage form submissions, inject JavaScript snippets, and much more. This is a REST-style API that uses JSON for serialization and OAuth 2 for authentication. This document covers the basics for interacting with the Netlify API, plus instructions for [deploying sites](/api/get-started/#deploy-with-the-api) and notes on some [commonly used endpoints](/api/get-started/#commonly-used-endpoints) . You can browse the [OpenAPI reference for the Netlify API](https://open-api.netlify.com) to explore available endpoints. Visit our Forums for more tips and conversation about [understanding and using Netlify’s API](https://answers.netlify.com/t/common-issue-understanding-and-using-netlifys-api/160) . Additionally, we have two API clients for your convenience: * [Go Client](https://github.com/netlify/open-api#go-client) * [JS Client](https://github.com/netlify/build/tree/main/packages/js-client) If you’d like to interact with the Netlify API using a no-code tool, you can use n8n.io’s [Netlify node](https://n8n.io/integrations/netlify/) . The node currently supports the following operations: * Create a new deployment * Get a deployment * Get all deployments * Cancel a deployment * Get a site * Get all sites * Delete a site [#](#make-a-request) Make a request ------------------------------------ All URLs start with `https://api.netlify.com/api/v1/`. **SSL only**. The path is prefixed with the API version. If we change the API in backward-incompatible ways, we’ll bump the version marker and maintain stable support for the old URLs. To make a request for all sites you have access to, for example, append the `sites` index path to the base URL to form something like `https://api.netlify.com/api/v1/sites`. Here’s an example in curl: curl -H "User-Agent: MyApp (YOUR_NAME@EXAMPLE.COM)" \ -H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \ https://api.netlify.com/api/v1/sites [#](#authentication) Authentication ------------------------------------ Netlify uses OAuth2 for authentication. All requests must use HTTPS. To generate a personal access token (PAT): 1. Go to **Applications \> Personal access tokens** . 2. Select **New access token**. 3. Enter a descriptive name to help you remember what the token will be used for. 4. Select **Allow access to my SAML-based Netlify team** to authorize access to your SAML-based team data through the API. 5. Select an **Expiration** date for your token to help keep your information secure. 6. Select **Generate token**. 7. Copy the token to your clipboard and store it in a safe location. Once you navigate away from this page, you won’t be able to access the value again. 8. Select **Done**. Use your PAT for manual authentication in shell scripts or commands that use the Netlify API. To authenticate API requests, include the token in the authorization header: `Authorization: Bearer ` To authenticate in shell scripts, refer to the [code sample above](#make-a-request) for an example of how to use this token in a curl request. SAML SSO If your team requires you to log in with [single sign-on (SSO)](/security/secure-netlify-access/configure-team-saml-sso/) , your personal access tokens will be denied access to the team by default. You can choose to grant access to the team when you generate a new token. You must be logged in to the team with SSO to grant access to it. If you’re making a public integration with Netlify for others to enjoy, you must use OAuth2. This allows users to authorize your application to use Netlify on their behalf without having to copy/paste API tokens or touch sensitive login info. You’ll need an application client key and a client secret to integrate with the Netlify API. You can register a new application in your Netlify user settings for [OAuth applications](https://app.netlify.com/applications) . Visit our blog post on [integrating with Netlify](https://www.netlify.com/blog/2016/10/10/integrating-with-netlify-oauth2/) for more information including common grant types and an example project. The OAuth2 end-user authorization endpoint is `https://app.netlify.com/authorize`. [#](#rate-limiting) Rate limiting ---------------------------------- To protect Netlify from getting flooded by automated deploys or misbehaving applications, the Netlify API is rate limited. You can make up to 500 requests per minute for most requests. Certain operations have their own stricter limits. For example, you can deploy through the Netlify API up to 3 times per minute and up to 100 times per day. You can check the returned HTTP headers of any API request to verify your current rate limit status: If you need higher limits, please [contact us](https://www.netlify.com/support/) . [#](#pagination) Pagination ---------------------------- All API requests that return over 100 items are paginated by default, with a limit of 100 items per page. You can specify further pages with the `?page` parameter. You can also set a custom page size that’s less than 100 with the `?per_page` parameter. Note that page numbering starts with 1 and that omitting the `?page` parameter will return the first page. ### [#](#link-header) Link header The pagination info is included in the `Link` header. Linebreak is included for readability. The possible `rel` values are: * `next` Shows the URL of the immediate next page of results. * `last` Shows the URL of the last page of results. * `prev` Shows the URL of the immediate previous page of results. [#](#deploy-with-the-api) Deploy with the API ---------------------------------------------- The most common API action is doing deploys, either of a new site or an existing site. If [builds are stopped](/configure-builds/stop-or-activate-builds/) for an existing site, you can still deploy with the API to update the site. Netlify supports two ways of doing deploys: 1. [Sending a digest](/api/get-started/#file-digest-method) of all files in your deploy, and then uploading any files Netlify doesn’t already have on its storage servers. 2. [Sending a ZIP file](/api/get-started/#zip-file-method) of the entire site and letting Netlify unzip and deploy. We generally recommend the first way, since it’s more efficient. Whether you deploy a brand new site or create a deploy within an existing site, the process is similar. First [create a new site](/api/get-started/#create-site) , if needed: POST /api/v1/sites Now you have a site ID and you can create a new deploy, either with a [file digest](/api/get-started/#file-digest-method) or a [ZIP file](/api/get-started/#zip-file-method) . ### [#](#file-digest-method) File digest method We recommend using a digest including a file path and SHA1 for each item. This method also allows you to upload serverless functions, however serverless functions should use SHA256 instead. POST /api/v1/sites/{site_id}/deploys { "files": { "/index.html": "907d14fb3af2b0d4f18c2d46abe8aedce17367bd", "/main.css": "f18c2d7367bd9046abe8aedce17d14fb3af2b0d4" }, "functions": { "hello-world": "708b029d8aa9c8fa513d1a25b97ffb6efb12b423" } } When using a file digest, the API will return an object which includes the following properties: { "id": "1234", "required": ["907d14fb3af2b0d4f18c2d46abe8aedce17367bd"], "required_functions": ["708b029d8aa9c8fa513d1a25b97ffb6efb12b423"] } The `required` property will give you a list of files by SHA1 that you need to upload. Similarly, `required_functions` will get you an array of required functions by SHA256 to upload, if you included a functions digest when creating the deploy. Tip If you have two files with the same SHA1, you don’t have to upload both of them. Now upload the files, using the deploy ID returned as `id` in the file digest response: PUT /api/v1/deploys/{deploy_id}/files/index.html Warning Be sure to escape the `file_path` parameter, and ensure file paths don’t include `#` or `?` characters. Use `Content-Type: application/octet-stream` and use the file contents as the HTTP request body. If the required file is a function, upload it to the functions endpoint, again using the deploy ID returned as `id` in the file digest response: PUT /api/v1/deploys/{deploy_id}/functions/hello-world?runtime=js Possible `runtime` parameters are: * `js`: zipped Node.js programs or bundled JavaScript files * `go`: Go binaries When uploading functions, use the name of the function, not the file path or any file extensions. Clients must zip the function prior to uploading to the API. Once all files have been uploaded, Netlify will post process the deploy and invalidate the CDN. #### [#](#async-requests-for-large-deploys) Async requests for large deploys API requests that last longer than 30 seconds will be terminated automatically. When creating large deploys, pass the `async` property in your file digest: { "async": true, "files": { "/index.html": "907d14fb3af2b0d4f18c2d46abe8aedce17367bd" }, "functions": { "hello-world": "708b029d8aa9c8fa513d1a25b97ffb6efb12b423" } } The request will then return the deploy ID (as `id`) which can be polled to determine when the deploy is ready for file uploads. GET /api/v1/sites/{site_id}/deploys/{deploy_id} You can check the `state` parameter in the response. It will be set to `preparing` as the upload manifest is generated, and either `prepared`, `uploading`, `uploaded`, or `ready` depending on the contents of the deploy. At this point, the deploy is either `ready`, or the API will give you a list of `required` files and `required_functions`. Additionally, when uploading large files, sometimes the request will time out. It is safe to retry these uploads a few times to verify whether additional attempts are successful. ### [#](#zip-file-method) ZIP file method You can deploy using a ZIP file but note there’s a limit of 25,000 files per zip extraction for a site. For the same site, you always need to upload a single zip with all the files. To deploy using a ZIP file, create a new deploy with `Content-Type: application/zip` and the ZIP file as the HTTP request body: POST /api/v1/sites/{site_id}/deploys A deploy from a ZIP file will enter post-processing mode straight after being created. While we generally recommend using file digests, you can use the ZIP file method straight from the command line with cURL: curl -H "Content-Type: application/zip" \ -H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \ --data-binary "@website.zip" \ https://api.netlify.com/api/v1/sites/mysite.netlify.app/deploys ### [#](#create-and-deploy-at-once) Create and deploy at once When creating a new site, you can include a file digest or a ZIP file straight away, to save an HTTP request. The following will create a new site and deploy it from a ZIP file: curl -H "Content-Type: application/zip" \ -H "Authorization: Bearer YOUR_OAUTH2_ACCESS_TOKEN" \ --data-binary "@website.zip" \ https://api.netlify.com/api/v1/sites ### [#](#poll-for-deploy-state) Poll for deploy state You can poll the deploy to check the state: GET /api/v1/deploys/{deploy_id} { "id": "1234", "state": "ready" } Once the state changes to `ready`, the deploy is live. ### [#](#draft-deploys) Draft deploys When creating a new deploy, you can set `"draft": true` to mark the deploy as a draft deploy. A draft deploy works like a normal deploy, but it won’t change the current published deploy of the site when it’s done processing. [#](#commonly-used-endpoints) Commonly used endpoints ------------------------------------------------------ This section describes usage for some popular endpoints. We also have an [OpenAPI reference for the Netlify API](https://open-api.netlify.com) that you can explore. Visit our Forums for more tips and conversation about [understanding and using Netlify’s API](https://answers.netlify.com/t/common-issue-understanding-and-using-netlifys-api/160) . ### [#](#sites) Sites The `/sites` endpoint allows you to access sites deployed on Netlify. Trying to manage your site’s environment variables? To update or retrieve your site’s environment variables, leverage the [environment variables](#environment-variables) endpoints. The `/sites` endpoint does not support environment variables. #### [#](#get-sites) Get sites `GET /api/v1/sites` returns all sites you have access to. [\ {\ "id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b",\ "premium": false,\ "claimed": true,\ "name": "synergy",\ "custom_domain": "www.example.com",\ "url": "http://www.example.com",\ "admin_url": "https://api.netlify.com/sites/synergy",\ "screenshot_url": null,\ "created_at": "2013-09-17T05:13:08Z",\ "updated_at": "2013-09-17T05:13:19Z",\ "user_id": "51f60d2d5803545326000005"\ }\ ] #### [#](#get-site) Get site `GET /api/v1/sites/{site_id}` returns the specified site. About site IDs * You can find a value for `{site_id}` by visiting the Netlify UI at **Site configuration \> General \> Site details \> Site information** . Site IDs are also available in the response when you [create a site](#create-site) or [get a list of sites](#get-sites) . * Whenever the API requires a `{site_id}`, you can either use the `id` of a site obtained through the API, or the domain of the site (for example, `mysite.netlify.app` or `www.example.com`). These two are interchangeable whenever they’re used in API paths. `GET /api/v1/sites/3970e0fe-8564-4903-9a55-c5f8de49fb8b` returns the site with a matching `id`. `GET /api/v1/sites/www.example.com` returns the site matching the domain `www.example.com`. { "id": "3970e0fe-8564-4903-9a55-c5f8de49fb8b", "premium": false, "claimed": true, "name": "synergy", "custom_domain": "www.example.com", "notification_email": "me@example.com", "url": "http://www.example.com", "admin_url": "https://api.netlify.com/sites/synergy", "screenshot_url": null, "created_at": "2013-09-17T05:13:08Z", "updated_at": "2013-09-17T05:13:19Z", "user_id": "51f60d2d5803545326000005" } #### [#](#create-site) Create site `POST /api/v1/sites` creates a new site. By default the site will be created in your personal team. When creating a site, you can set the following properties: * `name`: the name of the site (**mysite**.netlify.app) * `custom_domain`: the custom domain of the site (www.example.com) * `password`: password protect the site * `force_ssl`: will force SSL on the site if SSL is enabled * `processing_settings`: sets the Pretty URLs post processing setting: { "html": { "pretty_urls": true } } * `repo`: configures continuous deployment. It’s a bit complicated to create a `repo` object so please visit our Forums for a verified Support Guide on [linking a repository using the API](https://answers.netlify.com/t/common-issue-linking-a-repository-via-api/121) . #### [#](#create-site-in-team) Create site in team `POST /api/v1/{account_slug}/sites/` creates a new site in a specific team. It takes the same parameters as when creating a site. #### [#](#update-site) Update site `PATCH /api/v1/sites/{site_id}` updates some attributes on a site. `PUT /api/v1/sites/{site_id}` updates some attributes on a site. This lets you update a site. It takes all the same parameters as when creating a site. If you do a PUT request to a site with `Content-Type: application/zip` and a zipped website in the HTTP request body, it works exactly like creating a new deploy for the site based on a ZIP file. #### [#](#provision-ssl-for-a-site) Provision SSL for a site `POST /api/v1/sites/{site_id}/ssl` activates SSL for a site. The site must have a custom domain with DNS records configured to point to Netlify’s infrastructure. Any domain aliases with valid DNS records will also be included in the SSL certificate for the site. This endpoint manually triggers SSL provisioning for a site’s custom domains. Once SSL provisioning is successful, the domain will be served over HTTPS. #### [#](#delete-site) Delete site `DELETE /api/v1/sites/{site_id}` permanently deletes a site. This will return `200 OK`. ### [#](#site-metadata) Site metadata Each site has a metadata object. The properties of the metadata object can be used within the [snippets](/api/get-started/#snippets) for a site by using the [Liquid](https://github.com/Shopify/liquid) template syntax. #### [#](#get-metadata) Get metadata `GET /api/v1/sites/{site_id}/metadata` gets the metadata for a site. { "my_meta_key": "my_meta_value" } #### [#](#update-metadata) Update metadata `PUT /api/v1/sites/{site_id}/metadata` replaces the metadata object with a new metadata object. ### [#](#environment-variables) Environment variables The [environment variables API endpoints](https://open-api.netlify.com/#tag/environmentVariables) allow you to access and set both site and shared environment variables. Environment variable changes require a build and deploy to take effect. #### [#](#get-environment-variables) Get environment variables `GET /api/v1/accounts/{account_id}/env` returns all environment variables for a team or site. The list will only include shared environment variables if the request is made by a Team Owner. `GET /api/v1/accounts/{account_id}/env/{key}` returns an individual environment variable for a team or site. About account IDs * You can find a value for `{account_id}` by querying `GET /api/v1/accounts/{account_slug}`. The slug is available in the Netlify UI at **Team settings \> General \> Team details \> Team information** . An account in the Netlify REST API is equivalent to a team in the UI. * Whenever the API requires an `{account_id}`, you can substitute `{account_slug}`. These two are interchangeable whenever they’re used in API paths. #### [#](#create-and-update-environment-variables) Create and update environment variables `POST /api/v1/accounts/{account_id}/env` creates site or shared environment variables with the specified scopes and contextual values. An environment variable’s contextual values are the different values set for use in each [deploy context](/site-deploys/overview/#deploy-contexts) . `PUT /api/v1/accounts/{account_id}/env/{key}` updates an existing environment variable by replacing all of its values with the values provided with this request. `PATCH /api/v1/accounts/{account_id}/env/{key}` updates or creates a new value for an existing environment variable. #### [#](#delete-environment-variables) Delete environment variables `DELETE /api/v1/accounts/{account_id}/env/{key}` deletes an environment variable and all of its values. `DELETE /api/v1/accounts/{account_id}/env/{key}/value/{id}` deletes a specific environment variable value. ### [#](#files) Files All files deployed by Netlify can be read through the API. Where the public URL of a file will serve the processed version for HTML pages, the files accessed through the API are the original uploaded files. Netlify is based on a concept of atomic deploys. This means you never work on individual files. If you want to change a file, you do a new deploy with a new version of the site. To delete a file, you create a new deploy without the file. The file digest based deployment method means that these operations are fast and low-cost. Atomic deploys guarantees that your site is never in an inconsistent state where some files are being uploaded and where users might get HTML files that are not in sync with the CSS, image files, etc. #### [#](#get-files) Get files `GET /api/v1/sites/{site_id}/files` returns a list of all the files in the current deploy. [\ {\ "id": "/index.html",\ "path": "/index.html",\ "sha": "20828dcdf2cd07e5980fe52759101591bf5014ab",\ "mime_type": "text/html",\ "size": 27232\ }\ ] #### [#](#get-file) Get file `GET /api/v1/sites/{site_id}/files/{file_path}` returns the file. { "id": "/index.html", "path": "/index.html", "sha": "20828dcdf2cd07e5980fe52759101591bf5014ab", "mime_type": "text/html", "size": 27232 } You can get the raw contents of the file by using the custom media type `application/vnd.bitballoon.v1.raw` as the `Content-Type` of your HTTP request. ### [#](#deploys) Deploys You can access all deploys for a specific site. #### [#](#get-deploys) Get deploys `GET /api/v1/sites/{site_id}/deploys` returns a list of all deploys for a site. [\ {\ "id": "52465f435803544542000001",\ "premium": false,\ "claimed": true,\ "name": "synergy",\ "custom_domain": "www.example.com",\ "notification_email": "me@example.com",\ "url": "http://www.example.com",\ "deploy_url": "http://52465f435803544542000001.some-site.netlify.app",\ "admin_url": "https://api.netlify.com/sites/synergy",\ "screenshot_url": null,\ "created_at": "2013-09-17T05:13:08Z",\ "updated_at": "2013-09-17T05:13:19Z",\ "user_id": "51f60d2d5803545326000005",\ "state": "old"\ }\ ] #### [#](#get-deploy) Get deploy `GET /api/v1/sites/{site_id}/deploys/{deploy_id}` returns a specific deploy. { "id": "52465f435803544542000001", "premium": false, "claimed": true, "name": "synergy", "custom_domain": "www.example.com", "notification_email": "me@example.com", "url": "http://www.example.com", "deploy_url": "http://52465f435803544542000001.some-site.netlify.app", "admin_url": "https://api.netlify.com/sites/synergy", "screenshot_url": null, "created_at": "2013-09-17T05:13:08Z", "updated_at": "2013-09-17T05:13:19Z", "user_id": "51f60d2d5803545326000005", "state": "old" } #### [#](#restore-deploy-rollback) Restore deploy (rollback) `POST /api/v1/sites/{site_id}/deploys/{deploy_id}/restore` restores an old deploy and makes it the live version of the site. { "id": "52465f435803544542000001", "premium": false, "claimed": true, "name": "synergy", "custom_domain": "www.example.com", "notification_email": "me@example.com", "url": "http://www.example.com", "deploy_url": "http://52465f435803544542000001.some-site.netlify.app", "admin_url": "https://api.netlify.com/sites/synergy", "screenshot_url": null, "created_at": "2013-09-17T05:13:08Z", "updated_at": "2013-09-17T05:13:19Z", "user_id": "51f60d2d5803545326000005", "state": "current" } ### [#](#snippets) Snippets Snippets are code snippets that are injected into every HTML page of the website, either right before the closing `head` tag or right before the closing `body` tag. Each snippet can specify code for all pages and code that gets injected into “Thank you” pages shown after a successful form submission. #### [#](#get-snippets) Get snippets `GET /api/v1/sites/{site_id}/snippets` gets a list of snippets specific to a site. [\ {\ "id": 0,\ "title": "Test",\ "general": "\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E",\ "general_position": "head",\ "goal": "",\ "goal_position": "footer"\ }\ ] The `general` property is the code that will be injected right before either the head or body end tag. The `general_position` can be `head` or `footer` and determines whether to inject the code in the head element or before the closing body tag. The `goal` property is the code that will be injected into the “Thank you” page after a form submission. `goal_position` determines where to inject this code. #### [#](#get-snippet) Get snippet `GET /api/v1/sites/{site_id}/snippets/{snippet_id}` gets a specific snippet. { "id": 0, "title": "Test", "general": "\u003Cscript\u003Ealert(\"Hello\")\u003C/script\u003E", "general_position": "head", "goal": "", "goal_position": "footer" } #### [#](#add-snippet) Add snippet `POST /api/v1/sites/{site_id}/snippets` adds a new snippet to a site. #### [#](#update-snippet) Update snippet `PUT /api/v1/sites/{site_id}/snippets/{snippet_id}` replaces a snippet. #### [#](#delete-snippet) Delete snippet `DELETE /api/v1/sites/{site_id}/snippets/{snippet_id}` deletes a snippet. ### [#](#forms) Forms You can access all [Netlify Forms](/forms/setup/) metadata and submissions for a site. #### [#](#get-forms) Get forms `GET /api/v1/sites/{site_id}/forms` returns a list of all forms for a site, including metadata about each form, but not including form submissions. [\ {\ "id": "ac0865cc46440b1e64666f520e8d88d670c8a2f6",\ "site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048",\ "name": "Landing Page",\ "paths": ["/index"],\ "submission_count": 3,\ "fields": [\ { "name": "name", "type": "text" },\ { "name": "email", "type": "email" },\ { "name": "phone", "type": "text" },\ { "name": "company", "type": "text" },\ { "name": "website", "type": "url" },\ { "name": "number_of_employees", "type": "select" }\ ],\ "created_at": "2013-09-18T20:26:19Z"\ }\ ] #### [#](#get-verified-submissions) Get verified submissions `GET /api/v1/sites/{site_id}/submissions` returns a list of verified form submissions across all forms for a specific site. `GET /api/v1/forms/{form_id}/submissions` returns a list of verified form submissions for a specific form. [\ {\ "id": "5231110b5803540aeb000019",\ "number": 13,\ "title": null,\ "email": "test@example.com",\ "name": "Mathias Biilmann",\ "first_name": "Mathias",\ "last_name": "Biilmann",\ "company": "Netlify",\ "summary": "Hello, World",\ "body": "Hello, World",\ "data": {\ "email": "test@example.com",\ "name": "Mathias Biilmann",\ "ip": "127.0.0.1"\ },\ "created_at": "2013-09-12T00:55:39Z",\ "site_url": "http://synergy.netlify.app"\ }\ ] #### [#](#get-spam-submissions) Get spam submissions To get spam submissions, add a `state=spam` query parameter to the URL: `GET /api/v1/sites/{site_id}/submissions?state=spam` returns a list of spam form submissions across all forms for a specific site. `GET /api/v1/forms/{form_id}/submissions?state=spam` returns a list of spam form submissions for a specific form. #### [#](#change-submission-state) Change submission state You can change the state of a submission from spam to verified or vice versa. `PUT /api/v1/submissions/{submission_id}/spam` marks the submission as spam. `PUT /api/v1/submissions/{submission_id}/ham` marks the submission as verified. #### [#](#delete-submissions) Delete submissions `DELETE /api/v1/submissions/{submission_id}` removes a form submission. #### [#](#delete-form) Delete form `DELETE /api/v1/sites/{site_id}/forms/{form_id}` removes a form and any existing submissions to it. Future submissions to the form will result in a 404 error, and previous submissions will no longer be available. ### [#](#hooks) Hooks Netlify can trigger webhooks, send email notifications, or send Slack messages on certain events. The `/hooks` endpoint lets you control the hooks for your site. #### [#](#get-hook-types) Get hook types `GET /api/v1/hooks/types` returns a list of types of hooks that you can configure on Netlify. [\ {\ "name": "url",\ "fields": [\ {\ "name": "url",\ "options": {\ "type": "string",\ "title": "URL to notify"\ }\ }\ ],\ "events": ["submission_created", "deploy_created", "deploy_failed"]\ }\ ] Each type has a series of fields that you need to set to create a new hook, and a list of events that can trigger them. #### [#](#get-hooks-for-a-site) Get hooks for a site `GET /api/v1/hooks?site_id={site_id}` returns a list of a hooks defined for a specific site. [\ {\ "id": "5636b7a00d61eec2d6001004",\ "site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048",\ "type": "email",\ "event": "submission_created",\ "data": { "email": "test@example.com" },\ "created_at": "2015-10-20T21:51:51Z",\ "updated_at": "2015-10-20T21:51:51Z"\ }\ ] #### [#](#create-hook) Create hook `POST /api/v1/hooks` creates a new hook. An example request body for an email hook for a specific form in your site would be formatted like this: { "site_id": "0d3a9d2f-ef94-4380-93df-27ee400e2048", "form_id": "5235a7a00d61eec2d6001302", "type": "email", "event": "submission_created", "data": { "email": "test@example.com" } } `form_id` is optional and links the hook to a specific form within your site. You can also use `form_name` with the value of the `name` attribute of the form of your site as an alternative to `form_id`. #### [#](#delete-hook) Delete hook `DELETE /api/v1/hooks/{hook_id}` removes a hook permanently. Note, for outgoing webhooks, returning a `410 Gone` status code from the URL endpoint will trigger a deletion of the hook. Last updated: July 22, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Monorepos | Netlify Docs Netlify provides flexibility in how you organize and build a site or application. Although some sites are built directly from the root of a repository, we also support those with a more complex setup like monorepos — repositories that contain multiple sites or apps, each in its own subdirectory. To help you successfully configure sites from a monorepo, Netlify offers both [automatic monorepo detection](#automatic-monorepo-detection) and [manual configuration options](#manual-configuration) . You also have the ability to control the volume of [commit status notifications](#commit-status-notifications) and to configure a custom [`ignore` command](/configure-builds/ignore-builds/) . This document also outlines our [recommended monorepo setup](#recommended-monorepo-setup) . Using the CLI with a monorepo? After you set up your site on Netlify, you can use the Netlify CLI’s `--filter` flag to specify which site in your monorepo to run commands on. This way, you can work directly from the root of your project. Learn more about [using the CLI with monorepos](/cli/get-started/#work-with-monorepos) . [#](#definitions) Definitions ------------------------------ To deploy a site from a monorepo, you may need to set or use the following: * **Base directory:** directory where Netlify checks for [dependency management](/configure-builds/manage-dependencies/) files such as `package.json` or `.nvmrc`, installs dependencies, and runs your build command. The build system will use this directory to perform caching during the build process. If not set, the base directory defaults to the root of the repository. * **Site files:** source files in your repository that represent the code for your site and any related configurations. Also known as your site’s package. * **Package directory:** typically used for monorepos, the directory that contains your site files, including the `netlify.toml`. Set this only if the location is different from the base directory. Learn more about how Netlify searches for your [configuration files in monorepos](/configure-builds/monorepos/#how-netlify-finds-your-configuration-files) . * **Build command:** the command to run to build your site if you are using a static site generator or other build tool. For example, `npm run build`. The build command runs in the Bash shell, allowing you to add Bash-⁠compatible syntax to the command. Visit the [frameworks](/frameworks/) doc to learn about typical build commands for popular tools. * **Publish directory:** directory that contains the deploy-ready HTML files and assets generated by the build. The directory is relative to the base directory, which is root by default (`/`). Visit the [frameworks](/frameworks/) doc to learn about typical publish directories for popular tools. Only files in the publish directory are deployed Files and assets located outside of the publish directory won’t be included in site deploys. * **Netlify configuration file:** optional configuration file (`netlify.toml`) that specifies how Netlify builds and deploys your site — including redirects, branch and context-specific settings, and more. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . [#](#automatic-monorepo-detection) Automatic monorepo detection ---------------------------------------------------------------- When you [create a new site from an existing repository](/welcome/add-new-site/#import-from-an-existing-repository) , Netlify automatically scans the repository to detect if you are using a monorepo. If Netlify detects multiple sites in your repository, the Netlify UI displays a list of the sites and directories for you to select under **Site to deploy**. Once you select a site to deploy, Netlify automatically fills in the **Build command** and **Publish directory** based on that selection. Netlify also uses this selection to set the **Package directory**, and leaves the **Base directory** unset. You can review both fields under **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** after you finish setting up your site. As the **Base directory** is not set, Netlify uses the root of the repository as the default to install dependencies and build your site. ![](/images/configure-builds-monorepos-autodetection.png) If the site you wish to deploy isn’t automatically detected, select `Other (configure manually)` in the list and you can [manually configure the site](#manual-configuration) instead. [#](#manual-configuration) Manual configuration ------------------------------------------------ If your site isn’t automatically detected, Netlify offers you the option to manually set the [base directory](#set-the-base-directory) , [package directory](#set-the-package-directory) , [build command](#set-the-build-command) , and [publish directory](#set-the-publish-directory) for your site. While there are multiple ways to set each of these values, the [recommended method](#recommendations-for-specific-setups) may differ depending on your project setup. ### [#](#set-the-base-directory) Set the base directory Want to run builds for your monorepo in root? To install dependencies and run builds in the root directory of your monorepo, you don’t need to set the base directory. Netlify uses the root of the repository as the default. If your Netlify configuration file is located with your project in a directory other than root, you can specify the location with a [package directory](#set-a-package-directory) . If not explicitly set, the [base directory](#definitions) defaults to the root of the repository. If you want to install dependencies and build your site in a subdirectory rather than root, you can specify this by setting a base directory. For example, if your repository has a monorepo workspace set up in a `/frontend` directory and other unrelated code in a `/backend` directory, you likely want to set your base directory to `/frontend` instead of root (`/`). You can set a base directory in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) stored at the root of your repository. Use the `base` property under `[build]` settings, and Netlify will use that value to set the base directory when you first set up the site. * if you’re creating a [Deploy to Netlify](/site-deploys/create-deploys/#deploy-to-netlify-button) button for other people to easily clone and deploy your site, use the [`base` query parameter](/site-deploys/create-deploys/#set-a-base-directory-for-monorepos) to set the base directory for that button. You can create different buttons for each site in your monorepo by setting a different `base` value for each button. A base directory specified in a root-level `netlify.toml` overrides the UI setting. ### [#](#set-the-package-directory) Set the package directory If you use a [monorepo](/configure-builds/monorepos/) and store your [site files](#definitions) in a different directory from your base directory, you can specify the location using the **Package directory** field in the Netlify UI. This is helpful if you want to install dependencies and run builds in the root but want to store your site’s source files, including the corresponding `netlify.toml`, in separate project directories. If you don’t set this value, Netlify will [search for the `netlify.toml`](/configure-builds/monorepos/#how-netlify-finds-your-configuration-files) in the base and root directories. In addition, if you don’t [set an explicit publish directory](#set-the-publish-directory) , Netlify uses the package directory to search for the directory that contains the output of your build (for example, a `dist` folder) and any related `_headers` and `_redirects` files within that directory. To set the package directory for a site: 1. Navigate to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . 2. Select **Configure**. 3. Enter the **Package directory**. For example, `/packages/website`. 4. Select **Save**. ### [#](#set-the-build-command) Set the build command You can manually set the [build command](#definitions) in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) . Use the `command` property under `[build]` settings. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . * using [Netlify CLI](/cli/get-started/) when setting up continuous deployment for a site. To find the typical build command for your framework, refer to the [frameworks](/frameworks/) doc. ### [#](#set-the-publish-directory) Set the publish directory You can manually set the [publish directory](#definitions) in the following ways: * in the Netlify UI, when you select **Add new site**. For an existing site, you can update the setting at **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . * in a [Netlify configuration file](/configure-builds/file-based-configuration/#build-settings) . Use the `publish` property under `[build]` settings. Learn more about [file-based configuration](/configure-builds/file-based-configuration/) . * using [Netlify CLI](/cli/get-started/) when setting up continuous deployment for a site. To find the typical publish directory for your framework, refer to the [frameworks](/frameworks/) doc. ### [#](#use-a-netlify-configuration-file) Use a Netlify configuration file You can configure most build and deploy settings for your site using a [Netlify configuration file](/configure-builds/file-based-configuration/) instead of the Netlify UI. Note that the [package directory](#set-the-package-directory) can only be set in the Netlify UI. Depending on your monorepo project setup, you may have one or more Netlify configuration files in your repository. The best practice is to have one Netlify configuration file for each site, where the settings in each file are unique to that site. Settings in a root configuration will apply to all sites in your monorepo. Netlify needs to know which files to use for your site build. You can either explicitly [set the location](#set-a-package-directory) of the site’s configuration files or rely on Netlify to find it in [either your base or root directory](#how-netlify-finds-your-configuration-files) . For a sample `netlify.toml` file, refer to the [file-based configuration](/configure-builds/file-based-configuration/#sample-netlify-toml-file) docs. For an example monorepo file structure that includes a different configuration file for each site, refer to the [recommended monorepo setup](#example-monorepo-setup) section below. Use absolute file paths in the `netlify.toml` To specify the location of plugins, functions, or other configuration details in `netlify.toml` for a site in your monorepo, use absolute paths that are relative to the base directory. If not set, the default value for the base directory is the root (`/`). For example, if the site’s base directory is `/frontend`, the site’s package directory is `/frontend/packages`, and the plugin is within `/frontend/packages/my-app/plugins`, the configuration file should specify the plugin location as `/packages/my-app/plugins/netlify-plugin-check-output-for-puppy-references`. #### [#](#how-netlify-finds-your-configuration-files) How Netlify finds your configuration files Netlify will search for configuration files in the following order: 1. Package directory 2. Base directory 3. Root directory [#](#commit-status-notifications) Commit status notifications -------------------------------------------------------------- You can manage the amount of commit status and commit check notifications for projects where one repository builds multiple applications. These types of [deploy notifications](/site-deploys/notifications/) are available on commit lists and pull/merge requests for Netlify sites connected to GitHub or GitLab and are also referenced as Commit status webhooks. 1. For your Netlify team, go to **Team settings \> Notifications \> Commit status webhooks** and select **Edit commit status webhooks**. 2. Choose one of the following options: * **Multiple webhooks per repo:** enables commit statuses and commit checks for multiple sites linked to a repository. ![Multiple Deploy Preview status checks per pull request.](/images/configure-builds-monorepo-commit-status-multiple-github.png) * **One webhook per repo:** limits commit checks and commit statuses in a pull/merge request or commit list to one linked site only, regardless of the number of sites linked to a repository. [#](#recommended-monorepo-setup) Recommended monorepo setup ------------------------------------------------------------ Whether you want to build a single site from a monorepo or multiple sites from a monorepo, the recommendations are the same: * Set the subdirectory that contains the site you want to deploy as your [package directory](#set-the-package-directory) . If you have custom configuration settings for the site in a `netlify.toml`, ensure the file is in the same directory. * Leave the base directory as the default, the repository root (`/`). * Define all dependencies at a more specific, subdirectory level, and leave dependency management up to the tool you’re using. For example, if you have a monorepo with a site that uses React and a component library that also uses React, you should list `react` as a dependency in `package.json` files within each subdirectory. With a Yarn workspace, for example, Yarn can hoist dependencies dynamically, moving them to the root of the repository whenever it makes sense to do so. ### [#](#example-monorepo-setup) Example monorepo setup Here’s an example directory structure for a monorepo that contains a component library and two sites to be hosted on Netlify: / ├─ apps/ │ ├─ app-1/ │ │ ├─ package.json │ │ ├─ netlify.toml │ │ ├─ ...app-1-source-files │ ├─ app-2/ │ │ ├─ package.json │ │ ├─ netlify.toml │ │ ├─ ...app-2-source-files │ ├─ other-packages/ │ ├─ component-library/ │ │ ├─ package.json │ │ ├─ ...component-library-source-files │ ├─ package.json There is a subdirectory for each site that contains the source files for that site and a `netlify.toml` with site-specific configurations. All necessary site dependencies are declared in `package.json` files within each subdirectory, and the root-level `package.json` is used to define a Yarn or npm workspace. In this example scenario, you would [create](/welcome/add-new-site/#import-from-an-existing-repository) two separate Netlify sites linked to the monorepo. If Netlify [automatically detects](#automatic-monorepo-detection) that you are using a monorepo during the set-up step for each site, you can select the directory to deploy in the Netlify UI and Netlify will configure the build settings for you. If you need to [configure the sites manually](#manual-configuration) , you can use the Netlify UI to set the [package directory](#set-the-package-directory) for each site to point to the site’s subdirectory within the monorepo. Leave the base directory unset for Netlify to use the repository root as the default value. For example, the package directory for the `app-1` site should be `apps/app-1` and the base directory should be unset. Based on this configuration, Netlify will access the site’s source files and configuration files from `apps/app-1` and will run the dependency installation and build command in the repository’s root (`/`). By default, any changes in the base directory (the repository root, by default) trigger a build of all connected sites. If you would like to only trigger site builds when a change occurs in the site’s subdirectory, you can add a custom [ignore builds command](/configure-builds/ignore-builds/#mimic-default-behavior) to the site’s `netlify.toml` file. No special configuration required if you declare dependencies at both the root and subdirectory level Most package managers, such as Yarn and npm, are context-aware now. This means that they can run in the root directory and manage dependencies declared in subdirectories as needed. In addition, Netlify’s build system caches all `node_modules` directories within the repository, regardless of where the dependencies are declared. [#](#more-build-configuration-resources) More build configuration resources ---------------------------------------------------------------------------- * [Common framework configurations](/frameworks/) * [JavaScript SPAs](/configure-builds/javascript-spas/) * [Ignore builds](/configure-builds/ignore-builds/) * [Netlify CLI - Work with monorepos](/cli/get-started/#work-with-monorepos) * [Netlify Blog: the Enhanced Monorepo Experience](https://www.netlify.com/blog/better-monorepos-on-netlify/) * [Example `netlify.toml` file](/configure-builds/file-based-configuration/#sample-netlify-toml-file) Last updated: March 12, 2024 ← [JavaScript SPAs](/configure-builds/javascript-spas/) [Ignore builds](/configure-builds/ignore-builds/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage build dependencies | Netlify Docs When you trigger a build on Netlify, our build system starts a Docker container to build your site. Before running your build command, the build system will search for instructions about required languages and software needed to run your command. These are called _dependencies_, and how you declare them depends on the languages and tools used in your build. Follow the guidelines below to specify your required dependencies, and Netlify will install them before running your build. Any executables from these dependencies will be made available from the PATH for the remainder of the build. [#](#node-js-and-javascript) Node.js and JavaScript ---------------------------------------------------- A build’s Node.js version is initially determined by the [default version](/configure-builds/available-software-at-build-time/) preinstalled on the site’s selected build image. We pin the site to that version so your builds won’t change even if the build image’s defaults change. You can choose the Node.js version we use to build your site in the following ways: * Navigate to **Site configuration \> Build & deploy \> Continuous deployment \> Dependency management** in the Netlify UI and select from the major Node.js versions that Netlify currently supports. Once you change the version, you need to redeploy your site for it to take effect. Note that a `NODE_VERSION` environment variable, `.node-version` file, or `.nvmrc` file will override this UI setting. * Set a `NODE_VERSION` [environment variable](/configure-builds/environment-variables/) with any released version of Node.js or any valid string that [nvm](https://github.com/nvm-sh/nvm#nvmrc) understands. You can either set a specific version or set a major version, such as the number `18` for the latest version of Node.js 18.x. * Add a `.node-version` or [`.nvmrc`](https://github.com/nvm-sh/nvm#nvmrc) file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. The file can include any released version of Node.js or any valid string that [nvm](https://github.com/nvm-sh/nvm#nvmrc) understands. You can either set a specific version or set a major version, such as the number `18` for the latest version of Node.js 18.x. The version of Node.js you use is dynamically fetched using `nvm` and then [cached](/configure-builds/manage-dependencies/#dependency-cache) to speed up subsequent builds. If you are using the Netlify CLI to run a build locally, make sure the Node.js version installed in your local environment matches the version set for your build on Netlify. If the versions don’t match, you may encounter errors. What about the Node.js version for functions? Typically, the functions runtime Node.js version automatically matches the version used for the build. If you need to customize the Node.js version for your functions, use the `AWS_LAMBDA_JS_RUNTIME` environment variable. Visit our docs on [Node.js version for runtime](/functions/optional-configuration/?fn-language=js#node-js-version-for-runtime-2) to learn more. ### [#](#node-js-environment) Node.js environment By default, Netlify’s build system sets `NODE_ENV` to `development`. You can change this value by setting a `NODE_ENV` [environment variable](/configure-builds/environment-variables/) . Dependencies and production If you set the `NODE_ENV` to `production`, any `devDependencies` in your `package.json` file will _not_ be installed for the build. ### [#](#javascript-dependencies) JavaScript dependencies If your build requires any JavaScript dependencies, you must list these in a `package.json` saved in the site’s [base directory](/configure-builds/overview/#definitions) in your repository. You can visit the npm docs to learn [how to create a package.json file](https://docs.npmjs.com/creating-a-package-json-file) . Tip If you’re having trouble linking to other repositories in your `package.json`, visit the [repository permissions and linking](/git/repo-permissions-linking/#access-other-repositories-at-build) doc for more information. #### [#](#npm) npm [npm](https://www.npmjs.com/) comes preinstalled with Node.js, so any build scripts using `npm run` will work automatically. By default, if your site’s repository does not include a `yarn.lock`, `pnpm-lock.yaml` or `bun.lockb` file, we will run `npm install` to install the dependencies listed in your `package.json`. You can customize your npm use with the following [environment variables](/configure-builds/environment-variables/) : * **`NPM_VERSION`:** variable that defaults to the version preinstalled with your version of Node.js. Accepts any released version number. * **`NPM_FLAGS`:** used to indicate the flags to pass to the `npm install` command. For example, you could pass the `--global` flag to make installed packages available outside your working directory. Learn more about npm flags in the [npm docs](https://docs.npmjs.com/cli/v8/using-npm/config#command-line-flags) . * **`NPM_TOKEN`:** used for authentication when installing private npm modules. Visit our Forums for a verified Support Guide on configuration details when [using private npm modules on Netlify](https://answers.netlify.com/t/common-issue-using-private-npm-modules-on-netlify/795) . #### [#](#pnpm) pnpm Netlify supports [pnpm](https://pnpm.io/) for Node.js 16.9.0 and later. If your site’s base directory includes a `pnpm-lock.yaml` file, we will run `pnpm install` to install the dependencies listed in your `package.json`. To specify a pnpm version, you can edit your `package.json` file: "packageManager": "pnpm@6.3.2" This tells Corepack to use and download your preferred pnpm version instead of the [default version](/configure-builds/available-software-at-build-time/#tools) that Netlify sets. Note that based on [Corepack limitations](https://github.com/nodejs/corepack/issues/95) , you cannot use [`semver`](https://docs.npmjs.com/cli/v6/using-npm/semver) to specify a range of versions for this package manager. In certain scenarios, you must pass additional flags to the `pnpm install` command. For example, some frameworks such as Nuxt 3 and Next.js require that you modify the `pnpm install` command. To avoid import issues with pnpm and these frameworks, use the `PNPM_FLAGS` environment variable and set it to `--shamefully-hoist`. #### [#](#yarn) Yarn Netlify can detect and install [Yarn](https://yarnpkg.com) and then use it to install your project’s dependencies. If you commit a `yarn.lock` file to your site’s repository or if your `packageManager` property specifies Yarn, Netlify will install Yarn and then run the `yarn` command to install the dependencies specified in your `yarn.lock` file. By default, Netlify will use the Yarn version preinstalled with your initial [build image](/configure-builds/overview/#build-image-selection) . Note that based on [Corepack limitations](https://github.com/nodejs/corepack/issues/95) , you cannot use [`semver`](https://docs.npmjs.com/cli/v6/using-npm/semver) to specify a range of versions for this package manager. To specify a different Yarn version: * You can edit your `package.json` file: "packageManager": "yarn@3.2.4" * Or, you can leverage Yarn’s way of vendoring a specific version by setting a [`yarnPath`](https://yarnpkg.com/configuration/yarnrc#yarnPath) inside a [`.yarnrc.yml` file](https://yarnpkg.com/configuration/yarnrc) . yarnPath: .yarn/releases/yarn-3.2.4.cjs nodeLinker: node-modules You can also customize your Yarn use with the following [environment variables](/configure-builds/environment-variables/) : * **`YARN_FLAGS`:** used to indicate the flags to pass to the `yarn` command. Includes `--ignore-optional` by default. You can override this by adding `--no-ignore-optional` to this variable. * **`YARN_NPM_AUTH_TOKEN`:** used for authentication when installing private npm modules. * **`NETLIFY_USE_YARN`:** deprecated variable that is supported but no longer recommended; undefined by default. If `true`, Netlify will install and run Yarn. If `false`, we will use npm or pnpm. If left unset, we will run Yarn if the site’s `package.json` specifies yarn as the package manager or if a `yarn.lock` file is present. * **`YARN_VERSION`:** deprecated variable that is supported but no longer recommended; defaults to the version preinstalled with your initial build image. Accepts any released version number. We recommend setting the version in `package.json` or through a `yarnPath` in `.yarnrmc.yml` instead. Yarn Berry requires a setting in `.yarnrc.yml` To build your project on Netlify with [Yarn 2.0.0 or later](https://github.com/yarnpkg/berry) , you must add `nodeLinker: node-modules` to a [`.yarnrc.yml` file](https://yarnpkg.com/configuration/yarnrc) , which is generally stored in your repository root. Netlify depends on the `node_modules` folder tree that’s generated with this setting. [Plug'n'Play](https://yarnpkg.com/features/pnp) is not currently supported on Netlify. #### [#](#bun) Bun Netlify can detect when your project is using [Bun](https://bun.sh/) and then use it to install your project’s dependencies. If you commit a `bun.lockb` file to your site’s repository, Netlify will run the `bun install` command to install the dependencies specified in your `bun.lockb` file. All builds will use the version [pre-installed in our build image](/configure-builds/available-software-at-build-time/) . You can also customize your Bun use with the following [environment variable](/configure-builds/environment-variables/) : * **`BUN_FLAGS`:** used to indicate the flags to pass to the `bun install` command. #### [#](#bower) Bower If your repository includes a `bower.json` file in the [base directory](/configure-builds/overview/#definitions) , we’ll automatically run `bower install --config.interactive=false` against it to install your Bower dependencies. This is _in addition to_ running any other requisite dependency management commands as described in this doc. [#](#go) Go ------------ A build’s initial Go version is determined by the [default version](/configure-builds/available-software-at-build-time/) for the site’s build image. We pin the site to that version so your builds won’t change even if the build image’s defaults change. You can change the Go version we use to build your site in the following ways: * Set a `GO_VERSION` [environment variable](/configure-builds/environment-variables/) with any released version of Go. You can also use `.x` suffix, such as `1.20.x`, to indicate the latest version of `1.20`. * Add a `.go-version` file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. The file can include any released version of Go. You can also use `.x` suffix, such as `1.20.x`, to indicate the latest version of `1.20`. `.go-version` overrides `GO_VERSION` Note that if your site has both a `.go-version` file and a `GO_VERSION` environment variable, the `.go-version` file takes precedence. We recommend matching your local development environment’s Go version to your selected build image’s Go version. You can use any version of Go that’s available on the [Go downloads page](https://golang.org/dl/) . The configured Go version is also used when compiling [Go serverless functions](/functions/lambda-compatibility/?fn-language=go) during the build. [#](#php) PHP -------------- The [default PHP version](/configure-builds/available-software-at-build-time/) is determined by the site’s selected build image. You can choose the PHP version we use to build your site by setting a `PHP_VERSION` [environment variable](/configure-builds/environment-variables/) . We recommend matching your local development environment’s PHP version to a version that your selected build image supports. For a list of supported versions, refer to the [available software at build time](/configure-builds/available-software-at-build-time/) doc. ### [#](#php-dependencies) PHP dependencies Add your PHP dependencies to a [`composer.json` file](https://getcomposer.org/doc/01-basic-usage.md) . Dependencies listed in `composer.json` are automatically installed with Composer, which is included in all build images. [#](#python) Python -------------------- The [default Python version](/configure-builds/available-software-at-build-time/) is determined by the site’s selected build image. You can choose the Python version we use to build your site in one of the following ways: * Set a `PYTHON_VERSION` [environment variable](/configure-builds/environment-variables/) . * Add a `runtime.txt` file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. The file must include the version number _only_: `x.y`, with no trailing newline. * Use [Pipenv](https://docs.pipenv.org/basics/#specifying-versions-of-python) to specify a version and save it to a `Pipfile` in the site’s [base directory](/configure-builds/overview/#definitions) in your repository. `runtime.txt` overrides `Pipfile` If the site’s base directory includes both a `runtime.txt` file and a `Pipfile`, Netlify will use the version specified in `runtime.txt`. The [list of supported versions](/configure-builds/available-software-at-build-time/) depends on the site’s selected build image. ### [#](#python-dependencies) Python dependencies If your build requires any Python dependencies, you must provide a list of these for installation using [pip](#install-via-pip) or [Pipenv](#install-via-pipenv) . #### [#](#install-using-pip) Install using pip If you manage your Python dependencies using [pip](https://pip.pypa.io/en/stable/cli/pip_install/) , you can generate a list of them by running the following command in the site’s [base directory](/configure-builds/overview/#definitions) in your repository: pip freeze > requirements.txt This creates a `requirements.txt` file that Netlify will use to install your dependencies by running `pip install`. Refer to the pip docs for more details about the [requirements file format](https://pip.pypa.io/en/stable/reference/requirements-file-format/) . #### [#](#install-using-pipenv) Install using Pipenv If you manage your Python dependencies using [Pipenv](https://pipenv-fork.readthedocs.io/en/latest/basics.html) , be sure to commit your `Pipfile` to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. Netlify will run `pipenv install` to install your dependencies. If you also commit your `Pipfile.lock`, this will ensure that `pipenv install` installs the same exact versions of your dependencies on Netlify as it does locally. `requirements.txt` overrides `Pipfile` If the site’s base directory includes both a `requirements.txt` file and a `Pipfile`, Netlify will run `pip install` to install the dependencies in `requirements.txt`, and ignore the dependencies in the `Pipfile`. [#](#ruby) Ruby ---------------- A build’s Ruby version is initially determined by the [default version](/configure-builds/available-software-at-build-time/) preinstalled on the site’s selected build image. We pin the site to that version so your builds won’t change even if the build image’s defaults change. You can choose the Ruby version we use to build your site in two different ways: * Set a `RUBY_VERSION` [environment variable](/configure-builds/environment-variables/) . * Add a `.ruby-version` file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. This will also tell any other developer using the repository which version of Ruby it depends on. No newlines in `.ruby-version` The `.ruby-version` file must include the version number _only_: `x.y.z`, with no trailing newline. Both methods above will accept any released version of Ruby, or any valid string that [RVM](https://github.com/rvm/rvm) understands. We recommend specifying a version of Ruby that matches your local development environment. If the version you select is preinstalled in your site’s selected build image, it will be available immediately. If not, your selected version will be installed using `rvm` and then [cached](/configure-builds/manage-dependencies/#dependency-cache) to speed up subsequent builds. ### [#](#ruby-dependencies) Ruby dependencies If your build requires any Ruby dependencies, you must list these in a `Gemfile` saved in the site’s [base directory](/configure-builds/overview/#definitions) in your repository. We use [Bundler](https://bundler.io/) to install the dependencies in that file. You can visit the Bundler docs to learn [how to manage Ruby dependencies with Bundler](https://bundler.io/v2.0/guides/using_bundler_in_applications.html) . If you run the `bundle install` command locally, Bundler will create a `Gemfile.lock` to record the gem names and versions installed. If you commit this file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository, we will install the exact versions specified in your `Gemfile.lock`. [#](#rust) Rust ---------------- Although [rustup](https://github.com/rust-lang/rustup/blob/master/README.md) and [cargo](https://doc.rust-lang.org/cargo/) are preinstalled, Netlify doesn’t install a default Rust toolchain. You must specify the Rust toolchain used to build your site in one of the following ways: * Add a [`rust-toolchain`](https://rust-lang.github.io/rustup/overrides.html#the-toolchain-file) file to the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. This is the recommended option. When a `rust-toolchain` file is present, cargo installs the toolchain when it first executes, for example, on `cargo build`. * Include a [toolchain install](https://rust-lang.github.io/rustup/concepts/toolchains.html) command as part of your site’s build command. Use the syntax `rustup toolchain install `, for example: `rustup toolchain install stable`. The build image supports any toolchain that rustup can install. The selected Rust toolchain is [cached](/configure-builds/manage-dependencies/#dependency-cache) to speed up subsequent builds. [Crates](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html) are cached in `~/.cargo/registry`, and compilation assets are cached in `target` if your working directory has a `Cargo.toml` or `Cargo.lock` file. ### [#](#rust-dependencies) Rust dependencies Include any Rust dependencies in a `Cargo.toml` manifest file in the base directory in your repository. If you also commit a `Cargo.lock`, this will ensure that cargo installs the same exact versions of your Rust dependencies on Netlify’s build image as it does locally. Dependencies aren’t installed automatically. Instead cargo fetches them when `cargo doc` or `cargo build` executes as part of the build command. [#](#swift) Swift ------------------ A default Swift version does not come preinstalled on a site’s selected [build image](/configure-builds/overview/#build-image-selection) . Instead, at the time of the first build, Netlify installs your specified Swift version in the build container. You can choose the Swift version we use to build your site in two different ways: * Set a `SWIFT_VERSION` [environment variable](/configure-builds/environment-variables/) . * Add a `.swift-version` file to the site’s [base directory](/configure-builds/overview/#definitions) in your repository. This will also tell any other developer using the repository which version of Swift it depends on. Both methods above will accept any Swift version that [swiftenv](https://github.com/kylef/swiftenv) can install that is later than Swift 4.x. Versions 4.x and earlier aren’t supported due to incompatible shared libraries. We recommend specifying a version of Swift that matches your local development environment. Default Swift version If no `SWIFT_VERSION` environment variable is set and no `.swift-version` file is present but a `Package.swift` file exists in the site’s [base directory](/configure-builds/overview/#definitions-1) in the repository, Netlify installs a default Swift version determined by the site’s selected [build image](/configure-builds/overview/#build-image-selection) . Your selected version will be initially installed using `swiftenv` and then [cached](/configure-builds/manage-dependencies/#dependency-cache) to speed up subsequent builds. ### [#](#swift-dependencies) Swift dependencies If your build requires any Swift dependencies, you must list these in a `Package.swift` manifest file saved in the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. During the build, our build system runs the `swift build` command, using [Swift Package Manager](https://swift.org/package-manager/) to install the dependencies and exact versions specified in `Package.swift`. For more information about managing dependencies with the manifest file, visit the [Swift Package Manager documentation](https://www.swift.org/documentation/package-manager/#importing-dependencies) . [#](#build-image-defaults) Build image defaults ------------------------------------------------ Netlify’s [build images](/configure-builds/overview/#build-image-selection) have default preinstalled versions for many languages and tools. For a full list of defaults and more information on how to manage versions, refer to our [available software at build time](/configure-builds/available-software-at-build-time/) doc. Not sure what build image your project uses? You can find out in the Netlify UI, by navigating to **Site configuration \> Build & deploy \> Continuous deployment \> Build image selection** . You can also find all of the software versions your build uses in your site’s [deploy logs](/site-deploys/overview/#deploy-log) . [#](#dependency-cache) Dependency cache ---------------------------------------- The first build you do can take some time while we install all of your dependencies. After the initial build, we’ll cache the dependencies so we don’t have to install them every time you push an update. This is intended to make subsequent builds faster. If you change your dependency requirements, the next build will re-run the installation command which may update cached dependencies if needed. It isn’t guaranteed a change will take place if the previous dependencies still satisfy the installer, though! You can check which directories are cached by searching for `$NETLIFY_CACHE_DIR` in the `run-build-functions.sh` file for your site’s selected [build image](/configure-builds/overview/#build-image-selection) . If a build fails, it’s worth retrying with a cleared build cache to check if this works better. You can do this by [deploying the latest branch commit](/site-deploys/manage-deploys/#retry-deploy-from-latest-branch-commit) with the clear cache option. Last updated: November 6, 2024 ← [Ignore builds](/configure-builds/ignore-builds/) [Build environment variables](/configure-builds/environment-variables/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Access data with Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify Connect makes it easy to access data from different data sources and types. Instead of having to make multiple API calls to retrieve data from each source, configure [cross-references](/connect/manage-data-layers/manage-cross-references/) and make a single query to your data layer’s unified GraphQL API. Plus, when you connect a site to your data layer, Netlify will automatically rebuild that site when a data source updates. For static sites, this ensures your site has the latest data from your GraphQL API. Which data revision is the data layer’s GraphQL API using? At the top of the data layer’s overview page, you will find information about the [data revision](/connect/data-revisions/) that your data layer’s GraphQL API is currently using — including the data revision ID and whether or not the API is using a pinned revision. This document outlines some [GraphQL concepts](#graphql-concepts) , how to use the [GraphQL sandbox](#use-the-graphql-sandbox) , how to access data using the [GraphQL API](#use-the-graphql-api) , and how to use the [Connect client](#use-the-connect-client) for a better user and developer experience. [#](#graphql-concepts) GraphQL concepts ---------------------------------------- Every data revision for a data layer has a unique [GraphQL schema](https://graphql.org/learn/schema/) that you use to build your data queries. Netlify automatically generates a new data revision to represent the latest schema whenever your data changes. By default, the GraphQL API and sandbox for your data layer will use the latest data revision unless you pin a different revision. You also have the option to query a specific dataset using the revision’s unique sandbox and API URL. You can use standard GraphQL queries and fragments to interact with your data. Note that mutations are not currently supported. * [Queries](https://graphql.org/learn/queries/) : how you get data. * [Fragments](https://graphql.org/learn/queries/#fragments) : reusable sets of fields. Regex is not currently supported While the GraphQL sandbox includes a regex option for filtering, regex is not currently supported in queries made in the sandbox or made directly to the GraphQL API. [#](#queries-and-edge-caching) Queries and edge caching -------------------------------------------------------- Connect automatically caches data at the network edge by default. Other than factoring in the query size limitation, noted below, there is no need to write queries a specific way to enable caching. The cache key is the combination of the query + variables + API token used for that query. If the body of your query (the GraphQL query plus the variables) is larger than 9 KB, the response will not be cached at the edge. You can calculate the size of your query body using a library such as [string-byte-length](https://www.npmjs.com/package/string-byte-length) . If your query body is larger than the limitation, you can [adjust your queries to add pagination](/connect/troubleshooting-tips/#responses-from-the-data-layer-api-are-slow) to ensure the responses are cached. Note that edge caching does not apply to queries made in the GraphQL sandbox. [#](#query-complexity) Query complexity ---------------------------------------- To help you consider performance while you write your queries, please note the following calculation that we use for query complexity in Connect. If you are able to keep the complexity level to under 1,500 points, you should not expect a notable performance impact. Calculated from request body (GraphQL query + schema): * Find many query: 10 points * Find one query: 5 points * Scalar field: 1 point * Non-scalar field: 3 points * Extra points per field: * Reference field: 5 points * List field: 5 points * Union field: 3 points Calculated from response body: * Objects: 1 point per obj * Response size: 5 points per kb [#](#use-the-graphql-sandbox) Use the GraphQL sandbox ------------------------------------------------------ The GraphQL sandbox is an isolated environment in the Netlify UI that you can use to build and test GraphQL operations without directly affecting your sites. Netlify creates a unique [GraphiQL](https://github.com/graphql/graphiql/blob/main/packages/graphiql/README.md) sandbox for each data layer that you create, and for each data revision that results from a successful data sync. Note that, although you query the GraphQL API from individual sites, the sandbox is only accessible from your team’s Connect page. Also, any queries you create in the sandbox have to be copied into your code manually. Use the Connect client to write queries directly in your editor Use the [Connect client](#use-the-connect-client) to write queries in your code editor and benefit from in-editor feedback, auto-completion, and type hints based on your data layer’s GraphQL schema. To access the GraphQL sandbox for a data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer overview page, select **GraphQL sandbox**. This sandbox represents the data revision that your API is currently using. To access the GraphQL sandbox for a specific data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer‘s overview page, select **Revisions** to access the list of available revisions. 4. Find the revision you want to access, select **Options**, and then select **Open in GraphQL sandbox**. ![Example data layer sandbox with a sample query and the query results displayed.](/images/connect-access-data-sandbox.png) At the top of the sandbox, you’ll find the ID of the data revision that the sandbox is using and when that revision was created. There is also an options menu that you can use to pin or unpin the data revision, download the changeset, and copy the data revision’s GraphQL sandbox link or API URL. The sandbox consists of three main areas: * In the left pane, the sandbox menu and sub-sections, including: * the GraphiQL explorer, which contains schema fields and types that you can expand and select to build queries with * the documentation explorer, which contains the [schema reference docs](#review-your-data-layer-schema) for the data revision * the sandbox history, which contains previous queries you have created and automatically [saved](#save-queries-for-later) * In the center pane, the area that you build the query in and buttons to run, copy, prettify, and merge fragments into the query. * In the right pane, the area that will contain the output when you run a query. ### [#](#review-the-graphql-schema) Review the GraphQL schema The sandbox includes a documentation explorer that contains the schema reference docs for that data revision. The explorer makes it easy to review the combined GraphQL schema for the data revision that was made while syncing all of the GraphQL types from your data sources. If you have added multiple data sources of the same type, such as two Drupal instances, you will notice the type prefix for each source reflected in the schema. This is helpful to know as you start building your queries. To review the schema in the GraphQL sandbox, select the book icon (labeled “Show Documentation Explorer” for screen readers) to open the documentation explorer and access the reference docs. You can select each type to learn more about all of the included Object types and fields. ![Example sandbox with the book icon and reference docs areas highlighted.](/images/connect-access-data-sandbox-reference-docs.png) ### [#](#build-and-run-a-query) Build and run a query To build a query using the GraphQL schema for a data revision, you have two options: 1. Toggle open the types in the GraphiQL explorer to find the fields to add to your query. Select items as needed and the query in the center section of the sandbox will update to include your selection. ![](/images/connect-access-data-sandbox-select-query.png) 2. Enter your query directly in the center pane. As you write the query, the sandbox will suggest fields to add based on the schema. You can continue typing or just select the correct suggestion to add it to your query. ![](/images/connect-access-data-sandbox-type-query.png) You can add more specificity to your query by selecting the `filter`, `limit`, `skip`, and `sort` options in the explorer and then entering the logic for your modifier either in the left pane or the center pane. ![](/images/connect-access-data-sandbox-with-limit.png) To run the query, press control + enter or select the play icon (labeled “Execute query” for screen readers) in the center pane. The query results will appear in the pane on the right. ![](/images/connect-access-data-sandbox-run-query.png) Once you have a query that works for you, copy the query into your codebase and [use the GraphQL API](#use-the-graphql-api) to request and access this data in your site. ### [#](#save-queries-for-later) Save queries for later When you use the GraphQL sandbox, we automatically save the queries in the sandbox so that you can return to them later. You can find old queries by selecting the history icon (labeled “Show History” for screen readers) in the left pane to open the sandbox history section. ![](/images/connect-access-data-sandbox-view-saved-queries.png) Since the sandbox uses your browser’s `localStorage` to save the queries, saved queries are only be available to you and in the browser you create them in. Other team members do not have access to your saved queries when they use the sandbox. Note that saved queries will appear across all versions of the sandbox but the query will only run against and return data for the associated data revision. To confirm which data revision you are querying against, check the data revision ID at the top of the sandbox. To clear all saved queries, select the settings icon (labeled “Open settings dialog” for screen readers) in the bottom left to open the sandbox settings. Then, under **Clear storage**, select **Clear data**. ![](/images/connect-access-data-sandbox-clear-saved-queries.png) [#](#use-the-graphql-api) Use the GraphQL API ---------------------------------------------- To use data in your site, add code that sends a query to the data layer’s GraphQL API. By default, your data layer’s GraphQL API uses the latest data revision unless you pin a different one. You also have the option to query a specific data revision using the unique API URL for that revision. For the most part, the code to query a GraphQL API is the same whether you query in a component file or in a function. But, depending on where you query the API, you need to set up your data layer correctly to ensure your site always has access to the latest data. Learn more about [when to connect your site](/connect/manage-data-layers/manage-connected-sites/#when-to-connect-a-site) . Once you have the [GraphQL API URL](#find-the-graphql-api-url) and an [API token](#generate-an-api-token) , you can write your query. We recommend using the [Connect client](#use-the-connect-client) for in-editor type system support and caching optimizations, but there are a number of other [tools you can use to query](https://graphql.org/code/) . The examples below use the Connect client. Use the GraphQL sandbox or Connect client to verify types If you specify a prefix while adding a data source to your data layer, the prefix is added to all types synced from that data source. This impacts the types you use in your queries. You can confirm what the final types are in the [GraphQL sandbox](/connect/access-data/#review-your-data-layer-schema) or by using the [Connect client](#use-the-connect-client) . ### [#](#generate-an-api-token) Generate an API token You must authenticate all requests to your data layer’s GraphQL API using an [API token](/connect/api-authentication/#manage-api-tokens) . If your data layer restricts access to certain fields and types using [API scopes](/connect/api-authentication/#manage-api-scopes) , the API token must have the required scopes to access that data. Make sure to include the API token in the authorization header for all API requests. If you use the [Connect client](/connect/access-data/#use-the-connect-client) , you can store the token in an environment variable and the client will automatically apply it for you. Learn how to generate API tokens and scopes in the [API authentication](/connect/api-authentication/) doc. ### [#](#find-the-graphql-api-url) Find the GraphQL API URL By default, your data layer’s GraphQL API uses the latest data revision unless you pin a different one. The API URL is formatted as `https://{data_layer_key}-prod.api.netlify-connect.com`. Note that the data layer key is different from the data layer ID. To find the GraphQL API URL for your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. Find the `API URL` at the top of the page. You can also find the `API URL` under **Data layer settings \> General \> Data layer information** . ![](/images/connect-access-data-graphql-api-url.png) If you want to access the GraphQL API for a specific data revision, use the API URL for that revision. Learn how to [access the API for a specific data revision](/connect/data-revisions/#query-the-graphql-api-for-a-revision) . ### [#](#query-in-site-code) Query in site code Use Connect client if your site uses SSR with caching For sites that use server-side rendering (SSR) with caching, we recommend querying your data layer’s API with the [Connect client](#use-the-connect-client) to benefit from more efficient caching of dynamic content. It doesn’t matter if your site uses static site generation (SSG) or uses server-side rendering (SSR), the code to query the API is the same. Here is an example that uses [Connect client](#use-the-connect-client) in an Astro project to query the API for the `id` and `title` of the first 10 nodes under `allContentfulAsset`. 1. Follow the three steps to [configure the Connect client](#configure-and-use-the-client) . Make sure to create `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables with the URL and API token for your data layer’s GraphQL API. 2. Depending on the architecture of your app, add the following code to the appropriate file to request data before your component is rendered. Make sure you update the query to reflect your schema. * Loading error: Refresh the page to access this code sample import { query } from "@netlify/connect-client"; import { graphql } from "../netlify-connect/graphql"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); const getAssets = async (Astro: any) => { const res = await query(assetQuery, { Astro }); return res.allContentfulAsset.nodes; }; const assets = await getAssets(Astro); import { query } from "@netlify/connect-client"; import { graphql } from "../netlify-connect/graphql"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); const getAssets = async (Astro) => { const res = await query(assetQuery, { Astro }); return res.allContentfulAsset.nodes; }; const assets = await getAssets(Astro); When you query, the Connect client automatically accesses the `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables stored on Netlify and adds their values to the API request header for you. 3. Update your component code to use the results returned from the query (`assets` in the above example). To ensure your site always has access to the latest data, review our doc on [when to connect your site](/connect/manage-data-layers/manage-connected-sites/#when-to-connect-a-site) . ### [#](#query-in-a-function) Query in a function Here is an example of how to query the API in a function. Every request to this endpoint receives the latest results from the API. This example uses [Connect client](#use-the-connect-client) to query the API for the `id` and `title` of the first 10 nodes under `allContentfulAsset`. 1. Follow the three steps to [configure the Connect client](#configure-and-use-the-client) . Make sure to create `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables with the URL and API token for your data layer’s GraphQL API. 2. [Create a function file](/functions/get-started/#create-function-file) in the functions directory. For example, `YOUR_BASE_DIRECTORY/netlify/functions/get-data.js`. 3. In the file, add the following code to create a function that queries the API and returns the data. Make sure you update the query to reflect your schema. * Loading error: Refresh the page to access this code sample // YOUR_BASE_DIRECTORY/netlify/functions/get-data.ts import type { Context } from "@netlify/functions"; import { query } from "@netlify/connect-client"; import { graphql } from "../../src/netlify-connect/graphql"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); export default async (req: Request, context: Context) => { const data = await query(assetQuery); return new Response(JSON.stringify(data)); }; // YOUR_BASE_DIRECTORY/netlify/functions/get-data.js import { query } from "@netlify/connect-client"; import { graphql } from "../../src/netlify-connect/graphql"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); export default async (req, context) => { const data = await query(assetQuery); return new Response(JSON.stringify(data)); }; When your site makes a request to the endpoint at `/.netlify/functions/get-data` relative to the base URL of your site, the function runs and uses the Connect client to query the data layer. The Connect client automatically accesses the `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables stored on Netlify and adds their values to the API request header before making the query. Since the function makes the API request during runtime, it always gets the latest data from your data layer, even if you don’t rebuild your site. ### [#](#query-in-an-edge-function) Query in an edge function Here is an example of how to query the API in an edge function. Every request to a path that matches the edge function path receives the latest results from the API. This example uses [Connect client](#use-the-connect-client) to query the API for the `id` and `title` of the first 10 nodes under `allContentfulAsset`. 1. Follow the three steps to [configure the Connect client](#configure-and-use-the-client) . Make sure to create `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables with the URL and API token for your data layer’s GraphQL API. 2. [Create an edge function file](/edge-functions/get-started/#create-an-edge-function) in the edge functions directory. For example, `YOUR_BASE_DIRECTORY/netlify/edge-functions/get-data.js`. 3. In the file, add the following code to create an edge function that queries the API and returns the data. Make sure you update the query to reflect your schema. * Loading error: Refresh the page to access this code sample // YOUR_BASE_DIRECTORY/netlify/edge-functions/get-data.ts import type { Config, Context } from "@netlify/edge-functions"; import { query } from "@netlify/connect-client"; import { graphql } from "../../src/netlify-connect/graphql.ts"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); export default async (req: Request, context: Context) => { const data = await query(assetQuery); return new Response(JSON.stringify(data)); } export const config: Config = { path: "/get-data", }; // YOUR_BASE_DIRECTORY/netlify/edge-functions/get-data.js import { query } from "@netlify/connect-client"; import { graphql } from "../../src/netlify-connect/graphql.ts"; // Note this is a relative path const assetQuery = graphql(` query MyQuery { allContentfulAsset(limit: 10) { nodes { id title } } } `); export default async () => { const data = await query(assetQuery); return new Response(JSON.stringify(data)); } export const config = { path: "/get-data", }; When your site makes a request to the `/get-data` path relative to the base URL of your site, the edge function runs and uses the Connect client to query the data layer. The Connect client automatically accesses the `DATA_LAYER_API_URL` and `DATA_LAYER_API_TOKEN` environment variables stored on Netlify and adds their values to the API request header before making the query. Since the edge function makes the API request during runtime and does not cache the results, it always gets the latest data from your data layer, even if you don’t rebuild your site. #### [#](#avoid-queries-in-edge-functions-configured-for-caching) Avoid queries in edge functions configured for caching Since Connect automatically caches data at the network edge, we don’t recommend using an [edge function configured for caching](/edge-functions/optional-configuration/#response-caching) to query the API. There are no extra performance benefits to gain from using edge function caching on top of the built-in caching in Connect, and it will likely add unnecessary complexity. We recommend that you use an [edge function that is not configured for caching](#query-in-an-edge-function) instead. [#](#use-the-connect-client) Use the Connect client ---------------------------------------------------- Use the Connect JavaScript client, [`connect-client`](https://www.npmjs.com/package/@netlify/connect-client) , to make requests to your data layer’s GraphQL API for an optimized user and developer experience. When you use the client, you benefit from the following: * **Efficient caching of dynamic content on Netlify’s CDN.** Instead of invalidating the full cache every time your data changes, you can invalidate only the stale content. This optimizes site performance for your users and is particularly helpful if your site uses a framework with SSR caching. * **TypeScript type system support, enhanced by [gql.tada](https://gql-tada.0no.co/) .** Benefit from in-editor feedback, auto-completion, and type hints based on your data layer’s GraphQL schema. This provides a better developer experience and allows you to write queries directly in your site code instead of copying them over from the GraphQL sandbox. Refer to the readme to learn more about [how Connect client supports caching](https://www.npmjs.com/package/@netlify/connect-client#how-connect-client-supports-caching) . ### [#](#cache-optimization-support) Cache optimization support While you can use the client with any framework to query the API and get in-editor type system support, the built-in caching optimization is currently only supported for Astro and Next.js. If you use a different framework with SSR caching, we recommend that you add your own cache management logic using [on-demand invalidation](/platform/caching/#on-demand-invalidation) . Alternatively, you can choose to [connect your site](/connect/manage-data-layers/manage-connected-sites/#connect-a-site) for a full redeploy and [cache invalidation](/platform/caching/#automatic-invalidation-with-atomic-deploys) every time your data changes. While it may not be the most efficient option, it ensures you always have the latest data. ### [#](#configure-and-use-the-client) Configure and use the client As outlined in the [`connect-client` readme](https://www.npmjs.com/package/@netlify/connect-client?activeTab=readme) , there are three steps to set up and use the client with your site: 1. [Install the client and configure your project](https://www.npmjs.com/package/@netlify/connect-client#install-the-connect-client-and-configure-your-project) . If you only want to use the client to query your data layer’s API and to get in-editor type system support, stop here. Otherwise, complete the following steps to set up the client and your data layer to support cache invalidation. 2. [Create a function to handle cache invalidation](https://www.npmjs.com/package/@netlify/connect-client#create-a-function-to-handle-cache-invalidation) . 3. [Set up a notification on your data layer](https://www.npmjs.com/package/@netlify/connect-client#set-up-a-notification-on-your-data-layer) . Once you set up the client and your project, you can use the client to make queries in your site code. For examples, refer to the sections above on how to query in [site code](#query-in-site-code) , a [function](#query-in-a-function) , and an [edge function](#query-in-an-edge-function) . The client automatically adds the authorization headers for each request and, if you completed all three steps, manages the data caching as needed. Ensure the API token has the correct scopes If your data layer restricts access to certain fields and types using [API scopes](/connect/api-authentication/#manage-api-scopes) , make sure the API token you set for the client or pass to the individual query has the required scopes to access that data. For detailed instructions, refer to the [`connect-client`readme](https://www.npmjs.com/package/@netlify/connect-client?activeTab=readme) . ### [#](#limitations-and-billing) Limitations and billing * **Cache optimization is only for Next.js and Astro.** While you can use the client with any framework to query the API and get in-editor type system support, the built-in caching optimization is currently only supported for Astro and Next.js. * **Netlify Functions limits and billing apply.** Since the client requires you to add a serverless function to your site, you should review the [default deployment options](/functions/overview/#default-deployment-options) and [usage and billing documentation](/functions/usage-and-billing/) for Netlify Functions. [Manage connected sites in Netlify Connect: When to connect a site](/connect/manage-data-layers/manage-connected-sites/#when-to-connect-a-site) Last updated: November 26, 2024 ← [API authentication](/connect/api-authentication/) [Sync events](/connect/sync-events/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # On-demand Builders | Netlify Docs On-demand Builders are serverless functions used to generate web content as needed that’s automatically cached on Netlify’s Edge CDN. They enable you to build pages for your site when a user visits them for the first time and then cache them at the edge for subsequent visits. Consider serverless functions with the durable cache instead For better performance and fewer function invocations, consider using [serverless functions with the `durable` directive](/platform/caching/#durable-directive) instead of On-demand Builders. Key characteristics of On-demand Builders: * They are Lambda-compatible serverless functions written [in TypeScript](/functions/lambda-compatibility/?fn-language=ts) or [in JavaScript](/functions/lambda-compatibility/?fn-language=js) . * They accept GET requests only. * They don’t provide access to HTTP headers or query parameters from incoming requests. * They are protected from repeated invocations by caching generated pages or assets. * They use the request’s URL path to determine whether to create a new cache object or reuse an existing one. This approach can’t be customized with [cache key variations](/platform/caching/#cache-key-variation) . * They use the [response type](#cached-responses) to determine whether or not to cache the response. * They support an optional [time to live (TTL)](#time-to-live-ttl) pattern for configuring caching. They don’t support [cache control headers](/platform/caching/) . * They buffer responses. They don’t support response streaming. * A new site deploy invalidates the cached responses associated with builders in the same [deploy context](/site-deploys/overview/#deploy-contexts) , such as the same Deploy Preview number or the same branch deploy. On-demand Builders were designed to achieve [_Distributed Persistent Rendering_ (DPR)](https://www.netlify.com/blog/2021/04/14/distributed-persistent-rendering-a-new-jamstack-approach-for-faster-builds/) on Netlify. They also currently enable support for Incremental Static Regeneration (ISR) for [Next.js sites using Netlify’s Next.js Runtime v4](/frameworks/next-js/runtime-v4/overview/) . You can join the conversation about DPR and ISR in our [Support Forums](https://answers.netlify.com/categories) . [#](#cached-responses) Cached responses ---------------------------------------- Successful responses, redirection responses, and Not Found responses are cached at the edge and served to subsequent requests. That is, any response with a status code of `2xx` (such as `200` or `201`), `301`, `302`, `307`, `308`, or `404` is cached. If you use [Time to Live (TTL)](#time-to-live-ttl) , responses with the above status codes invalidate the cache after the TTL expires. Responses with any other status codes, such as `500`, are not cached. [#](#create-on-demand-builders) Create On-demand Builders ---------------------------------------------------------- To get started, follow our docs to create a Lambda-compatible function [in TypeScript](/functions/lambda-compatibility/?fn-language=ts) or [in JavaScript](/functions/lambda-compatibility/?fn-language=js) . Use the synchronous function format, and return a response that can be served as a cached static asset. To convert the function to a builder, use the `builder()` method from the [`@netlify/functions`](https://github.com/netlify/functions) package. First, add the package to your site dependencies: npm install -D @netlify/functions Then, pass your function as a parameter to the `builder()` method and export this method as the `handler` from your function file. * Loading error: Refresh the page to access this code sample import { builder, type Handler } from "@netlify/functions"; const myHandler: Handler = async (event, context) => { // logic to generate the required content }; const handler = builder(myHandler); export { handler }; const { builder } = require("@netlify/functions") async function handler(event, context) { // logic to generate the required content } exports.handler = builder(handler); For example, your builder could return a full HTML page or a processed image file. Here’s a “hello world” example: * Loading error: Refresh the page to access this code sample import { builder, type Handler } from "@netlify/functions"; const myHandler: Handler = async (event, context) => { return { statusCode: 200, headers: { "Content-Type": "text/html", }, body: ` Hello World `, }; }; const handler = builder(myHandler); export { handler }; const { builder } = require("@netlify/functions") async function handler(event, context) { return { statusCode: 200, headers: { "Content-Type": "text/html", }, body: ` Hello World `, }; } exports.handler = builder(handler); On success, this builder returns a `200` status code and an HTML page with a “Hello World” message. This successful response is cached at the edge and served to subsequent requests. If the initial invocation of a builder fails with a status code that is not one of the [cached response codes](#cached-responses) , for example because a third-party API is down and the response status is `500`, the erroring response is served but not cached. The next request will retry the builder to get a successful response. For a working example of using On-demand builders with code to explore, you can visit this [example site](https://every-color.netlify.app/) and its corresponding [code repository](https://github.com/netlify/example-every-color) . ### [#](#time-to-live-ttl) Time to live (TTL) On-demand Builders support an optional time to live (TTL) pattern that allows you to set a fixed duration of time after which a cached builder response is invalidated. This allows you to force a refresh of a builder-generated response without a new deploy. You can set a TTL for your builder by including a `ttl`, in seconds, in your response. `ttl` has a minimum value of 60. * Loading error: Refresh the page to access this code sample import { builder, type Handler } from "@netlify/functions"; const originalResponse = { body: ':thumbsup:', statusCode: 200, ttl: 3600, }; const myHandler: Handler = async (event, context) => { // logic to generate the required content return originalResponse; }; const handler = builder(myHandler); export { handler }; const { builder } = require("@netlify/functions") const originalResponse = { body: ':thumbsup:', statusCode: 200, ttl: 3600, } async function handler(event, context) { // logic to generate the required content return originalResponse } exports.handler = builder(handler); After the TTL has expired, the next request triggers a builder invocation to regenerate the content. The previously cached response is served for 60 seconds after a refresh is triggered. If the refresh is successful and returns with one of the [cached response codes](#cached-responses) , the updated response is cached and served until the next successful refresh. If the refresh fails and returns with any other status code, for example because a third-party API is down, the previously cached successful response is served until the next successful refresh. ### [#](#confirm-request-type) Confirm request type Incoming requests to On-demand Builders include a `x-nf-builder-cache` header that indicates whether the request is an initial request for your content or a background refresh request. This gives you the opportunity to add conditional logic to your builder depending on the request type — for example, you might want to serve a loading page while a user waits for an initial request to complete. To confirm the type of the incoming request, check the `x-nf-builder-cache` header value in the `headers` property of the `event` object. If the header’s value is `miss`, the request is an initial blocking request from the browser that needs to complete before a user can take next steps. If the header’s value is `revalidate`, the request is an asynchronous TTL refresh request that runs in the background. ### [#](#environment-variables) Environment variables On-demand Builders have access to environment variables in the runtime environment. If you have the option to set specific scopes for your environment variables, the scope must include **Functions** to be available to On-demand Builders during runtime. Learn more about how to set and use [environment variables with functions](/functions/environment-variables/) . [#](#use-on-demand-builders) Use On-demand Builders ---------------------------------------------------- Similar to other functions, On-demand Builders can be invoked at endpoints relative to the base URL of your site. Builders, however, use a unique `builders` path for invocation: `/.netlify/builders/FUNCTION_NAME`. Builder endpoints can be called directly like regular web URLs or can be executed by redirecting traffic from another URL. For example, consider a news site with a large amount of infrequently visited, archived content. You can use a builder to generate those less-frequented pages on-demand when a user requests them. The request URL might be something like this: https://myawesomenews.com/.netlify/builders/my-archive-builder/article/199x-news The first call to the builder invokes it and returns the generated page, assuming that’s the logic in your function. Subsequent calls return the cached page content until the next deploy or until the [time to live (TTL)](#time-to-live-ttl) has elapsed. In another example, if you want to replace a static image `src` with a custom-sized image generated using a builder, you can format an `img` tag like this: kittens. The first builder call processes and returns the image, and subsequent calls return the cached image until the next deploy or until the [TTL](#time-to-live-ttl) has elapsed. ### [#](#customize-paths-with-redirects) Customize paths with redirects In the example above, you might prefer to use a different URL instead of the default builder endpoint. You can do this by redirecting traffic from a URL to the builder using [redirect rules](/routing/redirects/) in the `_redirects` file or `netlify.toml` Netlify configuration file. Here are some examples with [`_redirects` file](/routing/redirects/#syntax-for-the-redirects-file) and [`netlify.toml`](/routing/redirects/#syntax-for-the-netlify-configuration-file) syntax. * Loading error: Refresh the page to access this code sample /images/* /.netlify/builders/my-image-transformer 200 /archive /.netlify/builders/my-archive-builder 200 [[redirects]] from = "/images/*" to = "/.netlify/builders/my-image-transformer" status = 200 [[redirects]] from = "/archive" to = "/.netlify/builders/my-archive-builder" status = 200 The original path is passed to the builder as part of the event object. To continue an example from above, a call to `/images/kittens.jpg/width/640` triggers the `my-image-transformer` function with the following values passed to it as part of the `event`: { "path": "/images/kittens.jpg/width/640", "httpMethod": "GET" ... } For more information about the `event` parameter and the Lambda-compatible Netlify Functions programming model, refer to our docs on [synchronous function format for TypeScript](/functions/lambda-compatibility/?fn-language=ts#synchronous-function-format) or [JavaScript](/functions/lambda-compatibility/?fn-language=js#synchronous-function-format-2) . #### [#](#redirect-workaround-for-query-parameters) Redirect workaround for query parameters On-demand Builders currently don’t process or cache query parameters from redirected paths. In most cases, it’s preferable to embed these parameters into the path directly, but in cases where you don’t control the path, you can re-shape it with an additional redirect rule to the path resolution. The first rule must have a `3XX` [HTTP status code](/routing/redirects/redirect-options/#http-status-codes) , as that ensures a new URL for our redirects engine to process the second rule, passing your new path to the builder. Here’s an example in `_redirects` syntax: /generated/image url=:url w=:w /img/:url/:w 301! /img/:url/:w /.netlify/builders/image 200 #### [#](#shadowing) Shadowing Redirect rules leverage [shadowing](/routing/redirects/rewrites-proxies/#shadowing) , which means that they trigger only if there isn’t already an asset at the specified `from` path. This can be useful if your prebuilt assets and content generated by your builder share the same path. If you prefer to trigger the proxy regardless of the presence of a pre-built asset, you can append `!` to the status code in the `_redirects` file, or add `force = true` in `netlify.toml`. ### [#](#local-development) Local development You can build and test logic like any other function using [Netlify Dev](/cli/local-development/) . When testing locally, however, caching isn’t available. ### [#](#secure-on-demand-builders) Secure On-demand Builders You can use the same authentication and authorization strategy as the rest of your Netlify site to secure builders. We recommend using JSON Web Tokens (JWT), roles, and redirect rules for managing granular access. Refer to [our docs on role-based access control](/security/secure-access-to-sites/role-based-access-control/) to learn more. ### [#](#limits) Limits * The maximum response payload size for a builder is 6 MB. * Pages or assets generated by On-demand Builders are limited to 10,000 per deploy. For a higher limit, please [contact sales](https://www.netlify.com/contact/) . If the limit is reached, additional generated pages or assets will have reduced caching and may be regenerated upon subsequent requests. * There is a 30 second execution time limit that results in a timeout. [#](#usage-and-billing) Usage and billing ------------------------------------------ Requests to builders that return a previously non-cached response count towards your [Netlify Functions usage](/functions/usage-and-billing/) for billing purposes. This includes requests per month and run time per month. If a cached response is available and served, no function invocation is made and no usage is incurred against your Netlify Functions allotment. On-demand Builders execution doesn’t count towards build minutes. Last updated: September 6, 2024 ← [File-based configuration](/configure-builds/file-based-configuration/) [Build hooks](/configure-builds/build-hooks/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Monitor activity in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify provides logs to help you observe and troubleshoot activity on your data layer. You can access data layer activity logs to [review sync activity](#review-data-layer-sync-events) and the team audit log to [review team member activity](#review-team-member-activity) . [#](#review-data-layer-sync-events) Review data layer sync events ------------------------------------------------------------------ Logs are retained for 5 days Currently, Netlify only retains Connect logs for five days. Older events are listed in the **Activity** section, but the logs are unavailable. To review [sync events](/connect/sync-events/) for a data layer, navigate to the overview page for that data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer you want to review from the **Data layers** list. 3. Review the **Activity** section and select a sync event in the list to access the detailed log. ![Example data layer activity section with a sync event expanded to reveal the detailed logs.](/images/connect-monitor-expand-logs.png) To review the associated data revision for a successful sync, select **Revisions**. ### [#](#set-up-slack-notifications) Set up Slack notifications Set up subscriptions to get notified of sync event failures with the [Netlify App for Slack](/slack-app/) . If a data layer sync event fails, the app automatically notifies the Slack channel you specify. 1. Follow the instructions to [authorize and install the Netlify App for Slack](/slack-app/#set-up-the-netlify-app-for-slack) . 2. Go to **Team settings \> Notifications \> Slack notifications** . 3. Select **Add subscription**. 4. Select `Connect sync events` as the **Event type**, and select the Slack **Channel** to notify. 5. Select **Create subscription**. Note that you can only set up the subscription using the Netlify UI. It is not possible to set up the subscription from a Slack channel. [#](#review-team-member-activity) Review team member activity -------------------------------------------------------------- To help you audit and troubleshoot changes to your data layer, Netlify automatically logs changes to the following items in your team audit log: * **API scopes:** when a team member adds, edits, or deletes an API scope for a data layer. * **API tokens:** when a team member generates, updates, or revokes an API token for a data layer. * **Connected sites:** when a team member connects or disconnects a site. * **Cross-references:** when a team member adds, edits, or deletes a cross-reference. * **Data layers:** when a team member creates, updates, or deletes a data layer. * **Data revisions:** when a team member pins or unpins a data revision. * **Data sources:** when a team member creates, updates, or deletes a data source. * **Notifications:** when a team member creates or deletes a notification. * **Webhooks:** when a team member creates or deletes a webhook. To access these logs, navigate to your team’s **Audit log** . Learn more about the [team audit log](/accounts-and-billing/team-management/team-audit-log/) . Last updated: November 26, 2024 ← [Sync events](/connect/sync-events/) [Troubleshooting tips](/connect/troubleshooting-tips/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Data revisions in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Every data layer in Netlify Connect has access to a unified GraphQL API with support for multiple data revisions. With each successful [data sync](/connect/sync-events/) , Netlify generates a new data revision for your data layer that represents the GraphQL schema and data at that point in time. You can query against each data revision using the revision’s GraphQL sandbox or its unique API URL. By default, your data layer’s GraphQL API uses the latest data revision but you also have the option to pin a different data revision instead. The ability to pin and access different data revisions for your data layer allows you to: * rollback and point your data layer’s API to a specific data revision while you troubleshoot and fix bugs * lock the data layer’s API to a specific data revision while you prepare for a major release * access and audit data from a specific date and time Netlify records the pinning and unpinning of data revisions in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . Data revisions include cross-references When Netlify generates a new data revision for your data layer, the revision includes any [cross-references](/connect/manage-data-layers/manage-cross-references/) that apply at the time. If you add, edit, or delete a cross-reference, the changes only apply to new data revisions generated after that modification. This document provides an overview of data revisions in Connect. It also outlines how to pin and unpin revisions, and how to access their data. [#](#manage-data-revisions) Manage data revisions -------------------------------------------------- Every successful sync to your data layer generates a new data revision, with a unique data revision ID. ![Example data layer overview with a pinned data revision and list of data revisions.](/images/connect-data-revisions-manage-data-revisions.png) At the top of the data layer’s overview page, you will find information about the data revision that your data layer’s GraphQL API is currently using — including the data revision ID and whether or not the API is using a pinned revision. Netlify retains data revisions for 60 days All data revisions are deleted after 60 days, except for the data revision that the API is currently using (by default or as a result of pinning). In the Netlify UI, you can [review](#review-data-revisions) all available data revisions. You can also manage which data revision your API uses by [pinning](#pin-a-data-revision) and [unpinning](#unpin-a-data-revision) data revisions. ### [#](#review-data-revisions) Review data revisions To review the data revisions available for your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer’s overview page, select **Revisions**. The data revision that your API is currently using is labelled with either the `Default` or `Pinned` badge. The `Pinned` badge indicates that you have pinned this specific data revision and the API will always use this one, even if newer revisions are available. The `Default` badge indicates that you have not pinned a data revision and the API is using this newest revision by default. ### [#](#pin-a-data-revision) Pin a data revision When you pin a data revision, the GraphQL API for your data layer will lock to that data revision. Successful syncs will continue to generate new data revisions but the API will always use this version. The data layer’s API URL and GraphQL sandbox will reflect the pinned revision but you can still access other data revisions using each revision’s unique API URL and sandbox. To pin the latest data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. At the top of the data layer’s overview page, select **Pin data revision**. ![](/images/connect-data-revisions-pin-revision-data-layer-card.png) 4. To confirm, select **Pin the latest data revision**. To pin an older data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer‘s overview page, select **Revisions** to access the list of available data revisions. 4. Find the revision you want to pin, select **Options**, and then select **Pin this data revision**. ![](/images/connect-data-revisions-pin-older-data-revision.png) 5. To confirm, select **Pin this data revision**. Netlify will automatically rebuild and redeploy your connected sites to ensure they use data from this pinned data revision. ### [#](#unpin-a-data-revision) Unpin a data revision When you unpin a data revision, the data layer’s GraphQL API will default to the most recent data revision. As Netlify syncs new data and generates new revisions, the API will always point to the latest one. Note that if you unpin a data revision that is older than the retention period of 60 days and a newer revision is available, the old revision will be deleted within 24 hours. To unpin the data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. At the top of the data layer’s overview page, select **Unpin data revision**. ![](/images/connect-data-revisions-unpin-revision-data-layer-card.png) 4. To confirm, select **Unpin data revision**. Netlify will automatically rebuild and redeploy your connected sites to ensure they use data from the most recent data revision. [#](#access-data-revisions) Access data revisions -------------------------------------------------- For each data revision, you have the option to download the changeset and make GraphQL queries using a revision-specific sandbox and API URL. ### [#](#download-the-changeset-for-a-revision) Download the changeset for a revision For each data revision, you get access to a changeset JSON file that outlines what new data was synced in the selected data revision compared to the previous data revision. To access the changeset for a data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer‘s overview page, select **Revisions** to access the list of available revisions. 4. Find the revision you want to review, select **Options**, and then select **Download changeset (JSON)**. ### [#](#use-the-graphql-sandbox-for-a-revision) Use the GraphQL sandbox for a revision You can access the GraphQL sandbox for a data revision to build, test, and run queries on the data from a specific point in time. To access the sandbox for a specific data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer‘s overview page, select **Revisions** to access the list of available revisions. 4. Find the revision you want to access, select **Options**, and then select **Open in GraphQL sandbox**. Note that saved queries will appear across all versions of the sandbox but the query will only run against and return data for the associated data revision. To confirm which data revision you are querying against, check the data revision ID at the top of the sandbox. Learn more about [using the GraphQL sandbox](/connect/access-data/#use-the-graphql-sandbox) in Connect. ### [#](#query-the-graphql-api-for-a-revision) Query the GraphQL API for a revision You can access the GraphQL API for a data revision to query the data as it existed at a specific point in time. Each data revision has a unique API URL, with the following format: `https://{data_layer_key}-{data_revision_id}.api.netlify-connect.com`. Note that the data layer key is different from the data layer ID. If you haven’t already, remember to [generate an API token](/connect/api-authentication/#generate-an-api-token) before you query the API. To find the GraphQL API URL for a specific data revision: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. On the data layer‘s overview page, select **Revisions** to access the list of available revisions. 4. Find the revision you want to access, select **Options**, and then select **Copy revision API URL**. Learn more about [using the GraphQL API](/connect/access-data#use-the-graphql-api) in Connect. Last updated: May 29, 2024 ← [Manage data layers](/connect/manage-data-layers/overview/) [API authentication](/connect/api-authentication/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage cross-references in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. After you [create and configure a data layer](/connect/get-started/) , you can add cross-references to create links between fields across data sources. When you request data, Netlify automatically resolves the cross-references so that you can get all of the related information at once and through a single query. This makes for a better developer experience and a faster user experience because you avoid having to do a series of queries, waiting for each one to resolve before making the next, and then manually combining the data yourself. Cross-references resolve for queries made in the [GraphQL sandbox](/connect/access-data/#use-the-graphql-sandbox) and through the [GraphQL API](/connect/access-data/#use-the-graphql-api) . Team Owners and Developers can add and update cross-references. Netlify records all activities related to adding, editing, and deleting cross-references in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . New to Connect? Set up a data layer first If you haven’t already created a data layer, navigate to the **Connect** page for your team and select **Add new data layer**. Follow the prompts to configure the data layer and to add data sources, connected sites, and notifications. For more information, refer to our [get started with Netlify Connect](/connect/get-started/) guide. [#](#how-cross-references-work) How cross-references work ---------------------------------------------------------- To understand how cross-references work, consider an example where you use Drupal for your site copy and Contentstack for your product information. Each `DrupalPage` represents a page in your site and contains a `contentstack_sku` field that identifies a product from Contentstack to display on that page. Similarly, each `ContentstackProduct` represents a product and contains a unique identifier in the `sku` field. Without cross-references, you would query for all the `DrupalPage` entities first and then do a second query using the `contentstack_sku` field to get the related `ContentstackProduct` entity for each `DrupalPage`. Instead of making a series of queries, you can add a cross-reference to create a link between the `contentstack_sku` field on `DrupalPage` and the `sku` field on `ContentstackProduct` first. ![](/images/connect-manage-data-layers-cross-references-example.png) Then, whenever you query for `DrupalPage` entities, Netlify resolves the cross-reference and automatically returns the `ContentstackProduct` entity for the `contentstack_sku` field on each `DrupalPage`. Essentially, the type of `contentstack_sku` becomes `ContentstackProduct`, so you can access all of the fields on the product directly in the query for the `DrupalPage`: query drupalToContentstack { drupalPage(title: { eq: "Store"}) { id title field_description body { value } contentstack_sku { refId reference { id title price image { url } } } } } [#](#add-a-cross-reference) Add a cross-reference -------------------------------------------------- Cross-references are available for select data sources Support for cross-references is currently available for data layers that use the following data source types: Contentful, Contentstack, Drupal, Shopify, and WordPress. Additional support is coming soon. Connect supports cross-references for string and number field types. You can configure cross-references to one level deep but you can query the resolved links to any depth required. To add a cross-reference to your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Cross-references**. 4. Select **Add a cross-reference**. 5. Select a **Data source**, a **Type** on that data source, and then a **Field** on that type. 6. Next, define the other half of the cross-reference relationship. Select a **Data source**, a **Type** on that data source, and then a **Field** on that type. Then, specify whether this field references a **Single** entity with a unique identifier, or if there are **Multiple** entities that share the same identifier. 7. Select **Save**. When you add a cross-reference, Netlify automatically starts a data sync to generate a new [data revision](/connect/data-revisions/) that reflects the updated schema. Existing data revisions represent the schema at a specific point in time and will not include the new cross-reference. [#](#edit-a-cross-reference) Edit a cross-reference ---------------------------------------------------- To edit a cross-reference on your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Cross-references**. 4. Find the cross-reference you want to edit and select **Options \> Edit** . 5. Update the cross-reference as needed and then select **Save**. When you edit a cross-reference, Netlify automatically starts a data sync to generate a new [data revision](/connect/data-revisions/) that reflects the updated schema. Existing data revisions represent the schema at a specific point in time and will not include the updated cross-reference. [#](#delete-a-cross-reference) Delete a cross-reference -------------------------------------------------------- When you delete a cross-reference, the change applies to new [data revisions](/connect/data-revisions/) generated after the update. Existing data revisions represent the schema at a specific point in time and will still include the deleted cross-reference. Unless you [pin the current data revision](/connect/data-revisions/#pin-a-data-revision) or update your site to [use the GraphQL API for that revision](/connect/data-revisions/#query-the-graphql-api-for-a-revision) , any queries for cross-referenced data will break once the deletion takes effect. Make sure to update the queries in your site or pin the data revision before deleting the cross-reference. Because this action cannot be reversed, only Team Owners can delete a cross-reference. To delete a cross-reference from your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Cross-references**. 4. Find the cross-reference you want to delete and select **Options \> Delete** . 5. Review the confirmation prompt and then select **Delete cross-reference**. When you delete a cross-reference, Netlify automatically starts a data sync to generate a new [data revision](/connect/data-revisions/) that reflects the updated schema. Last updated: November 26, 2024 ← [Manage data sources](/connect/manage-data-layers/manage-data-sources/) [Manage connected sites](/connect/manage-data-layers/manage-connected-sites/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage connected sites in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. After you [create and configure a data layer](/connect/get-started/) , you can review and modify the data layer on the settings page in the Netlify UI. This document outlines how to add and remove connected sites for an existing data layer. [Connected sites](/connect/get-started/#definitions) are sites in your Netlify team that will automatically build and deploy when data changes. Learn more about [when to connect a site](#when-to-connect-a-site) . Team Owners and Developers can add or delete connected sites at any time. Netlify records the addition and deletion of connected sites in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . Once you connect a site, the [build hooks](/configure-builds/build-hooks/) for the site will include a `Netlify Connect - Data layer` build hook with the data layer ID as the value. This provides a convenient way on the site level to check whether a site is connected to a data layer. ![](/images/connect-connect-sites-build-hooks.png) New to Connect? Set up a data layer first If you haven’t already created a data layer, navigate to the **Connect** page for your team and select **Add new data layer**. Follow the prompts to configure the data layer and to add data sources, connected sites, and notifications. For more information, refer to our [get started with Netlify Connect](/connect/get-started/) guide. [#](#when-to-connect-a-site) When to connect a site ---------------------------------------------------- When you connect a site to your data layer, Netlify adds a [build hook](/configure-builds/build-hooks/) to the site and uses it to automatically build and deploy your site whenever data changes. We recommend that you connect any sites that use static site generation (SSG). When your data layer updates, Netlify automatically rebuilds your site and any static code that includes queries to your GraphQL API receives the latest data. The new deploy also automatically [invalidates the cache](/platform/caching/#automatic-invalidation-with-atomic-deploys) for your site. All other site types should skip this step. If your site uses SSR with caching, we recommend that you use the [Connect client](/connect/access-data/#use-the-connect-client) for efficient management of cached data. If you use a framework other than Astro and Next.js, you can add your own cache management logic using [on-demand invalidation](/platform/caching/#on-demand-invalidation) . Sites that use functions and edge functions to query during runtime and don’t cache the responses always have access to the latest data. The same is true for sites that use a framework that handles server-side rendering (SSR) with functions or edge functions without caching enabled. The following table outlines some common options and how they compare: | API request location | Query timing | Connect your site? | | --- | --- | --- | | [Site code](/connect/access-data/#query-in-site-code)
for SSG (static site generation) | Build time | Yes | | [Site code](/connect/access-data/#query-in-site-code)
for SSR (server-side rendering) powered by Netlify Functions or Netlify Edge Functions | Runtime | No | | [Site code](/connect/access-data/#query-in-site-code)
for frameworks that cache SSR (server-side rendering) pages, such as Remix. | Runtime but then cached for each edge node | No, use [Connect client](/connect/access-data/#use-the-connect-client)
instead | | [Function code](/connect/access-data/#query-in-a-function) | Runtime | No | | [Edge function code (not configured for caching)](/connect/access-data/#query-in-an-edge-function) | Runtime | No | [#](#connect-a-site) Connect a site ------------------------------------ For Netlify to automatically build and deploy your site when data changes, your site must be [linked to a Git repository](/git/repo-permissions-linking/#link-a-git-repository) to enable continuous deployment, and it must have [active builds](/configure-builds/stop-or-activate-builds/) . To connect a site to your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Connected sites**. 4. Select **Search by site name or domain** and start entering the name or domain of the site you want to connect. 5. When the site appears in the results list, select the site to connect it. [#](#disconnect-a-site) Disconnect a site ------------------------------------------ Note that when you disconnect a site, Netlify will no longer automatically build and deploy the site whenever data changes. This may result in inconsistent content. You can’t disconnect a site by manually deleting the [build hooks](/configure-builds/build-hooks/) on the site level. You can only disconnect a site by editing the data layer. To disconnect a site from your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Connected sites**. 4. Find the site you would like to disconnect in the **Connected sites** list and select **Disconnect**. 5. A confirmation prompt will appear. Review the details and then select **Disconnect**. Last updated: November 26, 2024 ← [Manage cross-references](/connect/manage-data-layers/manage-cross-references/) [Manage notifications](/connect/manage-data-layers/manage-notifications/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Netlify Connect overview | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. With Netlify Connect, you can integrate content from multiple sources into a single data unification layer for easy access through a GraphQL API. Data updates sync automatically to ensure your sites and other web properties always have access to the latest content, all cached at the edge. ![](/images/connect-overview-diagram.png) When you unify your content sources through Connect, you unlock a number of benefits that make it easier to modernize your web architecture: * A single data unification layer that is cached at the network edge and is optimized for global availability, reliability, and performance * No-code integrations that allow you to use data from legacy systems alongside data from your modern CMS * The ability to create private data integrations that allow you to use data from your proprietary systems * A scalable GraphQL API that allows you to use CMS providers without having to worry about the CMS API’s rate-limiting or expensive bandwidth usage limits * Flexibility to access data through the GraphQL API with any frontend framework — including Remix, Next.js, Gatsby, Vue, Svelte, and Astro * Multiple data revisions cached for each data layer that capture the GraphQL schema and data at a point in time, with the ability to pin a specific revision for your API to use while planning for a major release or troubleshooting an error * The ability to specify cross-references between data sources and retrieve combined data through a single query for a faster user experience and better developer experience * Reduced web architecture migration risk with a modular approach that allows you to create data redundancy (by caching data in Connect) and then change or update architecture components over time Individual integrations versus Connect Connect is an Enterprise-only feature that’s best for those who have data spread across multiple data sources. If you want to sync data from a single data source, we recommend you review our individual [integrations](/integrations/overview/) instead, including our [Contentful integration](/integrations/contentful-integration/) . [#](#supported-data-sources) Supported data sources ---------------------------------------------------- Connect supports the following data source types: * commercetools * Contentful * Contentstack * Drupal * Salesforce Commerce Cloud * Shopify * WordPress * Custom — third-party or proprietary data sources supported by private or partner data integrations built with the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) Build support for your custom data source with the Netlify SDK Use the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) to develop a data integration for Connect. Data integrations use [Connectors](https://developers.netlify.com/sdk/connectors/overview/) to specify the data model and logic for syncing data from a third-party or proprietary data source. Once you publish your data integration, users can install and configure it to start syncing data. [#](#enable-connect) Enable Connect ------------------------------------ To enable Connect, [contact our sales team](https://www.netlify.com/contact/) to request a demo. Once enabled, the **Connect** page will be unlocked in the Netlify UI for your team. [#](#get-started) Get started ------------------------------ Once a Sales team member has enabled Connect for your team, here’s how to get started: 1. [Create your first data layer](/connect/get-started/#create-and-configure-a-data-layer) with at least one data source and site connected. 2. [Monitor the events](/connect/monitor-activity/#review-data-layer-sync-events) as we complete the initial data sync for your new data layer. 3. [Use the GraphQL sandbox](/connect/access-data/#use-the-graphql-sandbox) to create and test queries against your data layer. 4. [Generate an API token](/connect/api-authentication/#manage-api-tokens) to use in all requests to the GraphQL API. 5. Add code to your site to [query the GraphQL API](/connect/access-data/#use-the-graphql-api) for your data layer and use the results in your site. For a better user and developer experience, use the [Connect client](/connect/access-data/#use-the-connect-client) for your queries. 6. Modify content in your data source, [review the data sync event](/connect/monitor-activity/#review-data-layer-sync-events) , and confirm that your connected sites rebuild to get the latest data. 7. Go back and edit your data layer to [add more data sources](/connect/manage-data-layers/manage-data-sources/) and [add cross-references](/connect/manage-data-layers/manage-cross-references/) . If you need to, you can also [access different data revisions](/connect/data-revisions/#access-data-revisions) and [pin](/connect/data-revisions/#pin-a-data-revision) a specific revision for your API to use. You can also add [API scopes](/connect/api-authentication/#manage-api-scopes) to restrict access to certain data and then [generate new API tokens](/connect/api-authentication/#manage-api-tokens) to access that data. Repeat the above steps to [add additional data layers](/connect/get-started/#create-and-configure-a-data-layer) , as needed. [#](#limitations) Limitations ------------------------------ * **Connect logs are retained for 5 days**. All [sync events](/connect/sync-events/) are listed in the **Activities** section but the logs are currently retained for only five days. * **Data revisions are retained for 60 days**. All [data revisions](/connect/data-revisions/) are deleted after 60 days, except for the data revision that the API is currently using (by default or as a result of pinning). * **Continuous deployment is required for site updates**. For Netlify to automatically build and deploy your site when data changes, your site must be [linked to a Git repository](/git/repo-permissions-linking/#link-a-git-repository) to enable continuous deployment, and it must have [active builds](/configure-builds/stop-or-activate-builds/) . * **Data changes trigger only production branch builds for connected sites**. When data changes in your data layer, Netlify automatically builds and deploys the [production branch](/site-deploys/overview/#definitions) of all connected sites. Currently, it’s not possible to specify a different branch to connect. But, you can [use notifications as a workaround](/connect/troubleshooting-tips/#trigger-builds-automatically-for-a-specific-branch) . * **Responses to large queries do not get cached**. If your query is larger than 9 KB, the response will not be cached at the edge. Learn more about [how to adjust your queries](/connect/troubleshooting-tips/#responses-from-the-data-layer-api-are-slow) to ensure the responses are cached and data is returned faster. [#](#more-connect-resources) More Connect resources ---------------------------------------------------- * [Video: introducing Netlify Connect](https://www.youtube.com/watch?v=IwdFLZCVgCE) * [Video: Netlify Connect demo](https://www.youtube.com/watch?v=KQuhP4QMMus) * [Netlify SDK: build data integrations for Connect](https://developers.netlify.app/sdk/get-started/introduction/) * [Troubleshooting tips for Connect](/connect/troubleshooting-tips/) * [Connect usage and billing](/connect/usage-and-billing/) * [Connect JavaScript client](https://www.npmjs.com/package/@netlify/connect-client) Last updated: November 26, 2024 [Get started with Netlify Connect](/connect/get-started/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. To get started with Netlify Connect, create and configure your first data layer. A data layer allows you to sync and combine data from multiple sources into a single real-time graph database that you can query against with a GraphQL API. When you set up a data layer, you add data sources to sync data from. You also connect sites and add webhooks to notify whenever data updates. ![Diagram illustrating the parts of a data layer, and how data and notifications flow through the data layer to your sites and webhooks.](/images/connect-get-started-data-layer-diagram.png) This document outlines some [key terms](#definitions) , the four steps to [create and configure a data layer](#create-and-configure-a-data-layer) , and [what to do next](#what-next) . [#](#definitions) Definitions ------------------------------ Here are some key terms that are useful to understand as you get started with Connect: * **Data layer:** contains connections to one or more data sources, a real-time graph database containing all data synced from those sources, and a GraphQL API to access that data. It also supports connecting to sites to trigger builds when your data changes, and setting up notifications to notify external services. * **Data revisions:** every successful sync to a data layer generates a new [data revision](/connect/data-revisions/) that represents the GraphQL schema and data at that point in time. By default, a data layer’s GraphQL API uses the latest data revision, but you can also pin a different revision instead. You can query a specific data revision using the revision’s GraphQL sandbox or its unique API URL. * **Data source:** an external system or service that contains your data, such as a content management system (CMS). Connect has built-in support for a number of [data source types](/connect/overview/#supported-data-sources) and you can add support for your own custom data source with the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) . * **Data integration:** an extension built using the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) that allows you to sync data from a custom data source to Connect. Data integrations use [Connectors](https://developers.netlify.com/sdk/connectors/overview/) . * **Type prefix:** required when you want to add multiple data sources of the same type to a data layer, such as two Contentful CMS instances. When Netlify generates the GraphQL schema for your data layer, it will add the prefix to all GraphQL types from that data source. * **Cross-reference:** a link that you can create between fields across data sources. Netlify automatically resolves [cross-references](/connect/manage-data-layers/manage-cross-references/) when you query, so you can retrieve combined data through one query instead of a series of queries. * **GraphQL API:** allows web clients to query and receive data from a data layer on Connect. A data layer’s GraphQL API defaults to use the latest data revision unless you pin a different data revision. Each data revision has a specific GraphQL [schema](https://graphql.org/learn/schema/) based on your data sources, and you use this schema to construct queries and API requests. * **GraphQL sandbox:** an isolated environment in the Netlify UI that you can use to build and test queries against a data layer’s GraphQL API. Netlify creates a unique sandbox for each data layer that you create and for each data revision that results from a successful sync. * **Connected sites:** sites in your Netlify team that will automatically build and deploy when data changes. We use [build hooks](/configure-builds/build-hooks/) to trigger these builds. * **Notifications:** outgoing webhooks that will notify other services when there is a new sync for your data layer. * **Webhooks:** used to trigger a data layer sync from an external system. For example, your data source may send a POST request to a webhook URL to start a new sync. * **Sync events:** [activities](/connect/sync-events/) that occur in Connect when you add a data source and when data changes. These events include `Sync from all data sources` and `Sync from {data source type}`. [#](#prerequisite-enable-connect) Prerequisite: Enable Connect --------------------------------------------------------------- To enable Connect, [contact our sales team](https://www.netlify.com/contact/) to request a demo. Once enabled, the **Connect** page will be unlocked in the Netlify UI for your team. [#](#create-and-configure-a-data-layer) Create and configure a data layer -------------------------------------------------------------------------- Team Owners and Developers can set up data layers for your team. This includes creating the data layer, adding data sources, connecting Netlify sites, and adding notifications — activities that Netlify automatically logs to the [team audit log](/connect/monitor-activity/#review-team-member-activity) . You can create more than one data layer to fit your needs. For example: * One data layer for production data and sites to use, and another for staging data and sites to use * Different data layers for different departments or products across your organization Once you create a data layer, you can add one or more data sources to sync data from. You can select from the data sources Netlify officially supports as well as custom data sources supported through integrations built with the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) . The Netlify UI includes a guided flow to help you create and configure a new data layer. To get started, [add a data layer](#_1-add-a-data-layer) . Need to add a new data source to an existing data layer? If you want to add a new data source, site, notification, or webhook to an existing data layer, you can do this from the data layer settings page. To learn more, review our [manage data layers](/connect/manage-data-layers/overview/) doc. ### [#](#_1-add-a-data-layer) 1. Add a data layer To start the guided flow to add and configure a new data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select **Add new data layer**. 3. Enter a **Name** for this data layer. 4. (Optional) Enter a **Description**. 5. Select **Add data layer**. At this point, Netlify will create an empty data layer for your team with the provided name and description. The [next step](#_2-connect-data-sources) is to add data sources. ### [#](#_2-add-data-sources) 2. Add data sources The second step in the data layer configuration flow is to add one or more data sources to your data layer. We recommend that you add at least one data source now, but you will have the option to add more after you complete this flow. Each supported data source type has different credentials, options, and set up instructions. Select the type of data source: * commercetools * Contentful * Contentstack * Drupal * Salesforce Commerce Cloud * Shopify * WordPress * Other commercetools Contentful Contentstack Drupal Salesforce Commerce Cloud Shopify WordPress Other #### [#](#commercetools) commercetools commercetools is a dynamic data source The data integration for commercetools uses a dynamic connector, which means that Netlify proxies requests directly to the commercetools API every time you make a request for data. As a result, the data is never cached in Connect and you cannot use [cross-references](/connect/manage-data-layers/manage-cross-references/) and [API scopes](/connect/api-authentication/#manage-api-scopes) with this data source. To use commercetools, complete the following steps: 1. [Set up an API client in Account Manager](#set-up-an-api-client-in-your-commercetools-project) . 2. [Add your commercetools instance](#add-your-commercetools-instance) and API information to your data layer. ##### [#](#set-up-an-api-client-in-your-commercetools-project) Set up an API client in your commercetools project To enable syncing data from commercetools, you need to [create an API Client](https://docs.commercetools.com/merchant-center/api-clients#create-an-api-client) with the correct scopes in the commercetools Merchant Center: 1. In the Merchant Center for your commercetools project, navigate to **Settings \> Developer settings** . 2. Select **Create New API Client**. 3. Enter a **name** for the client. 4. Under **Scopes**, select the `Admin client` template. 5. Select **Create API client** to finish. Copy and save the `client_id`, `secret`, and `scope` values in a safe place because you will need them to set up the data source connection. ##### [#](#add-your-commercetools-instance) Add your commercetools instance Once you have [set up an API client](#set-up-an-api-client-in-your-commercetools-project) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `commercetools` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [commercetools extension details page](https://app.netlify.com/extensions/commercetools-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Enter a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. When you query data, the data types synced from this data source should be nested under this prefix in the GraphQL schema. For example, if your prefix is `StoreCA`, your query for `orders` would be formatted as: query { StoreCA { orders { ... } } } 5. Enter the **Secret** for the [API client you created](#set-up-an-api-client-in-your-commercetools-project) in commercetools Merchant Center. 6. Enter the **Client ID** for the API client. The Merchant Center displays this value as the `client_id`. 7. Enter the **Region** for your project. For example, `us-east-2.aws`. 8. Enter the **Scope** for the API client. 9. Enter the **Project key** for your project. 10. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#contentful) Contentful To use Contentful with Netlify Connect, complete the following steps: 1. [Prepare your Contentful instance](#prepare-your-contentful-instance) . 2. [Add your Contentful instance](#add-your-contentful-instance) to your data layer. ##### [#](#prepare-your-contentful-instance) Prepare your Contentful instance Take the following steps on your Contentful space before you add it to your data layer: 1. In the Contentful web app, navigate to **Settings \> API keys** , and select **Add API key** to [create an API key](https://www.contentful.com/developers/docs/references/authentication/#api-keys-in-the-contentful-web-app) and generate access tokens for the space you want to sync. Netlify will need one of these tokens to access your data. 2. In the Contentful web app, navigate to **Settings \> CMA tokens** , and select **Create personal access token** to generate a [Content Management API](https://www.contentful.com/developers/docs/references/authentication/#the-content-management-api) access token. Copy this token and store it in a safe place. Netlify will need this token to automatically set up a webhook in your Contentful space that will notify Connect whenever data changes in your CMS. 3. To enable automatic syncing to Netlify, add your data layer webhook to your Contentful instance: 1. In your Contentful account, navigate to **Settings \> Webhooks** , and select **Add webhook**. 2. Add the following webhook to the **URL** field. Make sure to replace the placeholder with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 3. Under **Triggers**, select the content types that you wish to sync and the events that should trigger a sync. For more information on how to configure webhooks, refer to the [Contentful docs](https://www.contentful.com/developers/docs/webhooks/configure-webhook/) . 4. Select **Save** to finish. If you decide to configure the webhook using the Contentful API instead, add a `x-connect-data-source` header to the request with `contentful` as the header’s value. This ensures that the webhook only triggers a sync for this specific data source, instead of all data sources on your data layer. ##### [#](#add-your-contentful-instance) Add your Contentful instance Once you have [prepared your Contentful instance](#prepare-your-contentful-instance) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `Contentful` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [Contentful extension details page](https://app.netlify.com/extensions/contentful) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Enter a **Prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `ContentfulPost` with the prefix `Marketing` becomes `MarketingContentfulPost` in the schema. 5. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 6. Enter the **Access token** for your Contentful instance. To sync published content, enter the `Content Delivery API access token`. To sync preview content instead, enter the `Content Preview API access token`. 7. Enter the **Space ID** for your Contentful instance. 8. Enter the **Content Management API access token** for your Contentful instance. Netlify will use this token to automatically set up a webhook in your Contentful space that will notify Connect whenever data changes in your CMS. 9. (Optional) Select the **Host URL** for your Contentful instance. The default is `cdn.contentful.com`. To use the Contentful Preview API, select `preview.contentful.com`. 10. (Optional) Enter the Contentful **Environment** to sync data from. The default is `master`. 11. (Optional) Enter a **Page limit** to specify the number of entries to fetch per page when syncing data from Contentful. The default is `100`. 12. (Optional) Select **Enable Contentful Tags** if your Contentful instance uses the [Contentful Tags feature](https://www.contentful.com/developers/docs/references/content-delivery-api/#/reference/tags) . Note that if you enable this option, you cannot use the content type name `tags` at this time. 13. (Optional) Fill in the **Locales** field to limit the locales Netlify will sync. By default, Netlify will sync all locales. Make sure these locales are enabled on Contentful. Netlify will use the default locale set in Contentful as the default locale for your source. 14. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#contentstack) Contentstack To use Contentstack with Connect, complete the following steps: 1. [Prepare your Contentstack instance](#prepare-your-contentstack-instance) . 2. [Add your Contentstack instance](#add-your-contentstack-instance) to your data layer. ##### [#](#prepare-your-contentstack-instance) Prepare your Contentstack instance Take the following steps on your Contentstack instance before you add it to your data layer: 1. In your Contentstack account, navigate to **Settings \> API Tokens** for your stack, and generate a [delivery token](https://www.contentstack.com/docs/developers/create-tokens/create-a-delivery-token) for the environment you want to sync. You’ll need to enter this token when you set up your Contentstack data source in the Netlify UI, and Netlify will use this token to access your data. 2. To enable automatic syncing to Netlify, add your data layer webhook to your Contentstack instance: 1. In your Contentstack account, navigate to **Settings \> Webhooks** for your stack, and select **New Webhook**. 2. Add the following webhook to the **URL To Notify** field. Make sure to replace the placeholder with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 3. Under **Trigger Conditions**, add a **Condition** for each content type and event that you wish to sync. At minimum, you should configure the webhook to trigger when the `Entry` type is `Created`, `Updated`, and `Deleted`. For more information on how to configure webhook conditions, refer to the [Contentstack docs](https://www.contentstack.com/docs/developers/set-up-webhooks/create-a-webhook) . 4. Select **Save** to finish. ##### [#](#add-your-contentstack-instance) Add your Contentstack instance Once you have [prepared your Contentstack instance](#prepare-your-contentstack-instance) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `Contentstack` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [Contentstack extension details page](https://app.netlify.com/extensions/contentstack-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Enter a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `ContentstackPost` with the prefix `Marketing` becomes `MarketingContentstackPost` in the schema. 5. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 6. Enter the **API key** for your stack. 7. Enter the read-only **Delivery token** for your stack environment. 8. Enter the stack **Environment** to sync data from. For example, the `production` environment. 9. (Optional) Enter the **Region** to sync data from. Valid options are `na-aws`, `eu-aws`, `na-azure`, and `eu-azure`. The default is `na-aws`. 10. (Optional) Specify the **Locales** to sync entries from. For example, `en-us, fr-ch`. 11. (Optional) When entries aren't available for the specified locale, you can sync them in the fallback language instead. Select **Include Fallback Locale** to enable this. The default is `false`. 12. (Optional) Enter a **Limit** to specify the number of entries or assets to sync per page. The default is `50`. 13. (Optional) Enter the **Content Types** to sync from Contentstack. For example, `author, book`. 14. (Optional) Enter the **Content Types to exclude** from Contentstack syncs. 15. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#drupal) Drupal Connect supports Drupal versions 9 and 10. To use Drupal with Connect, complete the following steps: 1. [Prepare your Drupal instance](#prepare-your-drupal-instance) . 2. [Add your Drupal instance](#add-your-drupal-instance) to your data layer. ##### [#](#prepare-your-drupal-instance) Prepare your Drupal instance Take the following steps on your Drupal instance before you add it to your data layer: 1. Install [Gatsby Integration module](https://www.drupal.org/project/gatsby) version 2. During the installation flow, follow the prompts to enable the [JSON:API Extras](https://www.drupal.org/project/jsonapi_extras) module. 2. In the [JSON:API Extras](https://www.drupal.org/project/jsonapi_extras) module, enable `Include count in collection queries`. This setting helps improve performance during data syncs. 3. Navigate to **Manage \> Extend** and enable: * `Gatsby` * `Gatsby JSON:API Extras` 4. Install [JSON:API Schema module](https://www.drupal.org/project/jsonapi_schema) . 5. To enable automatic syncing to Netlify, add your data layer webhook to the Gatsby Integration module. 1. Navigate to **Manage \> Configuration \> Web Services \> Gatsby Integration \> Gatsby Settings** . 2. Add the following webhook to the **Build Webhook URLs** field. Make sure to replace the placeholder with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 3. Under **Entity types to send to Gatsby Preview and Build Server**, select the types you wish to sync. At minimum, you should select the `Content` type. 4. Select **Save configuration** to finish. 6. Navigate to **Manage \> People \> Permissions** to add the following permissions for data syncing: 1. Add `Sync Gatsby Fastbuild log entities` permissions. If your Drupal instance does not use authentication, then select `Anonymous user`. Otherwise, select the appropriate Drupal role. 2. Add `View Gatsby log entity entities` permissions. If your Drupal instance does not use authentication, then select `Anonymous user`. Otherwise, select the appropriate Drupal role. ##### [#](#add-your-drupal-instance) Add your Drupal instance Once you have [prepared your Drupal instance](#prepare-your-drupal-instance) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `Drupal` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [Drupal extension details page](https://app.netlify.com/extensions/drupal-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Add a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `DrupalPost` with the prefix `Marketing` becomes `MarketingDrupalPost` in the schema. 5. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 6. Enter the **Site URL** for your Drupal site, including the trailing slash. 7. (Optional) Enter the **JSON API Path Prefix** to use as the relative path to the `JSON:API` root. The default is `jsonapi`. 8. (Optional) If your Drupal instance has [basic authentication](https://www.drupal.org/project/basic_auth) enabled, enter the **HTTP Basic Auth username** and **HTTP Basic Auth password**. 9. (Optional) Enter any **Disabled types** that you would like to exclude from the GraphQL API. 10. (Optional) Enter the number of **Concurrent API requests** a user can make to the Drupal API. The default is `20`. 11. (Optional) Enter a **Request timeout** value. This is the time in milliseconds before requests to Drupal will time out. The default is `30000`. 12. (Optional) Enter the **Default language** of your Drupal site. This will determine what language content to sync from Drupal. The default is to sync the English language content. 13. (Optional) Enter the **Enabled languages** for your Drupal site. This will allow you to sync different translations from Drupal, depending on what languages your site has enabled. 14. (Optional) Select **Filter by language** to filter the data you sync from Drupal based on the current language. 15. (Optional) Enter the **Translatable entities** to specify what entities to sync translations for. For example, `node--page, node--article`. 16. (Optional) Enter the **Non-translatable entities** from your Drupal site. These entities will use the default language of your site. For example, `taxonomy_term--tags, taxonomy_term--categories`. 17. (Optional) Enter the **Request Headers used for Drupal API** to apply specific headers for the API. 18. (Optional) Enter the **Filters used for Drupal API** to specify what content to sync. This will allow you to control the data you receive from Drupal. For example, `{"recipe": "filter[tags.name][value]=British"}`. 19. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#salesforce-commerce-cloud) Salesforce Commerce Cloud To use Salesforce Commerce Cloud (SFCC), complete the following steps: 1. [Set up an API Client in Account Manager](#set-up-an-api-client-in-account-manager) . 2. [Add your SFCC instance](#add-your-sfcc-instance) and API information to your data layer. ##### [#](#set-up-an-api-client-in-account-manager) Set up an API Client in Account Manager Netlify Connect utilizes the Salesforce Admin API to sync product data. To enable this, you need to set up an API Client with the correct scopes in Account Manager on Salesforce. Create an API Client in Account Manager by following the [instructions provided by Salesforce](https://developer.salesforce.com/docs/commerce/commerce-api/guide/authorization-for-admin-apis.html) . While you set up the API client, note the following: * Take note of the password you set for the API Client. This will be used as the **Client Secret** later. * The API Client will require the following scopes: `sfcc.products` and `sfcc.catalogs`. * When you finish creating the client, find it in the table of API clients and take note of the value in the **API Client ID** column of the table, as described in Salesforce’s instructions. For example, `1d763261-6522-4913-9d52-5d947d3b94c4`. ##### [#](#add-your-sfcc-instance) Add your SFCC instance Once you have [set up an API client](#set-up-an-api-client-in-account-manager) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `Salesforce Commerce Cloud` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [Salesforce Commerce Cloud extension details page](https://app.netlify.com/extensions/sfcc-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 5. Enter a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `SfccProduct` with the prefix `Marketing` becomes `MarketingSfccProduct` in the schema. 6. Enter the **Client ID** for the [API Client you created](#set-up-an-api-client-in-account-manager) in Account Manager. 7. Enter the password for the API Client as the **Client Secret**. 8. Enter the [**Organization ID**](https://developer.salesforce.com/docs/commerce/commerce-api/guide/base-url.html#organization-id) for your B2C Commerce instance. For example, `f_ecom_zzte_053`. 9. Enter the **Short Code** that is assigned to your realm. The [short code](https://developer.salesforce.com/docs/commerce/commerce-api/guide/base-url.html#short-code) applies to your entire realm, across all instances. For example, `kv7kzm78`. 10. Enter the [**Site ID**](https://developer.salesforce.com/docs/commerce/commerce-api/guide/base-url.html#site-id) for the site that you want to access data for (sometimes called a “channel”). For example, `RefArch` or `SiteGenesis`. 11. Enter a comma-separated list of **Locales** to sync data for. For example, `default, en-US, fr-FR, zh-CN, ja-JP, it-IT, en-GB`. 12. Enter the **Request Concurrency** to set the maximum number of concurrent requests to make to the B2C Commerce API. 13. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#shopify) Shopify To use Shopify with Connect, complete the following steps: 1. [Prepare your Shopify store](#prepare-your-shopify-store) . 2. [Add your Shopify store](#add-your-shopify-store) to your data layer. ##### [#](#prepare-your-shopify-store) Prepare your Shopify store To add a Shopify store to your data layer in Netlify Connect, first you need to set up a [custom Shopify app](https://help.shopify.com/en/manual/apps/app-types/custom-apps) that we can use to access Shopify’s Admin API and sync data. You will need the `Admin API access token` to set up your Shopify data source in Netlify Connect. 1. Log in to your Shopify store as the store owner and search for `Apps and sales channels`. 2. Enable [custom app development](https://help.shopify.com/en/manual/apps/app-types/custom-apps#enable-custom-app-development) . To do this, select **Develop apps**, then **Allow custom app development**. After reading the warning and information provided, select **Allow custom app development**. 3. [Create a custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps#create-the-app) . From the `App development` section, select **Create an app**. Enter an app name and developer, then select **Create app**. 4. [Set admin API scopes](https://help.shopify.com/en/manual/apps/app-types/custom-apps#update-admin-api-scopes-for-a-custom-app) for the app. On the custom app page, select **Configure Admin API scopes**. Enable the `read_products`, `read_product_listings`, and `read_files` scopes, and then select **Save**. You can use this data integration to proxy directly to the Shopify GraphQL API as well. To allow additional CRUD operations through the proxy, enable the admin API scopes for these operations, such as `write_products`. ![](/images/connect-add-data-layers-shopify-app-configure-admin-api-scopes.png) 5. [Install the app and get the API access token](https://help.shopify.com/en/manual/apps/app-types/custom-apps#install-the-app-and-get-the-api-access-tokens) . Select the **API credentials** tab and select **Install app** under **Access tokens**. Follow the prompts to install the app on your Shopify store. Next, under the **Admin API access token** section, select **Reveal token once** to access the token. Store the token in a safe place as you will need it to set up the data source connection. ![](/images/connect-add-data-layers-shopify-app-reveal-token.png) To enable automatic syncing to Netlify, you also need to add your data layer webhook to Shopify. This ensures that Shopify will notify Netlify when data updates. 1. In Shopify, navigate to **Settings \> Notifications** , and under **Webhooks**, select **Create webhook**. 2. Select each **Event** that should trigger a sync to Netlify. 3. Select `JSON` as the format. 4. Add the following webhook to the **URL** field. Make sure to replace the placeholder with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 5. Select **Add webhook** to finish. ##### [#](#add-your-shopify-store) Add your Shopify store Once you have [created a custom Shopify app](#prepare-your-shopify-store) , take the following steps in the Netlify UI to add your Shopify store to your data layer: 1. Select **Add a data source**. 2. Select `Shopify` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [Shopify extension details page](https://app.netlify.com/extensions/shopify-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Add a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `ShopifyProduct` with the prefix `Marketing` becomes `MarketingShopifyProduct` in the schema. 5. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 6. Enter the **Admin API access token**. This is the access token for the custom Shopify app you created in the [prepare your store step](#prepare-your-shopify-store) . The token starts with `shpat_`. 7. Enter the **Store Name** for your Shopify store. You can find store name in the Shopify URL. For example, `STORENAME.myshopify.com`. 8. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. #### [#](#wordpress) WordPress To use WordPress with Netlify Connect, complete the following steps: 1. [Prepare your WordPress instance](#prepare-your-wordpress-instance) . 2. [Add your WordPress instance](#add-your-wordpress-instance) to your data layer. ##### [#](#prepare-your-wordpress-instance) Prepare your WordPress instance Take the following steps on your WordPress instance before you add it to your data layer: 1. Install and activate the `Netlify Connect` WordPress plugin: 1. Download the [`Netlify Connect` WordPress plugin](/assets/netlify-connect-wp-plugin.zip) . 2. In your WordPress admin dashboard, navigate to **Plugins** and then select **Add New Plugin**. 3. Select **Upload Plugin** and follow the prompts to upload the `netlify-connect-wp-plugin.zip` file that you downloaded in step 1. 4. Select **Install now**. 2. In your WordPress admin dashboard, navigate to **Edit Profile \> Application Passwords** and [create an application password](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/#Getting-Credentials) . You’ll need to enter this as your **token** when you set up your WordPress data source in the Netlify UI, and Netlify will use this token to access your data. 3. To enable automatic syncing to Netlify, add your data layer [Webhook URL](https://docs.netlify.com/connect/sync-events/#trigger-a-sync-with-the-webhook) in your WordPress plugin settings for Connect: 1. In your WordPress admin dashboard, navigate to **Settings \> Netlify Connect** . 2. Add the following webhook to the **Data layer Webhook URL** field. Make sure to replace the placeholder `YOUR-DATA-LAYER-ID` with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 3. Select **Save Changes** to finish. ##### [#](#add-your-wordpress-instance) Add your WordPress instance Once you have [prepared your WordPress instance](#prepare-your-wordpress-instance) , take the following steps in the Netlify UI to add it to your data layer: 1. Select **Add a data source**. 2. Select `WordPress` as the **Data source type**. If you haven’t already installed the extension for this data source, follow the **install extension** prompt to open the [WordPress extension details page](https://app.netlify.com/extensions/wordpress-content) in a new tab. As a Team Owner, select **Install** to install and make the extension available to all data layers on your team. After you install the extension, close the tab and return to the **Add a data source** flow in Connect to continue with the next steps. 3. Enter a **Name** for this data source. 4. Add a **Type prefix** for this data source. The prefix must start with an uppercase letter and can only consist of alphanumeric characters and underscores. Connect will add the prefix to all data types synced from this data source in the GraphQL schema, which you will use when you query the GraphQL API. For example, `Post` with the prefix `Marketing` becomes `MarketingPost` in the schema. 5. Enter the **User** (the username for which you created the application password). 6. Enter the **Token** (the application password you created in WordPress). 7. Enter the full **API Host** URL for your WordPress instance (for example, `https://example.com` without a trailing slash). 8. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. ##### [#](#optional-configuration) Optional configuration If you need to customize your setup further, you can configure the following optional settings during the setup process: * **Instance ID** unique value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. * **Per page**: specify the number of nodes to fetch per page when syncing data from WordPress. The default is `100`. * **Request concurrency**: set the number of concurrent requests to make during node sourcing. You can lower this if your WordPress server experiences issues during data sourcing. The default is `15`. * **Types to exclude globally**: specify the slugs of post types, taxonomies, or other content types to exclude from sourcing, listed as comma-separated values. #### [#](#custom-data-source) Custom data source To use a custom data source, an integration must already exist for it If a data integration doesn’t already exist for your custom data source type, create one with the [Netlify SDK](https://developers.netlify.app/sdk/get-started/introduction/) . Once you publish your data integration, you can start using it in Netlify Connect. To use a custom data source with Netlify Connect, complete the following steps: 1. [Install the data integration](#install-the-data-integration) . 2. [Prepare your data source instance](#prepare-your-data-source-instance) . 3. [Add your custom data source](#add-your-custom-data-source) to your data layer. Support for private and partner data integrations For help with a custom data source, refer to the data integration’s details page in the Netlify UI and any external documentation the page links out to. You can find the details page by navigating to **Extensions** and searching for the integration by name. ##### [#](#install-the-data-integration) Install the data integration Before you can add a custom data source to your data layer, you must install the data integration for that type of source on your team. 1. As a Team Owner, navigate to the **Extensions** page for your team in the Netlify UI. 2. Find the data integration for the custom data source type that you wish to use and select it in the search results. 3. If it’s not already installed, on the details page, select **Install**. If you can’t find the data integration, speak with the integration developer to ensure they have followed all of the steps to [publish an extension](https://developers.netlify.app/sdk/publish/) . ##### [#](#prepare-your-data-source-instance) Prepare your data source instance To enable automatic syncing to Netlify, you need to manually add a webhook to your custom data source instance. The exact instructions vary for each system but you need to do the following: 1. Log in to your data source and navigate to the webhook settings. 2. Follow the prompts to create a new webhook and add the following to the URL field. Make sure to replace the placeholder with your [data layer ID](/connect/troubleshooting-tips/#find-your-data-layer-id) . https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/YOUR-DATA-LAYER-ID Note that you also have the ability to create a custom authenticated webhook and use that instead of the default webhook. Learn more about [managing webhooks](/connect/manage-data-layers/manage-webhooks/) . 3. If the options are available, select the data types and events that should trigger the webhook. We suggest including any create, edit, and delete events for all content types that you wish to store in your data layer. If you have the option to add a header to the webhook, add a `x-connect-data-source` header to the request with the [data integration’s slug](/connect/troubleshooting-tips/#find-the-slug-for-a-data-integration) as the header’s value. This ensures that the webhook only triggers a sync for this specific data source, instead of all data sources on your data layer. 4. Save and enable the webhook. You may need to complete other configuration steps on your data source instance. Please refer to the documentation provided by the integration developer. ##### [#](#add-your-custom-data-source) Add your custom data source Once you have [installed the data integration for your team](#install-the-data-integration) and [prepared your data source instance](#prepare-your-data-source-instance) , take the following steps in the Netlify UI to add the custom data source to your data layer: 1. If you are not already on the data layer settings page, on your team’s **Connect** page, select the data layer from the **Data layers** list, and then select **Data layer settings**. 2. On the data layer settings page, select **Data sources**. 3. Select **Add a data source**. 4. Select the data integration that you [installed](#install-the-data-integration) as the **Data source type**. 5. Enter a **Name** for this data source. 6. Add a **Type prefix** for this data source. The prefix must start with an uppercase letter, and can only consist of alphanumeric characters and underscores. The prefix will be added to all data types synced from this data source in the GraphQL schema and you will use it when you query the GraphQL API. For example, `Post` with the prefix `Marketing` becomes `MarketingPost` in the schema. 7. (Optional) Enter a unique **Instance ID** value to use for this data source. Netlify uses this value to support [cross-references](/connect/manage-data-layers/manage-cross-references/) and linking between data sources. 8. Fill in the remaining configuration fields with the values for your data source instance. For example, you may need to provide the API key for your CMS instance. 9. Select **Save** to add this data source. When you add a new data source, Netlify automatically connects to it and starts syncing data to your data layer. In the meantime, you can [add another source](#_2-connect-data-sources) or select **Continue** to move to the [next step](#_3-connect-sites) in the data layer configuration flow. If you want to add [cross-references](/connect/manage-data-layers/manage-cross-references/) between your data sources, you can configure them after you complete the data layer configuration flow. ### [#](#_3-connect-sites) 3. Connect sites The third step in the data layer configuration flow is to set up connections to sites on Netlify that should automatically build and deploy when data changes in this data layer. We recommend that you connect any sites that use static site generation (SSG) to ensure they always have access to the latest data. All other site types should skip this step. Learn more about [when to connect your site](/connect/manage-data-layers/manage-connected-sites/#when-to-connect-a-site) . For Netlify to automatically build and deploy your site when data changes, your site must be [linked to a Git repository](/git/repo-permissions-linking/#link-a-git-repository) to enable continuous deployment, and it must have [active builds](/configure-builds/stop-or-activate-builds/) . To connect a site to this data layer: 1. Select **Search by site name or domain** and start entering the name or domain of the site you want to connect. 2. When the site appears in the results list, select the site. The connected site will appear in the **Connected sites** list. Once you connect a site, the [build hooks](/configure-builds/build-hooks/) for the site will include a `Netlify Connect - Data layer` build hook with the data layer ID as the value. This provides a convenient way on the site level to check whether a site is connected to a data layer. ![](/images/connect-connect-sites-build-hooks.png) Repeat the above steps to connect as many sites as needed. Once you’re done, select **Continue** to move to the last step. ### [#](#_4-add-notifications) 4. Add notifications The final step in the flow allows you to add notifications to notify external services whenever data changes in your data layer. For example, you may want to add a notification to notify a Slack channel when your data layer updates. To add a notification: 1. Select **Add a notification**. 2. Enter a **Name** and **URL** for the notification. 3. Select **Create notification**. Repeat these steps to add as many notifications as needed. Once you’re done, select **Finish data layer configuration** to complete the set up process. [#](#what-next) What next? --------------------------- Once you finish the configuration flow for a new data layer, you can [review sync events](/connect/monitor-activity/) while Netlify completes the initial data sync from your data sources. After the sync events are successful, you need to [generate an API token](/connect/api-authentication/#manage-api-tokens) for the GraphQL API. Once you do that, you can [access the data](/connect/access-data/) with the GraphQL sandbox or through the GraphQL API in your app. If the sync events are not successful, review our [troubleshooting tips](/connect/troubleshooting-tips/#initial-sync-fails-after-configuring-a-data-source) for support. If you need to, you can now [pin a data revision](/connect/data-revisions/#pin-a-data-revision) so that your data layer’s API always uses that specific data revision. You can also [review and modify the data layer](/connect/manage-data-layers/overview/) to add or update configured data sources, sites, and webhooks. After you configure more than one data source on the data layer, you can add [cross-references](/connect/manage-data-layers/manage-cross-references/) to create links between fields across data sources and retrieve the combined data through a single query. You may also want to restrict access to certain data using [API scopes](/connect/api-authentication/#manage-api-scopes) and [generate new API tokens](/connect/api-authentication/#manage-api-tokens) to access that data. Last updated: November 26, 2024 ← [Overview](/connect/overview/) [Manage data layers](/connect/manage-data-layers/overview/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Sync events in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify Connect automatically syncs and updates your data layer to ensure that you always have access to the latest data. This document covers the [types of sync events](#sync-event-types) that occur, what triggers [automatic data syncs](#automated-syncs) , and how to [trigger a sync manually](#manual-syncs) in the Netlify UI or through webhooks. To learn how to access sync event logs and set up Slack notifications for failures, review [monitor activity](/connect/monitor-activity/) . [#](#sync-event-types) Sync event types ---------------------------------------- There are two types of events that can occur in Connect: * **Sync from all data sources:** the system reads data source configurations, installs dependencies, and then retrieves data from all data sources. Once the data is retrieved, the system uses the information to build or update the GraphQL schema for the data layer * **Sync from {data source type}:** the system retrieves data from the specified data source Netlify does a full sync to set up or update your data layer when you create a new data layer and when you add or update [data source configurations](/connect/manage-data-layers/manage-data-sources/) , [cross-references](/connect/manage-data-layers/manage-cross-references/) , and [API scopes](/connect/api-authentication/#manage-api-scopes) . Netlify also does a full sync when you [manually trigger a sync](#manual-syncs) . When a full sync occurs, the event is **Sync from all data sources**. When there is a data update, such as newly published content in your CMS, Netlify syncs the updated data source. If the [webhook notification](#trigger-a-sync-with-the-webhook) from the data source includes a header to specify that only that data source should update, the event is **Sync from {data source type}**. If not, the update will trigger a full sync and the event will be **Sync from all data sources**. Each successful sync generates a new data revision. You can review all available data revisions in the **Revisions** section on the data layer’s overview page. Learn more about [data revisions](/connect/data-revisions/) . [#](#automated-syncs) Automated syncs -------------------------------------- One of the benefits of Connect is that it automatically updates your data layers to ensure they always have access to the latest data. The API will use the pinned revision, even if syncs generate new ones If you pin a data revision, successful syncs will continue to generate new revisions but the GraphQL API for your data layer will always use the pinned one. Automated syncs occur in the following scenarios: * When you create a new data layer and when you add or update [data source configurations](/connect/manage-data-layers/manage-data-sources/) , [cross-references](/connect/manage-data-layers/manage-cross-references/) , and [API scopes](/connect/api-authentication/#manage-api-scopes) . This triggers a sync of all data sources and Netlify creates a new data revision and updates the GraphQL schema and API to reflect the change. * When data in a data source updates, such as when you publish new content in your CMS. Netlify is notified of the change and automatically creates a new data revision and updates your data layer. [#](#manual-syncs) Manual syncs -------------------------------- If you are troubleshooting and want to manually trigger a refresh of all data in your data layer, you can start a sync from all data sources through the Netlify UI or a webhook. Note that if your data layer’s API is using a pinned data revision, Netlify will generate a new revision to reflect the data sync but the API will continue to use the old data. Make sure to unpin the old data revision and/or pin the new revision once the data refresh is complete. ### [#](#trigger-a-sync-with-the-netlify-ui) Trigger a sync with the Netlify UI 1. Navigate to the **Connect** page for your team and select the data layer from the **Data layers** list. 2. In the **Activity** section, select **Trigger sync \> Sync from all data sources** . Netlify will start syncing the data. ![](/images/connect-monitor-events-manual-sync.png) ### [#](#trigger-a-sync-with-the-webhook) Trigger a sync with the webhook You can use webhooks in external systems to trigger a sync in Connect. Learn more about how to [create and use webhooks](/connect/manage-data-layers/manage-webhooks/) for your data layer. [#](#review-data-layer-sync-events) Review data layer sync events ------------------------------------------------------------------ Netlify retains sync event logs for five days. Review the [monitor activity](/connect/monitor-activity/) doc to learn how to access logs for data layer sync events and how to set up Slack notifications for sync event failures. Last updated: November 26, 2024 ← [Access data](/connect/access-data/) [Monitor activity](/connect/monitor-activity/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage data layers in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Once you [create and configure a data layer](/connect/get-started/) , you can review and modify the data layer on the settings page in the Netlify UI. Netlify records all activities related to creating, updating, and deleting data layers, data sources, and API authentication tokens in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . Want to create another data layer? To create a brand new data layer, navigate to the **Connect** page for your team and select **Add new data layer**. For more information on the flow to add and configure a new data layer, refer to our [get started with Netlify Connect](/connect/get-started/) doc. [#](#access-data-layer-settings) Access data layer settings ------------------------------------------------------------ To review or modify a [data layer](/connect/get-started/#definitions) and its related data sources, sites, or webhooks, navigate to the settings page for the data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. ![](/images/connect-select-data-layer.png) 3. Select **Data layer settings**. ![](/images/connect-manage-data-layers-data-layer-settings.png) [#](#update-data-layer-information) Update data layer information ------------------------------------------------------------------ Team Owners and Developers can update the name or description of a [data layer](/connect/get-started/#definitions) : 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **General \> Data layer information** . 4. Select **Edit settings**. 5. Enter the updated name or description. 6. Select **Save**. Team Owners also have the ability to [delete a data layer](#delete-a-data-layer) . [#](#update-configurations-on-your-data-layer) Update configurations on your data layer ---------------------------------------------------------------------------------------- On the data layer settings page, you can add and manage the following: * [Data sources](/connect/manage-data-layers/manage-data-sources/) * [Cross-references](/connect/manage-data-layers/manage-cross-references/) * [Connected sites](/connect/manage-data-layers/manage-connected-sites/) * [Notifications](/connect/manage-data-layers/manage-notifications/) * [Webhooks](/connect/manage-data-layers/manage-webhooks/) [#](#manage-api-authentication) Manage API authentication ---------------------------------------------------------- Use API tokens and scopes to ensure only authorized requests to your data layer’s API can access your data. Learn more about how to [manage API authentication](/connect/api-authentication/) . [#](#manage-data-revisions) Manage data revisions -------------------------------------------------- Every successful sync to your data layer generates a new data revision that represents the GraphQL schema and data at that point in time. You can query against the data revision using the revision’s GraphQL sandbox or its unique API URL. You can also pin a specific data revision and your data layer’s API will always use that revision. Learn more about [data revisions](/connect/data-revisions/) . Which data revision is the data layer’s GraphQL API using? At the top of the data layer’s overview page, you will find information about the [data revision](/connect/data-revisions/) that your data layer’s GraphQL API is currently using — including the data revision ID and whether or not the API is using a pinned revision. [#](#delete-a-data-layer) Delete a data layer ---------------------------------------------- When you delete a data layer, everything related to it is deleted — the GraphQL API and all data, data sources, site connections, and webhooks. Note that if you have submitted a support request related to the data layer, it will be difficult for us to help if you delete it. When you delete a data layer, the GraphQL API will be deleted also When you delete a data layer, the GraphQL API and all data revisions for that data layer will no longer be available. Remember to remove or adjust any code that uses the data layer’s GraphQL API to avoid any errors. As this action cannot be reversed, only Team Owners can delete a data layer. To delete a data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Danger zone**. 4. Select **Delete this data layer**. 5. A confirmation prompt will appear. Review the details and then enter the name of the data layer you want to delete. 6. Select **Delete**. [#](#troubleshooting) Troubleshooting -------------------------------------- Trying to find an ID or need help debugging an issue? Review our [troubleshooting tips](/connect/troubleshooting-tips) . [Manage data sources in Netlify Connect](/connect/manage-data-layers/manage-data-sources/) [Manage data sources in Netlify Connect: Add new data sources](/connect/manage-data-layers/manage-data-sources/#add-new-data-sources) [Manage data sources in Netlify Connect: Edit data sources](/connect/manage-data-layers/manage-data-sources/#edit-data-sources) [Manage data sources in Netlify Connect: Delete data sources](/connect/manage-data-layers/manage-data-sources/#delete-data-sources) [Manage connected sites in Netlify Connect](/connect/manage-data-layers/manage-connected-sites/) [Manage connected sites in Netlify Connect: Connect a site](/connect/manage-data-layers/manage-connected-sites/#connect-a-site) [Manage connected sites in Netlify Connect: Disconnect a site](/connect/manage-data-layers/manage-connected-sites/#disconnect-a-site) [Manage notifications in Netlify Connect](/connect/manage-data-layers/manage-notifications/) [Manage notifications in Netlify Connect: Add a notification](/connect/manage-data-layers/manage-notifications/#add-a-notification) [Manage notifications in Netlify Connect: Delete a notification](/connect/manage-data-layers/manage-notifications/#delete-a-notification) [API authentication in Netlify Connect: Generate an API token](/connect/api-authentication/#generate-an-api-token) [API authentication in Netlify Connect: Revoke an API token](/connect/api-authentication/#revoke-an-api-token) Last updated: November 26, 2024 ← [Get started with Netlify Connect](/connect/get-started/) [Manage data sources](/connect/manage-data-layers/manage-data-sources/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Netlify Connect usage and billing | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. You can check your Netlify Connect service usage at the top of the your team’s **Connect** page in the Netlify UI. This shows your current usage level and tracks the following metrics: * **Bandwidth:** total bandwidth used by your team’s data layers in Connect. This bandwidth factors into your [team’s overall bandwidth usage metric](/accounts-and-billing/billing/#bandwidth-usage) . * **Data layers:** the number of data layers configured on your team. * **Data sources:** the number of data sources configured across all data layers on your team. You can monitor which data layers use the most bandwidth under **Billing \> Bandwidth usage data** . Scroll down and select the caret next to **Top bandwidth usage per Netlify Connect data layer** for a list of [data layer IDs](/connect/troubleshooting-tips/#find-your-data-layer-id) and the bandwidth used by each data layer. Bandwidth usage data updates in near real-time and may require a browser refresh. ![](/images/accounts-and-billing-top-bandwidth-usage-connect-data-layer-dropdown-caret.png) Visit our [pricing page](https://www.netlify.com/pricing/?category=enterprise) to learn more about Connect pricing, including feature limits and add-ons. When your team’s usage reaches a feature limit, our [Sales team](https://www.netlify.com/contact/) will contact you to discuss next steps [#](#more-usage-and-billing-resources) More usage and billing resources ------------------------------------------------------------------------ * [Billing FAQ](/accounts-and-billing/billing-faq/) * [Billing](/accounts-and-billing/billing/) Last updated: May 29, 2024 ← [Troubleshooting tips](/connect/troubleshooting-tips/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Troubleshooting tips for Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. This document provides troubleshooting tips for Netlify Connect. ### [#](#find-your-data-layer-id) Find your data layer ID Need your data layer ID for a support conversation or for a manual set-up step for a data source? Once you add a data layer, you can find the ID in the URL for the data layer’s pages in the Netlify UI. The URL is formatted as `https://app.netlify.com/teams/YOUR-TEAM-NAME/connect/data-layers/YOUR-DATA-LAYER-ID/...` If you are in the initial flow to create and configure a new data layer, you can find the ID for the data layer in the URL starting from the [add data sources step](/connect/get-started/#_2-connect-data-sources) . If you have already created a data layer, the ID will appear in the URL as you navigate through the different Netlify UI pages for that data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. Find the data layer ID in the URL. ### [#](#find-your-data-layer-s-webhook-url) Find your data layer’s webhook URL Every data layer comes with a default **Webhook URL** that can be found in your **Data layer settings** under **General \> Data layer information** . It is formatted as `https://webhook.netlify-connect.com/hooks/data_layer/data_source/publish/{data_layer_id}`. However, we recommend generating a new authenticated webhook URL and using that instead. Learn more about how to [create and manage webhooks](/connect/manage-data-layers/manage-webhooks/) for your data layer. ### [#](#find-the-slug-for-a-data-integration) Find the slug for a data integration While setting up a webhook on a data source or troubleshooting an error, you may need to refer to the slug for the data integration you’re using. To find the slug: 1. Navigate to the **Extensions** page for your team. 2. Find the extension for the data integration and then select it. 3. Review the URL to find the slug, which is the last part of the URL. For example, if the URL for the Drupal data integration is `https://app.netlify.com/teams/your-team-name/extensions/cms/drupal-content`, the slug is `drupal-content`. ### [#](#data-integration-for-custom-data-source-doesn-t-show-up-as-an-option) Data integration for custom data source doesn’t show up as an option If you try to add a custom data source to your data layer and the data integration for that data source doesn’t appear as an option in the Netlify UI, confirm that you have installed the integration for your team. 1. In the Netlify UI, navigate to the **Extensions** page for your team. 2. Find the data integration for the custom data source you wish to use and select it. 3. If it’s not already installed, select **Install**. If you can’t find the data integration or the integration is already installed, work with the integration developer to ensure that it was [published correctly](https://developers.netlify.app/sdk/publish/) . If the above steps don’t seem to resolve this issue, [contact support](https://www.netlify.com/support/) . ### [#](#other-questions-about-custom-data-sources) Other questions about custom data sources For help with a custom data source, refer to the data integration’s details page in the Netlify UI and any external documentation the page links out to. You can find the details page by navigating to **Extensions** and searching for the integration by name. If you have questions, please contact the integration developer directly. ### [#](#initial-sync-fails-after-configuring-a-data-source) Initial sync fails after configuring a data source If you add a new data source and the initial sync isn’t successful, check the following: 1. Confirm that you completed the steps to prepare your data source instance for Connect, if applicable. To review the preparation steps, check our documentation on [how to add new data sources](/connect/manage-data-layers/manage-data-sources/#add-new-data-sources) and filter for the data source type to reveal the instructions. If there are additional steps to take, the instructions include a section with a title that begins with `Prepare`, such as `Prepare your Contentful instance`. 2. Confirm that the configuration details entered for your data source instance are correct. To review your settings: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Data sources**. 4. Select the data source you want to review. 5. If there are any errors, select **Edit**, update the fields as needed, and then select **Save**. 3. After you make any changes, [manually trigger a sync](/connect/sync-events/#manual-syncs) . If the above steps don’t seem to resolve this issue, [contact support](https://www.netlify.com/support/) . ### [#](#changes-in-data-source-don-t-trigger-a-sync) Changes in data source don’t trigger a sync Connect relies on your data source to send a notification whenever data changes. If a change does not trigger a sync in Connect, check the settings on your data source: 1. Confirm that a [webhook with your data layer’s webhook URL](#find-your-data-layer-s-webhook-url) exists. If a webhook doesn’t exist, you likely need to add one manually. This is often a prerequisite step for adding a data source to Connect, especially custom data sources. Review our documentation on how to [add and configure data sources](/connect/manage-data-layers/manage-data-sources/#add-new-data-sources) . 2. Confirm that the webhook is set to trigger on the data types and events you want to sync. For example, you may be missing a “product” type or a “delete” event. Refer to the documentation for your data source to learn more about configuring webhooks on their system. 3. Confirm that the webhook is enabled. If the above steps don’t seem to resolve this issue, [contact support](https://www.netlify.com/support/) . ### [#](#handle-large-contentful-or-wordpress-payloads) Handle large Contentful or WordPress payloads If you encounter errors syncing a Contentful data source due to the payload size, [edit the data source](/connect/manage-data-layers/manage-data-sources/#edit-data-sources) to lower the `Page limit` value from the default of `1000` so that data is retrieved in smaller batches. Similarly, if your WordPress data source has errors due to the payload size, [edit the data source](/connect/manage-data-layers/manage-data-sources/#edit-data-sources) to lower the `Per page` value from the default of `100` so that data is retrieved in smaller batches. ### [#](#responses-from-the-data-layer-api-are-slow) Responses from the data layer API are slow Responses to queries that are larger than 9 KB are not cached. If a large response is not cached, each subsequent query for the data will take a similar length of time to process. To get maximum performance from your data layer’s API, we recommend that you take advantage of pagination by using `skip` and `limit` filters in your queries. If that’s not possible, consider making multiple small queries that return smaller response bodies, which can be cached separately. Note that a data sync clears the edge cache entries for the modified data and that updates to more than 100 or so entries purge the cache for the entire data layer. As a result, initial queries following a data sync may take longer than usual. Learn more about [how we calculate query complexity](/connect/access-data/#query-complexity) . ### [#](#clear-database-cache-and-sync-again) Clear database cache and sync again If you are debugging an issue and want to clear out your data layer’s database and start fresh, you can use the clear cache option. 1. Navigate to the **Connect** page for your team and select the data layer from the **Data layers** list. 2. In the **Activity** section, select **Trigger sync \> Clear cache and sync from all data sources** . ![](/images/connect-troubleshooting-tips-clear-cache-and-sync.png) Netlify will clear the database cache and start syncing the data from all sources again to create a fresh database for your data layer. ### [#](#sync-event-is-complete-but-the-api-reflects-old-data) Sync event is complete but the API reflects old data If the **Activity** section reflects a successful data sync but the data layer API still reflects old data, make sure your API isn’t using a pinned data revision. If a data revision is pinned, successful syncs will continue to generate new data revisions but the API will always use the pinned version. 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list. 3. Check the data layer overview to confirm whether or not the API is using a `pinned` revision. ![](/images/connect-troubleshooting-check-pinned-data-revision.png) If a specific data revision is pinned and you want to check the data in a revision before unpinning or updating the pin, you can [query the data for that specific revision](/connect/data-revisions/#access-data-revisions) . ### [#](#trigger-builds-automatically-for-a-specific-branch) Trigger builds automatically for a specific branch When data changes in your data layer, Netlify automatically builds and deploys the [production branch](/site-deploys/overview/#definitions) of all connected sites. Currently, it’s not possible to specify a different branch when you connect a site. If you would like to trigger builds for a different branch, you can follow this workaround to create a Netlify [build hook](/configure-builds/build-hooks/) and add it as a [notification](/connect/manage-data-layers/manage-notifications/) to your data layer. 1. First, create a build hook for your site. Navigate to **Site configuration \> Build & deploy \> Continuous deployment \> Build hooks** . 2. Select **Add build hook**. 3. Enter a **Build hook name** and select the **Branch to build**, then select **Save**. 4. Find the new build hook in the list and copy the webhook URL. 5. Now, create a notification for your data layer. Navigate to the **Connect** page for your team. 6. Select the data layer from the **Data Layers** list, and then select **Data layer settings**. 7. On the data layer settings page, select **Notifications**. 8. Select **Add a notification**. 9. Enter a **Name** for this notification. 10. Paste the copied build hook into the **URL** field. 11. Select **Create notification** to add the notification to your data layer. Now, whenever your data layer updates, Netlify automatically triggers the notification. The notification then triggers the build hook to start a new build and deploy for the specified branch. ### [#](#api-query-does-not-return-the-expected-types-and-fields) API query does not return the expected types and fields If you make a query to your data layer’s API and not all of the data you expect is returned, make sure your API token has the correct scopes for that data. 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **API access control**. 4. In the **API scopes** section, find the scope for the data required. 5. Select the scope to expand the details and review the list of tokens, fields, and types that the scope applies to. ![](/images/connect-troubleshooting-query-scopes.png) 6. If your token is not on the list, use one of the tokens listed instead. Or [generate a new token with that scope](/connect/api-authentication/#generate-an-api-token) . ### [#](#get-help-with-connect-client) Get help with Connect client If you use the [Connect client](/connect/access-data/#use-the-connect-client) to query your data layer’s GraphQL API, refer to the [`connect-client` readme](https://www.npmjs.com/package/@netlify/connect-client#troubleshooting) for troubleshooting tips and support. Last updated: November 26, 2024 ← [Monitor activity](/connect/monitor-activity/) [Usage & billing](/connect/usage-and-billing/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Configure external DNS for a custom domain | Netlify Docs If you’ve assigned an externally registered domain to your site, and you don’t want to use [Netlify DNS](/domains-https/netlify-dns/) , you need to configure your external DNS provider to point your domain to Netlify. To access customized details about the DNS records you need to configure, go to **Domain management \> Production domains** and select **Awaiting External DNS** next to the custom domain. ![The link is between the domain name and the options menu.](/images/domains-https-check-dns-configuration.png) The next steps vary depending on the type of domain or subdomain. * For a [subdomain](/domains-https/custom-domains/#definitions) of a domain you own, such as `blog.petsofnetlify.com` or `www.petsofnetlify.com`, follow the directions below for [subdomain configuration](/domains-https/custom-domains/configure-external-dns/#configure-a-subdomain) . * For an [apex domain](/domains-https/custom-domains/#definitions) with no subdomain, such as `petsofnetlify.com`, make sure to read our [advice about using apex domains](/domains-https/custom-domains/multiple-domains/#apex-domains-and-www-subdomains) , then follow the directions below for [apex domain configuration](/domains-https/custom-domains/configure-external-dns/#configure-an-apex-domain) . Special handling for apex and `www` If you assign an apex domain or a `www` subdomain to your site, Netlify will automatically add _both_ the apex domain and the `www` subdomain. This means you should follow directions for both [configuring a subdomain](#configure-a-subdomain) and [configuring an apex domain](#configure-an-apex-domain) . For more information, visit the section on [apex domains and `www` subdomains](/domains-https/custom-domains/multiple-domains/#apex-domains-and-www-subdomains) . Need to delegate just a subdomain? You can delegate a subdomain to Netlify DNS without the apex domain. Learn more in this [doc](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . [#](#configure-a-subdomain) Configure a subdomain -------------------------------------------------- To point a subdomain such as `blog.petsofnetlify.com` or `www.petsofnetlify.com` to your site on Netlify, you must first [add the domain to your site](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) on Netlify and then create a CNAME record with your DNS provider. For example, if your site’s domain is `blog.petsofnetlify.com` and your [Netlify subdomain](/domains-https/custom-domains/#definitions) is `brave-curie-12345.netlify.app`: 1. Follow the instructions to [add the domain](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) `blog.petsofnetlify.com` to the `brave-curie-12345.netlify.app` site on Netlify. At the end of the process, Netlify provides a CNAME record to add to your DNS provider. 2. Find your DNS provider’s DNS record settings for your apex domain, `petsofnetlify.com`. 3. On your DNS provider’s site, add the CNAME record with your subdomain, `blog`, as the host. 4. Point the record to your Netlify subdomain, `brave-curie-12345.netlify.app`. High-Performance Edge uses a different subdomain If your site is on the High-Performance Edge, point the record to the dedicated subdomain in your High-Performance Edge onboarding PDF. 5. Save your settings. It may take a full day for the settings to propagate across the global Domain Name System. If your site uses the `www` subdomain, as in `www.petsofnetlify.com`, you will use the same procedure described above. Once you configure the `www` subdomain, an apex domain will also be added automatically to your site. You’ll need to follow the steps in the section below to configure the apex domain too. Learn more about our [special handling for `www` subdomains](/domains-https/custom-domains/multiple-domains/#apex-domains-and-www-subdomains) . [#](#configure-an-apex-domain) Configure an apex domain -------------------------------------------------------- Unlike subdomains, apex domains don’t support CNAME records. You must configure your apex domain with an ALIAS, ANAME, flattened CNAME, or A record. Different DNS providers support different record types. Depending on what your DNS provider supports, use either the recommended configuration or the fallback option below. If your [DNS provider supports ALIAS, ANAME, or flattened CNAME records](https://answers.netlify.com/t/support-guide-which-are-some-good-dns-providers-for-alias-aname-support/211) , use this recommended configuration, which is more resilient than the fallback option. 1. Find your DNS provider’s DNS record settings for your apex domain, such as `petsofnetlify.com`. 2. Add an **ALIAS**, **ANAME**, or **flattened CNAME record**. Depending on your provider, leave the host field empty or enter `@`. 3. Point the record to Netlify’s load balancer at: `apex-loadbalancer.netlify.com`. High-Performance Edge uses a different load balancer If your site is on the High-Performance Edge, point the record to the High-Performance Edge load balancer noted in the [**Awaiting External DNS** modal’s customized details](/domains-https/custom-domains/configure-external-dns/#check-dns-configuration) . 4. Save your settings. It may take a full day for the settings to propagate across the global Domain Name System. If your DNS provider does not support ALIAS, ANAME, or flattened CNAME records, use this fallback option. 1. Find your DNS provider’s DNS record settings for your apex domain, such as `petsofnetlify.com`. 2. Add an **A record**. Depending on your provider, leave the host field empty or enter `@`. 3. Point the record to Netlify’s load balancer IP address: `75.2.60.5`. High-Performance Edge uses a different load balancer If your site is on the High-Performance Edge, point the record to the High-Performance Edge load balancer IP address noted in the [**Awaiting External DNS** modal’s customized details](/domains-https/custom-domains/configure-external-dns/#check-dns-configuration) . 4. Save your settings. It may take a full day for the settings to propagate across the global Domain Name System. In both cases, the apex domain eventually resolves to our load balancer IP address. This means the apex domain can’t take advantage of direct DNS routing on a [global CDN like Netlify’s](https://www.netlify.com/products/edge/) . Because of this, we recommend using a subdomain for your [primary domain](/domains-https/custom-domains/multiple-domains/#domain-aliases) when using external DNS. Special handling for apex domains If you assign an apex domain to your site, Netlify will automatically add a `www` subdomain for the domain as well, which requires the [subdomain configuration](#configure-a-subdomain) as described above. To find out how this affects your site configuration, visit the section on [apex domains and `www` subdomains](/domains-https/custom-domains/multiple-domains/#apex-domains-and-www-subdomains) . [#](#dns-record-propagation) DNS record propagation ---------------------------------------------------- Depending on your DNS provider, **changes to DNS records can take several hours to propagate and take effect for the entire internet.** If more than 24 hours have passed since you configured your DNS records, and your site is still not accessible at your custom domain, try our [DNS troubleshooting tips](/domains-https/troubleshooting-tips/#dns-configuration) . Last updated: July 19, 2024 ← [Custom domains](/domains-https/custom-domains/) [Automatic deploy subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Delegate a stand-alone subdomain to Netlify DNS | Netlify Docs You can bring just a subdomain to Netlify DNS and keep your apex domain on a separate domain registrar. This makes all the benefits of Netlify DNS available to your subdomain, including automated wildcard SSL certificates and expanded use cases for your site with branch subdomains. For example, you can delegate `docs.example.com` to Netlify DNS and keep `example.com` on a different [domain registrar](/domains-https/custom-domains/#definitions) . If you delegate the stand-alone subdomain `docs.example.com` to Netlify DNS, your site gains these advantages: * **Automatic site security benefits.** Netlify DNS provisions your subdomain, and all subdomains of your subdomain, with [wildcard SSL certificates](/domains-https/https-ssl/) . * **More use cases with branch subdomains.** Your site can serve different content from different branches using [branch subdomains](/domains-https/custom-domains/multiple-domains/#branch-subdomains) . For example, the `staging` branch of your site can serve unique content at `staging.docs.example.com`. Likewise, your site’s `beta` branch can serve unique content at `beta.docs.example.com`. * **Wider reach with IPv6 support.** Your subdomain can reach a wider audience with [IPv6](/domains-https/netlify-dns/#ipv6-traffic) , which you can enable for your subdomain in the Netlify UI. * **Performance gains with the Netlify CDN.** Your site will be served from our global CDN, from the server closest to your site visitors. Between this and CDN-level routing, sites will often gain a performance boost from being served on the Netlify CDN. [#](#netlify-dns-support-for-subdomains-and-apex-domains) Netlify DNS support for subdomains and apex domains -------------------------------------------------------------------------------------------------------------- When you add an [apex domain](/domains-https/custom-domains/#definitions) to Netlify DNS, subdomains of this apex domain are managed by Netlify DNS automatically. If you delegate a stand-alone subdomain to Netlify DNS, additional configuration is required outside of Netlify. You will need to access the domain registrar for the related apex domain to set NS records ([Name Server records](/domains-https/netlify-dns/dns-records/#supported-record-types) ) for your subdomain. For example, if you’ve already added the apex domain `petsofnetlify.com` to Netlify DNS and you add the subdomain `rover.petsofnetlify.com` to your site on Netlify, then Netlify DNS will automatically manage this subdomain for you. Alternatively, if you have an apex domain that is already managed by an external domain registrar, such as `example.com`, and you want to bring just the subdomain `docs.example.com` to Netlify DNS, then you need to follow the steps below. [#](#delegate-a-stand-alone-subdomain-to-netlify-dns) Delegate a stand-alone subdomain to Netlify DNS ------------------------------------------------------------------------------------------------------ There are two main starting places in the Netlify UI to delegate just a subdomain to Netlify DNS: * **From your team’s Domains page:** If you have access to your team’s **Domains** page, then you can delegate a subdomain to Netlify DNS for your team and use this subdomain for one of your team’s sites. This flow allows you to wait for DNS propagation to complete before adding this subdomain to your site. * **From your site configuration:** If you only have access to a single site or want to add a subdomain directly to a site before the domain is live and then delegate it to Netlify DNS, then you can manage this through your site’s **Domain management** configuration. Avoid `www` as a stand-alone subdomain We recommend that you do not delegate `www` as a stand-alone subdomain. Netlify treats `www` subdomains and apex domains as alternates for each other. Attempts to delegate `www` as a stand-alone subdomain may lead to inconsistent behavior if one site is using the `www` subdomain while another uses the apex domain. ### [#](#delegate-a-subdomain-to-netlify-dns-for-your-team) Delegate a subdomain to Netlify DNS for your team When you delegate a subdomain to Netlify DNS through your team’s **Domains** page, this domain is available to any of your team’s sites. 1. If you haven’t already, check the [domain registrar](/domains-https/custom-domains/#definitions) that manages your apex domain to make sure it supports NS records for subdomains. You will need to access this domain registrar to update the NS records for your subdomain later in these steps. 2. In the Netlify UI, navigate to your team’s **Domains** page. 3. Select **Add or register a domain**. 4. Enter your subdomain, such as `docs.example.com`, and follow the UI prompts to delegate this subdomain to Netlify DNS. 5. To complete your subdomain delegation setup, copy the NS records for your subdomain from the Netlify UI. Log in to the domain registrar that manages the related apex domain, such as `example.com`, and enter NS records for your subdomain. DNS updates can take up to 24 hours to take effect. On occasion, record changes can take longer than this to propagate. Learn more in our [Support Guide on DNS propagation](https://answers.netlify.com/t/support-guide-why-do-dns-ssl-changes-take-up-to-48-hours-to-propagate-ttl/9359) . 6. Once you are ready to add your subdomain to a specific site, navigate to your team’s **Sites** page in the Netlify UI and select your site in the list. 7. Go to **Domain management** . 8. Select **Add a domain** and enter the stand-alone subdomain, such as `docs.example.com`, that you already delegated to Netlify DNS in the last steps. 9. Select **Verify**, then **Add subdomain**. Now the subdomain that you delegated to Netlify DNS is connected to your site. ### [#](#delegate-a-subdomain-to-netlify-dns-through-site-configuration) Delegate a subdomain to Netlify DNS through site configuration When you delegate a subdomain to Netlify DNS through your site configuration, we recommend you add your stand-alone subdomain and then delegate this domain to Netlify DNS. 1. Check the [domain registrar](/domains-https/custom-domains/#definitions) that manages your apex domain to make sure it supports NS records for subdomains. You will need to access this domain registrar to update the NS records for your subdomain later in these steps. 2. Navigate to your site and go to **Domain management** . 3. Select **Add custom domain**. 4. Enter your stand-alone subdomain, such as `docs.example.com`. This flow assumes that your subdomain stems from an apex domain, such as `example.com`, that is already registered through an external domain registrar. 5. Select **Verify**, then **Add subdomain**. Now this subdomain is connected to your site but is not yet delegated to Netlify DNS. 6. To delegate your subdomain to Netlify DNS, next to your subdomain, use the **Options** menu to select **Set up Netlify DNS**. ![](/images/domains-https-menu-to-delegate-to-netlify-dns-from-site-settings.png) 7. Follow the UI prompts to delegate your subdomain to Netlify DNS. During this UI flow, you may be asked to select **Verify** and **Add subdomain** again. 8. To complete your subdomain delegation setup, copy the NS records for your subdomain from the Netlify UI. Log in to the domain registrar that manages the related apex domain, such as `example.com`, and enter NS records for your subdomain. These DNS updates can take up to 48 hours to take effect. Learn more in our [Support Guide on DNS propagation](https://answers.netlify.com/t/support-guide-why-do-dns-ssl-changes-take-up-to-48-hours-to-propagate-ttl/9359) . Last updated: July 19, 2024 ← [Delegate to Netlify](/domains-https/netlify-dns/delegate-to-netlify/) [DNS records](/domains-https/netlify-dns/dns-records/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Custom domains | Netlify Docs A domain name is the URL or web address where visitors find your site. By default, any site on Netlify is accessible from its Netlify subdomain, which has the form `[name-of-your-site].netlify.app`. For example, you would access a site named `brave-curie-12345` at `https://brave-curie-12345.netlify.app/`. Custom domains allow you to make your sites accessible at your own domain names, such as `www.yourcustomdomain.com` or `docs.example.dev`. All top-level domains are supported for your custom domain. Netlify supports custom domains for your production site, Deploy Previews, and branch deploys. * For your production site, Netlify supports a primary site domain, [domain aliases](/domains-https/custom-domains/multiple-domains/#domain-aliases) , and [domain-based redirects](/domains-https/custom-domains/multiple-domains/#domain-redirects) . * For Deploy Previews, you can customize your domain after the Deploy Preview prefix `deploy-preview-#` with an [automatic deploy subdomain](/domains-https/custom-domains/automatic-deploy-subdomains) . For example: `deploy-preview-123.company.com`. * For branch deploys, you can customize your domain after your branch name with [automatic deploy subdomains or branch subdomains](/domains-https/custom-domains/multiple-domains/#manage-domains-for-deploy-previews-and-branch-deploys) . For example: `branch-name.company.com` For more example custom domains, check out [this chart](/domains-https/custom-domains/#custom-domain-examples) . [#](#definitions) Definitions ------------------------------ * **Domain name** (or **domain** for short)**:** full name used to access a site. For example, `yoursitename.netlify.app` or `www.yourcustomdomain.com` * **Top-level domain:** last part of the domain name. For example, the `.com` part in `www.yourcustomdomain.com`. * **Apex domain** (also known as a root, bare, or naked domain)**:** the `yourcustomdomain.com` part in `www.yourcustomdomain.com`. * **Subdomain:** domain that is part of a larger domain; the only domain that is not also a subdomain is the apex domain. For example, `www.yourcustomdomain.com` and `app.yourcustomdomain.com` are subdomains of `yourcustomdomain.com`. * **Netlify subdomain:** Netlify term for the default domain with the form `[name-of-your-site].netlify.app` given to each site. * **Custom domain:** domain you assign to a site. * **Primary domain:** Netlify term for the main custom domain assigned to a production site. * **Domain alias:** an additional custom domain assigned to a production site. * **Automatic deploy subdomain:** a subdomain that you can customize for all Deploy Previews and/or for all branch deploys. Can use your production site’s primary domain or a different custom domain with additional subdomains. Requires Netlify DNS. * **Branch subdomain:** a subdomain for a branch deploy that applies your production site’s primary domain to specified branch deploys. Can apply to an individual branch deploy or to all branches besides your production branch. Requires Netlify DNS. * **Domain registrar** (or domain registration service)**:** company that lets you register a domain name. * **DNS provider:** company that maintains the DNS servers that translate a domain name to a destination. * **Netlify DNS:** Netlify’s managed DNS service. * **Name server** (or DNS server)**:** specialized server that translates domain names into IP addresses. * **DNS zone:** used to provide information about one or more domain names. Each zone contains a list of DNS records with mappings between domain names and IP addresses. [#](#example-domains-for-your-site-deploys) Example domains for your site deploys ---------------------------------------------------------------------------------- Your site deploys can have different domain patterns based on the type of site deploy. ### [#](#custom-domain-examples) Custom domain examples | Site deploy type | Custom domain | Use case | | --- | --- | --- | | [Production deploy](/site-deploys/overview/#definitions) | `company.com` | Can set a primary domain for your production site. | | [Deploy Preview](/site-deploys/overview/#definitions) | `deploy-preview-42.early-access.company.com` | Can set a custom domain for Deploy Previews with an automatic deploy subdomain. | | [Branch deploy](/site-deploys/overview/#definitions)
for a branch named `staging` | Branch subdomain: `staging.company.com`

Automatic deploy subdomain: `staging.early-access.company.com` or `staging.internal-events.com` | Can set a custom domain for your branch deploys with an [automatic deploy subdomain or branch subdomains](/domains-https/custom-domains/multiple-domains/#manage-domains-for-deploy-previews-and-branch-deploys)
. | ### [#](#netlify-subdomain-examples) Netlify subdomain examples By default, your site deploys are available at a URL using the Netlify subdomain `yoursitename.netlify.app`. The Netlify subdomain URLs will always work even if you set up a custom domain for your site. | Site deploy type | Netlify subdomain | Use case | | --- | --- | --- | | [Production deploy](/site-deploys/overview/#definitions) | `yoursitename.netlify.app` | Typically a placeholder URL, ideal for internal development before assigning a custom domain for site visitors. | | [Deploy Preview](/site-deploys/overview/#definitions) | `deploy-preview-42--yoursitename.netlify.app` | Unique URL for previewing and collaborating on each pull/merge request. | | [Branch deploy](/site-deploys/overview/#definitions)
for a branch named `staging` | `staging--yoursitename.netlify.app`

Note: With a [branch subdomain](/domains-https/custom-domains/multiple-domains/#branch-subdomains)
set up, the URL can be `staging.yourcustomdomain.com`. | Long-standing URL ideal for internal testing, QA teams, and ongoing development. To set up branch deploys, check out [branch deploy controls](/site-deploys/overview/#branch-deploy-controls)
. | | Atomic deploy | `1234abcd12acde000111cdef--yoursitename.netlify.app` | Unique URL for a specific successful deploy. Also called [deploy permalinks](/site-deploys/overview/#definitions)
or just permalinks. Unlike the other site deploys, the web content at this URL never changes. A new deploy permalink is generated for each successful deploy of your site. | [#](#assign-a-domain-to-a-production-site) Assign a domain to a production site -------------------------------------------------------------------------------- To assign a custom domain or [domain alias](/domains-https/custom-domains/multiple-domains/#domain-aliases) to a production site, go to **Domain management \> Production domains** . Tip You can change a site’s default Netlify subdomain by selecting the **Options** button next to the subdomain in the **Production domains** panel, then selecting **Edit site name** in the menu. To add a custom domain, select **Add a domain** at the bottom of the **Production domains** panel, and then choose if you want to buy a new domain or use a domain you already own. Note: only [Team Owners or Organization Owners](/accounts-and-billing/team-management/roles-and-permissions/#owner) are able to buy new domains. **If you choose to buy a new domain**, you’ll be able to search and compare prices for available domains by keyword. Once you’ve found an unregistered domain you want to purchase, click "Buy" to register the domain on Netlify. Your domain will be automatically configured using [Netlify DNS](/domains-https/netlify-dns/) . No further configuration is necessary, but you may want to learn more about your new domain: * Visit the [domain registration](/domains-https/netlify-dns/domain-registration/) page for details about Netlify-registered domains. * Under [Netlify DNS](/domains-https/netlify-dns/) , learn how to enable [IPv6](/domains-https/netlify-dns/#ipv6-traffic) , and add [DNS records](/domains-https/netlify-dns/dns-records/) . * Find out about options for domain aliases, domain-level redirects, and branch subdomains in the page regarding [multiple domains](/domains-https/custom-domains/multiple-domains/) . **If you choose to add a domain you already own**, you will be asked to confirm that you’re the owner of the domain. If you _are_ the owner, select **Yes, add domain** to assign the custom domain to the site. The next step depends on how your domain is registered: * If the domain was [registered with Netlify](/domains-https/netlify-dns/domain-registration/) , is using [Netlify DNS](/domains-https/netlify-dns/) , or both, configuration is automatic. Visit the [multiple domains](/domains-https/custom-domains/multiple-domains/) page to learn about options for domain aliases, domain-level redirects, and branch subdomains. * If the domain was registered elsewhere, you can choose to use [Netlify DNS](/domains-https/netlify-dns/) for automatic configuration, branch subdomains, and automatic HTTPS on all subdomains with wildcard certificates. To get started, visit the doc about [adding a domain to Netlify DNS](/domains-https/netlify-dns/#add-a-domain) . * Alternatively, if the domain was registered elsewhere, and you want to continue using your current DNS provider, you will need to add DNS records on your provider to point your domain or subdomain to your site on Netlify. Visit the [external DNS](/domains-https/custom-domains/configure-external-dns/) instructions to complete your configuration. [#](#more-resources) More resources ------------------------------------ Visit our Forums for a list of verified Support Guides that highlight [best practices for using and configuring Netlify DNS and custom domains](https://answers.netlify.com/t/support-guide-compiled-resources-for-custom-domains-on-netlify-and-dns-settings-start-here/48222) . Last updated: February 4, 2025 [Configure external DNS](/domains-https/custom-domains/configure-external-dns/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Domain registration | Netlify Docs Netlify sites can be assigned to domains registered anywhere. For your convenience, Netlify also provides domain registration service directly in the Netlify UI. All Netlify domain registrations are private, with Netlify listed as the WHOIS contact. Netlify-registered domains are automatically configured to use [Netlify DNS](/domains-https/netlify-dns/) . For more information on valid domain extensions for Netlify-registered domains, refer to this [top level domains list](https://www.name.com/domains) . Certain domain extensions may not be available through our registration service. Need to delegate just a subdomain? You can delegate a subdomain to Netlify DNS without the apex domain. Learn more in this [doc](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . [#](#register-a-new-domain) Register a new domain -------------------------------------------------- Team and Organization [Owners](/accounts-and-billing/team-management/roles-and-permissions/#owner) can register a new domain on Netlify: 1. Go to your team’s **Domains** page and select **Add or register domain**. 2. Enter the domain you wish to register and select **Verify**. 3. If the domain already has an owner, choose a new domain and repeat step 2. 4. If the domain is available, you are presented with the price to register for one year. We’ll use the [payment method](/accounts-and-billing/billing/#change-billing-information) on file for the team, or you can add or update a payment method. 5. To authorize payment and register your new domain, select **Register domain now**. This will register the domain name, create a [Netlify DNS zone](/domains-https/netlify-dns/) for the domain, and provision a [wildcard certificate for HTTPS](/domains-https/https-ssl/#netlify-managed-certificates) , all in one click! To add a domain name that uses Unicode (or non-ASCII) characters such as ñ or é, use Punycode format. First, convert your domain name to Punycode using a Punycode converter, such as [Punycoder](https://www.punycoder.com/) . Then, use the converted output for the domain name as you follow the **Add or register domain** prompts. Next steps Once you have registered your domain on Netlify, you can use it with your Netlify sites and with other services. * To learn how to use your new domain to access a site on Netlify, visit the instructions for [assigning a custom domain to your site](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) . * If you need to add other DNS records, such as for an email service, visit the [DNS records](/domains-https/netlify-dns/dns-records/) doc. [#](#domain-renewal-and-expiration) Domain renewal and expiration ------------------------------------------------------------------ Domain registrations are valid for one year. To ensure continuous service, Netlify-registered domains automatically renew by default using the [payment method](/accounts-and-billing/billing/#change-billing-information) on file for the team. You can turn off auto-renewal in the domain detail page of the Netlify UI. Near the end of the registration period, Netlify will send you an email informing you of the cost for renewal, as well as whether your domain is set to renew automatically or not. If you have **disabled auto-renewal** on a domain, and the registration expires, all DNS records for the domain will stop working. You have the option to get the domain back, subject to the following timeline: * For the first 30 days after expiration, you can request assistance with domain renewal by contacting [support@netlify.com](mailto:support@netlify.com) from an email address associated with the Netlify team that paid for the domain. * For the next 30 days, days 31-60 after expiration, you can neither renew nor purchase the domain. * When 60 days have passed after expiration, the domain becomes available for sale to the public. You can then purchase it again as a new domain. [#](#transfer-registration) Transfer registration -------------------------------------------------- We cannot accept inbound domain transfer requests from other registrars. However, if you have a domain registered elsewhere, you can still take advantage of Netlify DNS by [delegating your domain to Netlify](/domains-https/netlify-dns/delegate-to-netlify/) . You can also transfer domain registrations and DNS zones between your teams on Netlify. Visit the [domain transfer](/domains-https/netlify-dns/#transfer-domains-between-teams) instructions for details. If you would like to transfer a Netlify-registered domain to another registrar, please [contact support](https://www.netlify.com/support) for assistance. Note that [ICANN regulations](https://www.icann.org/resources/pages/text-2012-02-25-en) do not permit transfers within 60 days of registration. Last updated: June 3, 2024 ← [Netlify DNS](/domains-https/netlify-dns/) [Delegate to Netlify](/domains-https/netlify-dns/delegate-to-netlify/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Dedicated secondary DNS | Netlify Docs This feature is deprecated Dedicated secondary DNS is [deprecated](/platform/release-phases/#deprecated) because the resiliency and reliability of [Netlify DNS](/domains-https/netlify-dns/) have surpassed the benefits provided by secondary DNS. As such, this feature is no longer available to new customers. Netlify’s dedicated DNS network is separately provisioned from our main DNS network, providing a DNS redundancy option. For teams using our dedicated DNS network, all DNS traffic for managed domains is distributed across both DNS networks. In the event of a volumetric attack such as a Distributed Denial of Service (DDoS), the secondary network provides a physically and logically separate failover for domain name resolution. Last updated: July 11, 2023 ← [DNS records](/domains-https/netlify-dns/dns-records/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Delegate your domain to Netlify | Netlify Docs If your domain is registered with another provider, you can still take advantage of Netlify’s managed DNS service by delegating your domain to Netlify. Need to delegate just a subdomain? You can delegate a subdomain to Netlify DNS without the apex domain. Learn more in this [doc](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . Transfer your DNS records first! If you have any existing records on your current DNS provider, such as MX records for email service, make sure to copy them to Netlify DNS first. This will ensure continuous service as you change providers. Visit the [DNS records](/domains-https/netlify-dns/dns-records/) page or the verified Support Guide in our Forums on [migrating a domain to Netlify-managed DNS](https://answers.netlify.com/t/support-guide-how-do-i-migrate-a-domain-to-netlify-managed-dns-with-zero-downtime/3397) for details. Assuming you have copied existing DNS records from your current provider, the final step to making your DNS records live is to update your domain registrar with the name servers that will be authoritative for your domain. The process for changing your domain’s name servers varies from registrar to registrar. Check your domain registrar’s documentation for updating name servers. For your convenience, we’ve gathered links to instructions for popular registrars [GoDaddy](https://www.godaddy.com/help/change-nameservers-for-my-domains-664) , [Google Domains](https://support.google.com/domains/answer/3290309) , [AWS](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register-other-dns-service.html) , [Name.com](https://www.name.com/support/articles/205934547-changing-nameservers-for-dns-management) , and [Hover](https://help.hover.com/hc/en-us/articles/217282477-How-to-Change-your-domain-name-servers-DNS-servers) . To delegate your domain to Netlify: 1. In the Netlify UI, go to your team’s **Domains** page. 2. Select your domain. 3. Make note of the four name servers listed in the **Name servers** panel. 4. Log in to the account you have with your domain registrar and find their instructions for updating name servers. 5. Replace the name servers with the name servers for your Netlify DNS zone. If your registrar requires name server IP addresses, visit our Forums for a verified Support Guide on [finding the IP addresses for Netlify’s name servers](https://answers.netlify.com/t/common-issue-finding-the-ip-addresses-for-netlifys-nameservers/8366) . It may take up to a day for the changes to propagate to the public internet. Next steps Once your name server settings have propagated across the domain name system, you’re ready to start using your domain and its subdomains. * To use the domain or a subdomain to access a Netlify site, visit the instructions for [assigning a domain to a site](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) . * If you want to point your domain or a subdomain to another service, like an email provider, visit the [DNS records](/domains-https/netlify-dns/dns-records/) doc for details. * If it’s been more than 24 hours, and your domain doesn’t seem to have propagated yet, visit the [troubleshooting](/domains-https/troubleshooting-tips/) page for tips and resources. Last updated: July 19, 2024 ← [Domain registration](/domains-https/netlify-dns/domain-registration/) [Delegate a stand-alone subdomain](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # HTTPS (SSL) | Netlify Docs Netlify offers free HTTPS on all sites, including automatic certificate creation and renewal. Our certificates use the modern TLS protocol, which has replaced the now deprecated SSL standard. HTTPS brings a lot of advantages: * **Content integrity.** Without HTTPS, free Wi-Fi services can inject ads into your pages. * **Security.** If your site has a login or accepts form submissions, HTTPS is essential for your users’ security and privacy. * **SEO.** Google search results prioritize sites with HTTPS enabled. * **Referral analytics.** HTTPS-enabled sites will not send referral data to sites without HTTPS enabled. * **HTTP/2.** Boost your sites’ performance — [HTTP/2](/domains-https/https-ssl/#http-2) requires HTTPS. [#](#certificate-service-types) Certificate service types ---------------------------------------------------------- Netlify offers two different ways of providing a certificate for HTTPS. **Netlify-managed certificates** are offered to all Netlify sites for free. Find details for this in the section on [Netlify-managed certificates](/domains-https/https-ssl/#netlify-managed-certificates) . **Custom certificates** are a way for you to provide a certificate that matches your specifications — things like a wildcard certificate or an Extended Validation (EV) certificate. If you’d like to provide your own custom certificate, refer to [Custom certificates](/domains-https/https-ssl/#custom-certificates) below for more details. For all certificate service types, Netlify enables HTTPS for only Netlify-hosted content. If you use Netlify to host content on an apex domain and other hosts for content on subdomains, Netlify cannot enable HTTPS for the subdomains with externally-hosted content. ### [#](#netlify-managed-certificates) Netlify-managed certificates When you create a new site on Netlify, it’s instantly secured at the Netlify-generated URL (for example, `https://brave-curie-12345.netlify.app`). If you add a [custom domain](/domains-https/custom-domains/) , we will automatically provision a certificate with [Let’s Encrypt](https://letsencrypt.org/) , enabling HTTPS on your domain. Certificates are generated and renewed automatically as needed. To ensure that only Netlify can create Let’s Encrypt certificates for your custom domain, you can add a [Certificate Authority Authorization (CAA) record](https://letsencrypt.org/docs/caa/) to your DNS provider that specifies Netlify’s `accounturi`, which is `https://acme-v02.api.letsencrypt.org/acme/acct/54403714`. For example, this is a CAA record for our domain `petsofnetlify.com`: petsofnetlify.com 300 IN CAA 0 issue "letsencrypt.org;accounturi=https://acme-v02.api.letsencrypt.org/acme/acct/54403714" Use Netlify DNS for automatic wildcards If your domain uses [Netlify DNS](/domains-https/netlify-dns/) , we’ll automatically provision a wildcard certificate, which ensures instant HTTPS for all of the Netlify sites using subdomains of that domain. In rare circumstances, there can be problems when provisioning a certificate for some domains. You can check the status of your site’s certificates in **Domain management \> HTTPS** . If you’re having trouble with the automatic provisioning, visit the [troubleshooting page](/domains-https/troubleshooting-tips/) for an error message guide and other tips. You can also visit our Forums for a verified Support Guide on [SSL / TLS certificate provisioning](https://answers.netlify.com/t/support-guide-ssl-tls-certificate-provisioning/1300) . #### [#](#domain-aliases) Domain aliases Your certificate will include all your [domain aliases](/domains-https/custom-domains/multiple-domains/#domain-aliases) when it’s issued, but note that DNS also needs to be configured _in advance_ for all aliases for us to include them on your certificate. Visit the [troubleshooting page](/domains-https/troubleshooting-tips/) for more information on confirming the new configuration. Avoid rate limiting for subdomains If you have more than 5 aliases that are subdomains of the same domain, you might run into rate limits with our certificate provider. In that case we recommend you provide your own wildcard certificate using Netlify DNS or [contact support](https://www.netlify.com/support) for our assistance for getting them set up with our certificate provider. Please do this _before adding any aliases_! ### [#](#custom-certificates) Custom certificates If you already have a certificate for your domain and prefer that to Netlify’s domain-validated certificate, you can install your own. To install a certificate, you’ll need: * the certificate itself, in X.509 PEM format (usually a .crt file) * the unencrypted private key you used to request the certificate * a chain of intermediary certificates from your Certificate Authority (CA) In **Domain management \> HTTPS** , select **Set Custom Certificate**, then enter the information above. For tips on specific formatting and the contents of the certificate, visit our Forums for a verified support guide on [custom SSL certificates](https://answers.netlify.com/t/support-guide-tips-for-bringing-your-own-custom-ssl-certificates-to-netlify/53633) . Renewal is not automatic When the time comes to renew your custom certificate, Netlify cannot do this automatically. You will need to renew it at your Certificate Authority, then follow the steps above to install it on your Netlify site. For automatic renewal, you can switch to a [Netlify-managed certificate](/domains-https/https-ssl/#netlify-managed-certificates) . Netlify validates that the certificate matches the custom domain for your site and that the DNS record for the domain is pointed at Netlify, then installs your certificate. If your certificate covers several of your sites (in other words, if it’s a wildcard certificate or uses Subject Alternative Names), you can install it on one site, and it will apply to all other sites covered by the certificate. Using automatic deploy subdomains? If you use a custom certificate for your site’s domains, that certificate must explicitly include any new subdomains used for automatic deploy subdomains. The standard wildcard syntax, such as `*.company.com`, does not cover this new subdomain. Learn more about [custom certificates and automatic deploy subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/#custom-certificate-requirements) . [#](#hsts-preload) HSTS preload -------------------------------- Most major browsers use a list of predefined domains to automatically connect to websites using HTTPS. This list is called the HTTP Strict Transport Security (HSTS) preload list. Your site can be included in this list if you follow the requirements in [hstspreload.org](https://hstspreload.org) : * Your custom domain must be accessible in the www subdomain. For example: `www.petsofnetlify.com`. * You must include this header in your [`_headers` file](/routing/headers/) or [Netlify configuration file](/configure-builds/file-based-configuration/) : * Loading error: Refresh the page to access this code sample /* Strict-Transport-Security: max-age=63072000; includeSubDomains; preload [[headers]] for = "/*" [headers.values] Strict-Transport-Security = ''' max-age=63072000; includeSubDomains; preload''' When this is set, the browser assumes that your site, along with all subdomains, can be accessed using HTTPS, and it will force those connections. This action is not easily reversible Please make sure to only use the directive `preload` once you’re confident that the domain _and all subdomains_ are ready to be served using _only_ HTTPS, since this setting is hard to remove once it’s in place, [as described at hstspreload.org](https://hstspreload.org/#removal) . [#](#http-2) HTTP/2 -------------------- When HTTPS is enabled for your site, Netlify supports HTTP/2, a newer internet protocol engineered for faster web performance. This brings support for core HTTP/2 features like request multiplexing and compressed headers, but does not include server push capability. Last updated: July 19, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Automatic deploy subdomains | Netlify Docs With automatic deploy subdomains, you can set up automatically branded URLs for Deploy Previews or branch deploys — unifying your site’s preview environments, auth flows, third-party services, and other site versions with a shared custom domain. Automatic deploy subdomains are a type of custom domain that you can set for all Deploy Previews or all branch deploys. ![Diagram showing that is the automatic deploy subdomain for the Deploy Preview URL of .](/images/domains-https-ads-defined.png) ### [#](#use-cases) Use cases When you set up an automatic deploy subdomain for all of your Deploy Previews or branch deploys, you can: * Share branded deploy URLs that don’t include the Netlify subdomain. For example, build greater trust with your stakeholders by sharing `deploy-preview-42.company.com` instead of `deploy-preview-42--yoursitename.netlify.app`. * Use third-party services the way you do for your production site, such as auth flow services that rely on a custom domain. * Ensure deploys are “trusted” and in the “allowed domain list” for any third-party scripts or services that require this. * Meet internal security requirements while leveraging Netlify’s Deploy Previews and branch deploys to preview and collaborate on changes before they go live. Once you configure an automatic deploy subdomain, Netlify uses this custom domain for your Deploy Previews and/or branch deploys by default within the Netlify UI, the API, CLI, and deploy notifications. ### [#](#domain-requirements) Domain requirements The custom domain you set as your automatic deploy subdomain must be managed by [Netlify DNS](/domains-https/netlify-dns/) and available to your team. By default, domains managed by Netlify DNS can be applied to your Deploy Previews or branch deploys. For example, if you already delegated `company.com` to Netlify DNS, then subdomains of `company.com`, such as `early-access.company.com`, are also delegated to Netlify DNS by default. That means you can use `early-access.company.com` as your automatic deploy subdomain. ![Diagram defining parts of the Deploy Preview URL , where the Deploy Preview prefix is , the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-deploy-previews.png) If you want to use a custom domain that Netlify DNS does not already manage, add the custom domain to your Netlify team and configure it to be managed by Netlify DNS. Learn more in these [domain setup steps](/domains-https/custom-domains/automatic-deploy-subdomains/#use-a-new-custom-domain-for-your-automatic-deploy-subdomain) . Want to use a subdomain without bringing the apex domain to Netlify DNS? You can bring a subdomain to Netlify DNS without the apex domain. For example, you can delegate `docs.company.com` to Netlify DNS without also delegating `company.com`. Learn more about [stand-alone subdomain support](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . ### [#](#example-deploy-urls) Example deploy URLs | Site deploys | Netlify subdomain | Automatic deploy subdomain | | --- | --- | --- | | [Deploy Preview](/site-deploys/overview/#definitions) | `deploy-preview-42--yoursitename.netlify.app` | `deploy-preview-42.company-internal-testing.com` | | [Branch deploy](/site-deploys/overview/#definitions)
, e.g. `staging` branch | `staging--yoursitename.netlify.app` | `staging.company-internal-testing.com` | | [Atomic deploy permalink](/domains-https/custom-domains/#netlify-subdomain-examples) | Uses the Netlify subdomain and a deploy ID, such as `1234abcd12acde000111cdef--yoursitename.netlify.app`. | N/A | When you set an automatic deploy subdomain for all Deploy Previews or all branch deploys, your deploys are still accessible at the Netlify subdomain, such as `deploy-preview-42--yoursitename.netlify.app` or `staging--yoursitename.netlify.app`. Using High-Performance Edge? If your site is on the [High-Performance Edge](https://www.netlify.com/platform/core/high-performance-edge/) , then automatic deploy subdomains are served from the High-Performance Edge. However, Netlify subdomains (`*.netlify.app`) are always served from the standard network. Your [deploy permalinks](/site-deploys/overview/#definitions) , which offer unique URLs for successful deploys of your site, will continue to use the Netlify subdomain. Unlike other deploy URLs, deploy permalinks do not update with new Git commits. Instead, Netlify generates new deploy permalinks for each successful deploy of your site. Not sure if you want to use Deploy Previews or branch deploys? Deploy Previews are scoped to a pull/merge request while branch deploys are scoped to a branch. Branch deploys can offer a longer-standing URL than Deploy Previews since they are based on the branch name and not the pull/merge request. Learn more about the difference between these deploys in these [docs](/site-deploys/overview/#branch-deploys-versus-deploy-previews) . [#](#automatic-deploy-subdomains-for-deploy-previews) Automatic deploy subdomains for Deploy Previews ------------------------------------------------------------------------------------------------------ Deploy Previews are automatically enabled for all sites using continuous integration with Netlify. If your site doesn’t have Netlify continuous integration set up, check out [these docs](/site-deploys/create-deploys/#deploy-with-git) . ### [#](#set-an-automatic-deploy-subdomain-for-deploy-previews) Set an automatic deploy subdomain for Deploy Previews To set up an automatic deploy subdomain for your site’s Deploy Previews: 1. Go to **Domain management \> Automatic deploy subdomains** . 2. Select **Edit custom domains**. 3. Next to **Deploy Previews**, select **Add custom domain**. 4. Under **Domain**, you’ll find domains managed by Netlify DNS. Select your chosen custom domain. Optionally, enter an additional subdomain, such as `early-access` or `qa`. ![](/images/domains-https-ads-for-deploy-previews.png) Want to use a different domain? If you can’t find the domain you want to add in the drop-down menu, check out these docs for [adding a new custom domain](/domains-https/custom-domains/automatic-deploy-subdomains/#use-a-new-custom-domain-for-your-automatic-deploy-subdomain) . 5. Review the preview of the deploy URL for your Deploy Previews. To confirm, select **Save**. Once saved, Netlify updates the domain for all open Deploy Previews. If you applied a custom domain that is not already live as your primary site domain (or does not already have a security certificate), then your new deploy URL may take up to 24 hours to resolve and work with HTTPS. [#](#automatic-deploy-subdomains-for-branch-deploys) Automatic deploy subdomains for branch deploys ---------------------------------------------------------------------------------------------------- Branch deploys are often used for maintaining a separate version of your site for QA, internal testing, or even to manage different versions of site content for different audiences or product versions. If you are already using [branch subdomains](/domains-https/custom-domains/multiple-domains/#branch-subdomains) , check out [our branch subdomain comparison docs](/domains-https/custom-domains/multiple-domains/#compare-subdomain-options-for-branch-deploys) to understand the key differences between these subdomains and how they can work together. If you set up an automatic deploy subdomain for branch deploys on your site, then each branch deploy will generate the same automatic deploy subdomain and include your branch deploy’s unique branch name. ![Diagram defining parts of the branch deploy URL , where the branch deploy prefix is the branch name, the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-branch-deploys.png) ### [#](#prerequisites) Prerequisites To set up an automatic deploy subdomain for your site’s branch deploys, you must first enable branch deploys for your site. 1. To enable branch deploys for your site, go to **Site configuration \> Build & deploy \> Branches and deploy contexts** . 2. Select **Configure**. 3. Next to **Branch deploys**, set up branch deploys for a specific branch or for all non-production branches. To confirm, select **Save**. 4. Once branch deploys are enabled, create a new branch and push a commit to this branch in your connected site repo. Netlify will automatically generate a branch deploy, which you can preview in your site’s deploy list. Created a deploy with the CLI? If you created a deploy using the [Netlify CLI’s `--alias` flag](/cli/get-started/#draft-deploys) , then be aware that these deploys are not branch deploys and do not support branch subdomains or automatic deploy subdomains. We recommend you avoid using `--alias` with any of your branch names. ### [#](#set-an-automatic-deploy-subdomain-for-branch-deploys) Set an automatic deploy subdomain for branch deploys To set up an automatic deploy subdomain for your site’s branch deploys: 1. Go to **Domain management \> Automatic deploy subdomains** . 2. Select **Edit custom domains**. 3. Next to **Branch deploys**, select **Add custom domain**. 4. Under **Domain**, you’ll find domains managed by Netlify DNS. Select your chosen custom domain. Optionally, enter an additional subdomain, such as `early-access` or `qa`. ![](/images/domains-https-ads-for-branch-deploys.png) Want to use a different domain? If you can’t find the domain you want to add in the drop-down menu, check out these docs for [adding a new custom domain](/domains-https/custom-domains/automatic-deploy-subdomains/#use-a-new-custom-domain-for-your-automatic-deploy-subdomain) . 5. Review the preview of the deploy URL for your branch deploys. To confirm, select **Save**. Once saved, Netlify updates the domain for all active branch deploys. If you applied a custom domain that is not already live as your primary site domain (or does not already have a security certificate), then your new deploy URL may take up to 24 hours to resolve and work with HTTPS. ### [#](#choose-a-unique-url-for-your-branch-deploys) Choose a unique URL for your branch deploys It is possible to configure automatic subdomains for branch deploys so that a branch subdomain conflicts with another site’s production domain. Since Deploy Previews are appended with the pull/merge request number, their automatic subdomains are unlikely to conflict with other domains. For example: * Site A has a primary site domain of `staging.company.com` for the production site. * Site B has an automated domain of `staging.company.com` for its `staging` branch. When there is a conflict, domains listed in your **Production domains** settings will take precedence over other internal domains. So in this example, `staging.company.com` will resolve to the content of site A. To prevent accidental domain duplication, you might choose to add another subdomain level to your branch subdomains that is not used in production, such as `internal` in `staging.internal.company.com`. If you get a domain conflict, you can rename the branch. For example, you can rename the branch from `staging` to `qa`. Then, the next time you deploy this branch, it would use the `qa.company.com` domain. ### [#](#limitations-for-sites-with-existing-branch-subdomains) Limitations for sites with existing branch subdomains Once you add an automatic deploy subdomain for branch deploys, you cannot edit or change existing manual [branch subdomains](/domains-https/custom-domains/multiple-domains/#branch-subdomains) . You also cannot manually add new branch subdomains, but existing branch subdomains will still work. If you configured branch subdomains before enabling automatic deploy subdomains, both the branch subdomains and automatic deploy subdomains will resolve and be available. If both are set up, the Netlify UI, CLI, API, and deploy notifications will link to the automatic deploy subdomain by default. To make changes to your branch subdomain, you must [remove the automatic deploy subdomain](/domains-https/custom-domains/automatic-deploy-subdomains/#remove-an-automatic-deploy-subdomain) first. If you want to compare using branch subdomains with automatic deploy subdomains, check out our [comparison docs for applying a custom domain to a branch deploy](/domains-https/custom-domains/multiple-domains/#manage-domains-for-deploy-previews-and-branch-deploys) . [#](#use-a-new-custom-domain-for-your-automatic-deploy-subdomain) Use a new custom domain for your automatic deploy subdomain ------------------------------------------------------------------------------------------------------------------------------ By default, you can choose primary site domains that are also managed by [Netlify DNS](/domains-https/netlify-dns) as your automatic deploy subdomain. You can also add additional subdomains to these domains, such as `early-access` or `qa`. ![](/images/domains-https-domain-drop-down-menu.png) If you want to use a custom domain that is not listed in the Netlify UI, you must first delegate this domain to Netlify DNS. Want to use a subdomain without bringing the apex domain to Netlify DNS? You can bring a subdomain to Netlify DNS without the apex domain. For example, you can delegate `docs.company.com` to Netlify DNS without also delegating `company.com`. Learn more about [stand-alone subdomain support](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . To delegate a new domain to Netlify DNS: 1. In the Netlify UI, navigate to your team’s **Domains** page. 2. Select **Add or register a domain**. 3. Enter your domain, and follow the UI prompts to delegate your domain to Netlify DNS. The UI may prompt you to add this domain to Netlify DNS. DNS updates can take up to 24 hours to take effect. On occasion, DNS record changes can take longer than this to propagate. Learn more in our [Support Guide on DNS propagation](https://answers.netlify.com/t/support-guide-why-do-dns-ssl-changes-take-up-to-48-hours-to-propagate-ttl/9359) . Once you have delegated your domain to Netlify DNS, your new domain should appear as a new drop-down menu option when you add your automatic deploy subdomain. [#](#use-the-netlify-api-to-set-automatic-deploy-subdomains) Use the Netlify API to set automatic deploy subdomains -------------------------------------------------------------------------------------------------------------------- You can set automatic deploy subdomains when you create a site using the Netlify API. In your [`createSite`](https://open-api.netlify.com/#tag/site) request, use the following query parameters to pass the values to use for the subdomains: * `deploy_preview_custom_domain` * `branch_deploy_custom_domain` Note that when you create or update a site with an automatic deploy subdomain, the build environment variable `DEPLOY_PRIME_URL` will update for all relevant deploys. Learn more about [`DEPLOY_PRIME_URL`](/configure-builds/environment-variables/#deploy-urls-and-metadata) . [#](#custom-certificate-requirements) Custom certificate requirements ---------------------------------------------------------------------- If you use a [custom certificate](/domains-https/https-ssl/#custom-certificates) for your site’s domains, that certificate must explicitly include any new subdomains used for automatic deploy subdomains. The standard wildcard syntax, such as `*.company.com`, does not cover this new subdomain. For example, your custom certificate will not work as expected in this scenario: * you have `early-access.company.com` as your automatic deploy subdomain, where `early-access` is the optional new subdomain you [added in the Netlify UI](/domains-https/custom-domains/automatic-deploy-subdomains/#set-an-automatic-deploy-subdomain-for-deploy-previews) ![Diagram defining parts of the Deploy Preview URL , where the optional newly added subdomain is and is the custom domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-without-prefix.png) * you have a custom certificate with `*.company.com` as your wildcard domain but not `*.early-access.company.com` In this scenario, you must update your certificate to include the domains `*.company.com, *.early-access.company.com` so that `early-access.company.com` will work as expected. [#](#remove-an-automatic-deploy-subdomain) Remove an automatic deploy subdomain -------------------------------------------------------------------------------- To remove an automatic deploy subdomain from your Deploy Previews or branch deploys: 1. Go to **Domain management \> Automatic deploy subdomains** . 2. Select **Edit custom domains**. 3. Next to **Branch deploys** or **Deploy Previews**, clear the **Add custom domain** checkbox. 4. To confirm, select **Save**. Last updated: July 19, 2024 ← [Configure external DNS](/domains-https/custom-domains/configure-external-dns/) [Multiple domains](/domains-https/custom-domains/multiple-domains/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # DNS records | Netlify Docs DNS records are rules that tell domain name servers how to handle traffic to your domains and subdomains. For domains managed by Netlify, we will automatically create “NETLIFY” records that point to our servers when you [assign a domain or subdomain](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) for your site. To learn more, visit our Forums for a verified support guide on [this type of DNS record](https://answers.netlify.com/t/support-guide-what-are-the-netlify-and-netlifyv6-type-dns-records-how-do-i-delete-these-records/17430) . You can also add your own DNS records to point to other services, such as an email provider. Visit our Forums for a verified Support Guide on [how to receive emails on your domain](https://answers.netlify.com/t/support-guide-how-can-i-receive-emails-on-my-domain/178) . [#](#supported-record-types) Supported record types ---------------------------------------------------- Netlify DNS supports the following types of records: * **A**: Address record, which is used to map host names to their IPv4 address. * **AAAA**: IPv6 Address record, which is used to map host names to their IPv6 address. * **CAA**: Certificate Authority (CA) Authorization, which is used to specify which CAs are allowed to create certificates for a domain. * **CNAME**: Canonical name record, which is used to specify alias names. * **MX**: Mail exchange record, which is used in routing requests to mail servers. * **NS**: Name server record, which delegates a DNS zone to an authoritative server. * **SPF**: Sender Policy Framework record, a deprecated record type formerly used in e-mail validation systems (use a TXT record instead). * **SRV**: Service locator record, which is used by some voice over IP, instant messaging protocols, and other applications. * **TXT**: Text record, up to 255 characters. Can contain arbitrary text and can also be used to define machine-readable data, such as security or abuse prevention information. [#](#add-a-new-record) Add a new record ---------------------------------------- To add a new DNS record: 1. Go to the **Domains** tab for your team. 2. Select the domain you want to edit. 3. At the bottom of the **DNS records** section, select **Add new record**. 4. Choose the type of record to create from the menu and fill in the remaining options. The fields you need to fill out will depend on the type of record you select. 5. Select **Save** to create the record and make the changes live. Remember, it may take up to a few hours for record changes to propagate. Note that you can host records for other services, such as your mail provider or your backend API, with us as long as you host at least one website with us that uses the domain. Next step If you’re adding DNS records as part of the process of moving your DNS service to Netlify DNS, your next step is to [delegate your domain to Netlify](/domains-https/netlify-dns/delegate-to-netlify/) . [#](#edit-a-record) Edit a record ---------------------------------- To make DNS changes, you need to first [add a new record](#add-a-new-record) with the new value and then [delete the old record](#delete-a-record) . DNS allows multiple entries for the same name and type, so you can avoid downtime by making changes this way. [#](#delete-a-record) Delete a record -------------------------------------- To delete a DNS record: 1. Go to the **Domains** tab for your team. 2. Select the domain you want to edit. 3. In the **DNS records** section, find the record you want to delete. 4. Select the record to expand the details and then select the delete option. 5. Review the warning message and select **Delete** to confirm. Remember, it may take up to a few hours for record changes to propagate. [#](#api-endpoints) API endpoints ---------------------------------- You can use the [API](https://open-api.netlify.com/#operation/getDnsRecords) to get DNS records, create DNS records, and more. Last updated: July 19, 2024 ← [Delegate a stand-alone subdomain](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) [Dedicated secondary DNS](/domains-https/netlify-dns/dedicated-secondary-dns/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Netlify DNS | Netlify Docs Netlify offers the option to handle DNS management for you. This enables advanced subdomain automation and deployment features, and ensures that your site uses our CDN for the apex domain as well as subdomains like www. Using an external DNS provider and don’t want to use Netlify DNS? If you use another service to manage your DNS, refer to our [configure external DNS](/domains-https/custom-domains/configure-external-dns/) doc to learn how to point your domain to Netlify. [#](#netlify-dns-domain-support) Netlify DNS domain support ------------------------------------------------------------ You can delegate many different types of domains to Netlify DNS, including [apex domains](/domains-https/custom-domains/#definitions) or [subdomains](/domains-https/custom-domains/#definitions) , which include stand-alone subdomains. For example, you can delegate a subdomain to Netlify DNS without the need to bring your apex domain to Netlify DNS. So you can delegate just `docs.company.com` to Netlify without bringing over `company.com` too. Learn more about [stand-alone subdomain support](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . [#](#automatic-deploy-subdomains) Automatic deploy subdomains -------------------------------------------------------------- Netlify can generate a custom domain for all of your Deploy Previews or branch deploys when you set up an automatic deploy subdomain. ![Diagram showing that is the automatic deploy subdomain for the Deploy Preview URL of .](/images/domains-https-ads-defined.png) Standardizing a custom subdomain for your Deploy Previews or branch deploys can unlock new ways of integrating deploys with your branding, review workflows, or security needs. Automatic deploy subdomains include a custom domain that must be managed by Netlify DNS and an optional additional subdomain. ![Diagram defining parts of the Deploy Preview URL , where the Deploy Preview prefix is , the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-deploy-previews.png) ![Diagram defining parts of the branch deploy URL , where the branch deploy prefix is the branch name, the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-branch-deploys.png) Learn more about [automatic deploy subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/) . [#](#branch-subdomains) Branch subdomains ------------------------------------------ Netlify can generate a custom domain for branch deploys you specify using your production site’s primary domain as long as this domain is managed by Netlify DNS. Learn more about [branch subdomains](/domains-https/custom-domains/multiple-domains/#branch-subdomains) . [#](#add-a-domain) Add a domain -------------------------------- Team and Organization [Owners](/accounts-and-billing/team-management/roles-and-permissions/#owner) can add a custom domain to Netlify DNS by registering a new domain or by delegating an existing domain from another registrar. ### [#](#register-a-new-domain) Register a new domain To learn how to register a new domain, visit the [domain registration](/domains-https/netlify-dns/domain-registration/) page. ### [#](#add-a-domain-you-own) Add a domain you own To add a domain you have already registered elsewhere: 1. Go to your team’s **Domains** page and select **Add or register domain**. 2. Enter the domain you wish to add and select **Verify**. 3. You will be asked to confirm that you are the owner of the domain. Select **Yes, add domain** to create a Netlify DNS zone for the domain. You will be given the option to [add DNS records](/domains-https/netlify-dns/dns-records/) , followed by instructions to [delegate your domain to Netlify](/domains-https/netlify-dns/delegate-to-netlify/) . Looking to add a domain name that uses Unicode characters? To add a domain name that uses Unicode (or non-ASCII) characters such as ñ or é, use Punycode format. First, convert your domain name to Punycode using a Punycode converter, such as [Punycoder](https://www.punycoder.com/) . Then, use the converted output for the domain name as you follow the **Add or register domain** prompts. ### [#](#set-up-emails-on-your-domain) Set up emails on your domain Netlify doesn’t provide a full email service. But, if you have set up email with an external email service provider and are using Netlify’s DNS hosting, you can add the MX records to Netlify DNS to use emails on your domain. Visit our Forums for a verified Support Guide on [how to receive emails on your domain](https://answers.netlify.com/t/support-guide-how-can-i-receive-emails-on-my-domain/178) . Send custom emails with Netlify Check out our [Netlify Email Integration](/integrations/email-integration/) to use Netlify and an email API provider to send custom emails that are stored and versioned alongside your project code. [#](#transfer-domains-between-teams) Transfer domains between teams -------------------------------------------------------------------- To transfer domains between teams, you must be a Team or Organization [Owner](/accounts-and-billing/team-management/roles-and-permissions/#owner) . If you already have a domain in your team’s **Domains** page, you can transfer the domain and all of its settings to any other team where you are an Owner or Developer. To do this, select the domain you wish to transfer, then go to **Collaboration > Transfer ownership**, near the bottom of the page. For information about transferring domains between _registrars_, visit the [domain registration](/domains-https/netlify-dns/domain-registration/#transfer-registration) page. [#](#ipv6-traffic) IPv6 traffic -------------------------------- IPv6 is a new version of the IP protocol that allows your site to reach areas of the world where connectivity using IPv4 is not possible due to the lack of IP addresses. For now, IPv6 is not enabled by default on all Netlify sites. If you use Netlify DNS, you need to enable it explicitly in your Domains dashboard. After [adding a domain to Netlify DNS](/domains-https/netlify-dns/#add-a-domain) , you’ll be able to enable IPv6 traffic for your domain by selecting **Enable IPv6** on the zone header: ![](/images/domains-https-dns-enable-ipv6.png) After IPv6 is enabled for your domain, your main domain and all the branch subdomains that you create will use IPv6, as well as IPv4. Last updated: June 3, 2024 [Domain registration](/domains-https/netlify-dns/domain-registration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # DNS & HTTPS troubleshooting tips | Netlify Docs If you’re having trouble accessing your site at your custom domain or branch subdomain, there is likely a problem with your DNS or HTTPS setup. This page includes tips and information to help get things working properly. [#](#dns-configuration) DNS configuration ------------------------------------------ The `dig` command line tool is a great tool for quickly diagnosing and understanding DNS responses. It is built into Linux and Mac, but can also be installed on Windows. Alternatively, you can use an online tool to [run `dig` in the browser](https://toolbox.googleapps.com/apps/dig/) . NS1, the DNS provider backing Netlify DNS, has a great series of articles on [using DIG](https://ns1.com/articles/decoding-dig-output) to test and troubleshoot your DNS configuration. ### [#](#inactive-netlify-dns-zone) Inactive Netlify DNS zone A common DNS configuration issue is an inactive Netlify DNS zone. This prevents our service from creating or updating the automatic Let’s Encrypt SSL certificates for your custom domain. This can cause problems for branch subdomains. For more information, visit our Forums for a verified Support Guide on [how to detect and fix inactive Netlify DNS zones](https://answers.netlify.com/t/support-guide-how-to-detect-and-fix-inactive-netlify-dns-zones/21742) . [#](#custom-certificate-not-working-for-automatic-deploy-subdomain) Custom certificate not working for automatic deploy subdomain ---------------------------------------------------------------------------------------------------------------------------------- If a custom certificate is not working for your automatic deploy subdomain, ensure your certificate includes any new subdomains used for automatic deploy subdomains. For example, for the automatic deploy subdomain `early-access.company.com` , your custom certificate should include the domains `*.company.com, *.early-access.company.com` and not just `*.company.com`. Learn more about [custom certificates and automatic deploys subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/#custom-certificate-requirements) . [#](#certificates-and-https) Certificates and HTTPS ---------------------------------------------------- There are many reasons why adding a Netlify certificate or uploading a custom certificate might not work. The common causes are listed below, but if they don’t seem to apply to you or you have additional questions, our [Support team](https://www.netlify.com/support) will be happy to help out! 1. Most importantly, you’ll need to [**configure the DNS for the custom domain**](/domains-https/custom-domains/) before Netlify can issue a certificate for you. Netlify must validate the domain in order to provision the certificate, and this step cannot be completed until the DNS records for your custom domain are pointing to our servers. 2. **All previous DNS settings must have their cache timeouts expired.** The [TTL setting](https://www.dnsknowledge.com/whatis/time-to-live-ttl/) on a DNS record determines how long the record may be cached. This cache must expire before your new DNS settings can be validated for certificate provisioning. 3. If your site is configured to go through another service (for example, using [Cloudflare “accelerate and protect”](https://answers.netlify.com/t/common-issue-why-isn-t-my-ssl-certificate-provisioning-automatically-with-cloudflare-netlify-are-there-other-problems-with-using-cloudflare-in-front-of-netlify/138) , or similar), **you need to disable that routing before we can provision the certificate**. Netlify must handle TLS termination to be able to provision a certificate. 4. It is possible that the name servers we use have some old cached values for your domain name. You can attempt to **accelerate cache expiration** for your domains using the [Flush Cache tool](https://developers.google.com/speed/public-dns/cache) provided by Google Public DNS. 5. It is possible that we will get a certificate for one name (for example, `petsofnetlify.com`) and not for another (for example, `www.petsofnetlify.com` or some domain alias). In this case selecting **Renew certificate** should resolve the issue. If it doesn’t, please post in the [Netlify Support Forums](https://answers.netlify.com/categories) so our support engineers can repair the certificate. ### [#](#https-error-messages) HTTPS error messages You can check the status of your certificate in **Domain management \> HTTPS** . If there is a problem with the certificate, you may find one of the error messages below. (We’re using `petsofnetlify.com` as an example.) #### [#](#petsofnetlify-com-doesn-t-appear-to-be-served-by-netlify) “petsofnetlify.com doesn’t appear to be served by Netlify” In order to make sure that the site is served by Netlify, check the HTTP response headers. 1. Examine the HTTP response headers in your browser’s [dev tools](https://developer.chrome.com/docs/devtools/network/reference/#headers) , using an [online checker](https://httpstatus.io/) , or with the following terminal command: curl -s -v http://your-newly-configured-hostname.com 2>&1 | grep -i server 2. Check for a line that says `server: Netlify`. 3. Repeat this for **each** domain connected to your site. If your custom domain is the apex domain or `www` subdomain (for example, `petsofnetlify.com` or `www.petsofnetlify.com`), we automatically serve your site and provision a certificate for both domains, so be sure they both have records pointing to Netlify. The next steps depend on what you find in the HTTP response headers. * If you do find `server: Netlify` in all response headers, but still receive this error, it may be caused by incorrect A records. For information on setting a proper A record with Netlify, refer to our documentation on [external DNS configuration](/domains-https/custom-domains/configure-external-dns/) . * If you don’t find `server: Netlify` in all response headers, and you’ve eliminated the [common problem sources listed above](#certificates-and-https) , please [contact support](https://www.netlify.com/support) . #### [#](#petsofnetlify-com-is-not-resolvable-with-a-resolver-that-validates-dnssec) “petsofnetlify.com is not resolvable with a resolver that validates DNSSEC” Netlify DNS doesn’t support DNSSEC. To use Netlify DNS, disable DNSSEC with your domain registrar or previous DNS host. You can use tools like [DNSViz](http://dnsviz.net/) to figure out where DNSSEC is currently enabled. To keep DNSSEC enabled, you can stop using Netlify DNS and use [external DNS](/domains-https/custom-domains/configure-external-dns/) instead. Last updated: July 19, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Sites with multiple domains | Netlify Docs You can find the domains associated with your site in the **Domain management** section of your site configuration. Need to delegate just a subdomain? You can delegate a subdomain to Netlify DNS without the apex domain. Learn more in this [doc](/domains-https/netlify-dns/delegate-a-subdomain-to-netlify-dns/) . [#](#manage-domains-for-your-production-site) Manage domains for your production site -------------------------------------------------------------------------------------- You can find the domains for your production site at **Domain management \> Production domains** . You have several options for managing multiple domains for your production site. ### [#](#domain-aliases) Domain aliases You can assign multiple custom domains to the same production site. When you do this, one is designated as the **primary domain**, and all others are called **domain aliases**. We recommend assigning no more than 50 domain aliases to a site. You can add a domain alias in your site configuration under **Domain management \> Production domains** . Select **Add domain alias**, and follow the process for [assigning a domain to your site](/domains-https/custom-domains/#assign-a-domain-to-a-production-site) . To change a domain alias to the primary domain, select the **Options** button next to the domain, then select **Set as primary domain**. ### [#](#domain-redirects) Domain redirects If you have multiple domains assigned to your site, you can redirect visitors between them or add other custom [redirect and rewrite rules](/routing/redirects/) based on the domain entered into the browser by your visitors. For more information, visit the docs on [domain-level redirects](/routing/redirects/redirect-options/#domain-level-redirects) . ### [#](#apex-domains-and-www-subdomains) Apex domains and `www` subdomains When you assign an apex domain (eg. `petsofnetlify.com`) _or_ a `www` subdomain (eg. `www.petsofnetlify.com`) as the primary domain for your site, two entries are added to the **Production domains** panel: * one entry for the apex domain, and * one entry for the `www` subdomain. The primary domain is the custom domain you entered. The other entry is for the alternative domain that gets redirected automatically to the primary domain. * If you set the `www` subdomain as your primary domain, Netlify will automatically redirect the apex domain to the `www` subdomain. * If you set the apex domain as your primary domain, Netlify will automatically redirect the `www` subdomain to the apex domain. If you’re using external DNS, **we strongly recommend setting the `www` subdomain (or another subdomain) as your primary domain**. If you want to set an apex domain as your primary domain, we recommend using Netlify DNS. Our blog post [How to Set Up Netlify DNS](https://www.netlify.com/blog/2020/03/26/how-to-set-up-netlify-dns-custom-domains-cname-a-records/) has more details on these recommendations. Redirects for non-`www` subdomains Though Netlify automatically redirects between the apex domain and `www` subdomain, we don’t do this for any other subdomains. You can configure this behavior yourself with [domain-level redirects](/routing/redirects/redirect-options/#domain-level-redirects) . [#](#manage-domains-for-deploy-previews-and-branch-deploys) Manage domains for Deploy Previews and branch deploys ------------------------------------------------------------------------------------------------------------------ When you first set up your site on Netlify, Deploy Previews and branch deploys will use the Netlify subdomain `netlify.app`. For example: * Deploy Previews use `deploy-preview-#--yoursitename.netlify.app` * Branch deploys use `branch-name--yoursitename.netlify.app` You can further customize these subdomains with automatic deploy subdomains and/or branch subdomains. We recommend automatic deploy subdomains for [Core Pro plans and above](https://www.netlify.com/pricing/) with these scenarios: * you want a custom domain for a Deploy Preview * you want to set up a custom domain for all branch deploys without more setup * you want maximum flexibility with your custom domain If you want more manual control over a custom domain for branch deploys and don’t need a different custom domain beyond the production site’s primary domain, then branch subdomains may be a better option for you. ### [#](#automatic-deploy-subdomains) Automatic deploy subdomains _This feature is available in our UI with [Netlify DNS](/domains-https/netlify-dns/) _. Netlify can generate a custom domain for all of your Deploy Previews and/or branch deploys when you set up an automatic deploy subdomain. ![Diagram showing that is the automatic deploy subdomain for the Deploy Preview URL of .](/images/domains-https-ads-defined.png) Automatic deploy subdomains include a custom domain or subdomain that must be managed by Netlify DNS and an optional additional subdomain. ![Diagram defining parts of the Deploy Preview URL , where the Deploy Preview prefix is , the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-deploy-previews.png) ![Diagram defining parts of the branch deploy URL , where the branch deploy prefix is the branch name, the optional newly added subdomain is and is the domain managed by Netlify DNS.](/images/domains-https-ads-parts-defined-for-branch-deploys.png) Standardizing a custom subdomain for your Deploy Previews or branch deploys can unlock new ways of integrating deploys with your branding, review workflows, or security needs. Learn more about [automatic deploy subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/) . ### [#](#branch-subdomains) Branch subdomains _This feature is available in our UI with [Netlify DNS](/domains-https/netlify-dns/) _. Netlify can generate a branch subdomain for specified branch deploys using your site’s primary custom domain designated for your production site. The resulting branch subdomains use the fixed syntax `branchname.yourcustomdomain.com` and can’t use a different pattern. For example, if your custom domain is `example.com` and your branch is `staging`, you can check the latest deploy of that branch at `staging.example.com`. Before you can enable branch subdomains, you must [enable branch deploys](/site-deploys/overview/#branch-deploy-controls) for your branch and successfully deploy your branch. To add a new branch subdomain, go to **Domain management \> Domains \> Branch subdomains** , and select **New subdomain**. ![](/images/domains-https-branch-subdomains-screenshot.png) A branch subdomain can be deleted by using the `x` button in the corresponding subdomain row. ![](/images/domains-https-subdomain-record.png) Visit our Forums for a verified Support Guide on [setting up branch subdomains without Netlify DNS](https://answers.netlify.com/t/support-guide-how-to-use-netlify-s-branch-deploy-feature-without-netlify-dns/) . ### [#](#compare-subdomain-options-for-branch-deploys) Compare subdomain options for branch deploys For an overview of the main differences between these subdomains, consider these key differences. | | Automatic deploy subdomains | Branch subdomains | | --- | --- | --- | | **Custom domain options** | Can use your production site’s primary domain or any other custom domain or subdomain managed by Netlify DNS and available to your team. | Can only use your production site’s primary domain, which must be managed by Netlify DNS. | | **Additional subdomain support** | X | | | **Requires Netlify DNS** | X | X | | **Pricing plan** | Core Pro plan and above | All plans | | **Branch deploy scope** | Applies to all branch deploys. | Applies to user-specified branch deploys:
individual branches or all branches except the designated production branch. | | **Setup interactions** | Once set up, becomes the primary deploy URL for branch deploys. Cannot change existing branch subdomain settings without [removing your automatic deploy subdomain](/domains-https/custom-domains/automatic-deploy-subdomains/#remove-an-automatic-deploy-subdomain)
. | Once automatic deploy subdomains are set up, cannot change existing branch subdomain settings but branch subdomain URLs still resolve for pre-existing branches. | #### [#](#set-up-both-a-branch-subdomain-and-an-automatic-deploy-subdomain) Set up both a branch subdomain and an automatic deploy subdomain If you want to use both branch subdomains and an automatic deploy subdomain for branch deploys, ensure that you set up any branch subdomains before your automatic deploy subdomain. We recommend setting up only stable or internal branch subdomains since you would need to remove your automatic deploy subdomain to make changes to your branch subdomain settings. Also, note that the Netlify UI, CLI, and API will use the automatic deploy subdomain for branch deploys configured with a branch subdomain. The branch deploy URL featuring your branch subdomain, such as `staging.company.com` should still resolve and work for site visitors though. Learn more about [limitations to using both types of subdomains for branch deploys](/domains-https/custom-domains/automatic-deploy-subdomains/#limitations-for-sites-with-existing-branch-subdomains) . Last updated: July 19, 2024 ← [Automatic deploy subdomains](/domains-https/custom-domains/automatic-deploy-subdomains/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Edge Functions API | Netlify Docs This page provides an overview of key concepts as well as a full reference. [#](#overview) Overview ------------------------ Use TypeScript or JavaScript to create an edge function file that exports a default function responsible for processing a request. When the function is invoked, it receives two arguments: * a [standard `Request` object](https://developer.mozilla.org/en-US/docs/Web/API/Request) representing the incoming HTTP request * a [Netlify-specific `Context` object](#netlify-specific-context-object) The expected return value is one of the following: * a [standard `Response` object](https://developer.mozilla.org/en-US/docs/Web/API/Response) representing the HTTP response to be delivered to the client * a [standard `URL` object](https://developer.mozilla.org/en-US/docs/Web/API/URL) if you want to rewrite the incoming request to another same-site URL with a 200 status code * `undefined` if you choose to bypass the current function ### [#](#edge-function-types) Edge function types For TypeScript, you can import the types for the `Context` and `Config` objects from `@netlify/edge-functions`. The types for the `Request` and `Response` objects are in the global scope. import type { Config, Context } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { // ... }; export const config: Config = { path: "/", }; ### [#](#request-handling) Request handling Edge functions can handle requests in the following ways: * [return a response](#return-a-response) directly as an endpoint * [redirect](#return-a-redirect) to any URL * [rewrite](#return-a-rewrite) to a same-site URL * [modify a response](#modify-a-response) as middleware Looking for a list of available request headers? Netlify doesn’t add specific headers to edge function requests. To find information about the client request, use the [`context` object](/edge-functions/api/#netlify-specific-context-object) instead. #### [#](#return-a-response) Return a response Similar to serverless functions and other endpoints, an edge function can just return a [standard `Response` object](https://developer.mozilla.org/en-US/docs/Web/API/Response) . Once the function returns the response, the request chain ends and any redirects declared for that path do not occur. For example, this edge function [returns the string](https://edge-functions-examples.netlify.app/example/hello) `Hello, World!` as text/html: export default async () => { return new Response("Hello, World!", { headers: { "content-type": "text/html" } }); }; #### [#](#return-a-redirect) Return a redirect You can use an edge function to return [an HTTP redirect](https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections) to any URL of your choice. To do this, use the [standard `Response.redirect` function](https://developer.mozilla.org/en-US/docs/Web/API/Response/redirect) , as shown in the example below. export default async (req: Request, { cookies, geo }: Context) => { if ( geo.city === "Paris" && cookies.get("promo-code") === "15-for-followers" ) { const url = new URL("/subscriber-sale", req.url); return Response.redirect(url); } }; #### [#](#return-a-rewrite) Return a rewrite Similar to our [static routing engine](/routing/redirects/rewrites-proxies/) , an edge function can also return a rewrite, which is a redirect with a 200 status code. This means that the URL in the visitor’s address bar remains the same, while Netlify’s servers fetch the new location behind the scenes. To do this, return a [standard `URL` object](https://developer.mozilla.org/en-US/docs/Web/API/URL) with the path you want to rewrite to. export default async (request: Request, { cookies, geo }: Context) => { if ( geo.city === "Paris" && cookies.get("promo-code") === "15-for-followers" ) { return new URL("/subscriber-sale", request.url); } }; Same-site URLs only Edge functions can rewrite to only same-site URLs. To fetch content hosted on another Netlify site or an external site, use the [`fetch` Web API](/edge-functions/api/#web-apis) . #### [#](#modify-a-response) Modify a response An edge function can act as middleware that modifies and returns the response of subsequent functions or requests. This kind of edge function calls `context.next()` to continue the request chain and waits for a response to return before finishing execution. Any edge functions that return `undefined` or use an empty `return;` also continue the request chain. Once all edge functions for the initial path run, Netlify evaluates any redirect rules declared for that path and then continues the request chain to eventually serve static content or return a response from a serverless function. For more details on the order of events, review our docs on the [declaration processing order](/edge-functions/declarations/#declaration-processing-order) . For example, this edge function uses `context.next()` to [transform the content](https://edge-functions-examples.netlify.app/example/transform) of the HTTP response to the requested path: import type { Context } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { const url = new URL(request.url); // Look for the query parameter, and return if we don't find it if (url.searchParams.get("method") !== "transform") { return; } const response = await context.next(); const text = await response.text(); return new Response(text.toUpperCase(), response); }; If you want to modify and return the content of a path other than the requested one, use `fetch()` to retrieve it. export default async (req: Request) => { const url = new URL("/welcome", req.url); const res = await fetch(url); return someTransformationFunction(res); }; export const config = { path: "/hello" }; ##### [#](#use-conditional-request) Use conditional request When using `context.next()` to transform a response, we modify the request to the downstream asset so that [conditional requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests#cache_update) don’t apply and you always get a full response back. If you want full control over the client caching behavior and you’d like to use conditional requests, you should pass the `sendConditionalRequest` to the `context.next()` call. export default async (req: Request, { next }: Context) => { const res = await next({ sendConditionalRequest: true }); // If the response is a 304, it’s cached in the client and we can return it if (res.status === 304) { return res; } // Transform the response however you need const text = await res.text(); return new Response(text.toUpperCase(), res); }; ##### [#](#read-request-body) Read request body If you want to read the request body in your edge function, you need to explicitly pass on a new request with an unused body when you call `context.next()` afterwards. For example, `context.next(new Request(...))`. Without this, attempts to read the request body in subsequent edge functions will cause an error because a request body can only be read once. export default async (req: Request, context: Context) => { const body = await req.json(); if (!isValid(body.access_token)) { return new Response("forbidden", { status: 403 }); } return context.next(new Request(req, { body: JSON.stringify(body) })); }; ### [#](#runtime-environment) Runtime environment Edge functions run in a [Deno](https://deno.land/)  runtime environment that supports many standard Web APIs. Edge Functions support Node.js built-in modules and Deno modules. Support for npm packages is in beta. * For Node.js built-in modules, prefix the import with `node:`, for example `import { randomBytes } from "node:crypto"`. * For Deno modules, use a URL import. You can do this directly in the edge function code, for example `import React from "https://esm.sh/react"`, or by using an [import map](#import-maps) . * For npm packages, install them [using `npm install`](https://docs.npmjs.com/cli/v6/commands/npm-install) or your favorite package manager. Then import them using the package name, for example `import _ from "lodash"`. Support for npm modules is in beta, and some packages that rely on native binaries (like [Prisma](https://github.com/prisma/prisma) ) or dynamically importing a file at runtime (like [cowsay](https://github.com/piuccio/cowsay) ) might not work correctly. Please share feedback and bug reports [in the forums](https://answers.netlify.com) . Edge functions have access to environment variables in the runtime environment. If you have the option to set specific scopes for your environment variables, the scope must include **Functions** to be available to edge functions during runtime. Learn more about how to set and use [environment variables with functions](/functions/environment-variables/) . ### [#](#import-maps) Import maps When you import third-party modules in your edge function, it can be cumbersome to repeat the module’s full URL in every import statement. To use module names in your import statements, use an import map file to map module URLs to names. Netlify edge functions support separate import map files instead of import maps defined in `deno.json`. You can place the import map file anywhere in the project directory. For example, this file maps `html-rewriter` to `https://ghuc.cc/worker-tools/html-rewriter/index.ts`: { "imports": { "html-rewriter": "https://ghuc.cc/worker-tools/html-rewriter/index.ts" } } To enable the import map, declare it in `netlify.toml`: [functions] deno_import_map = "./path/to/your/import_map.json" You can now use `html-rewriter` as a shorthand for the module URL. import { HTMLRewriter } from "html-rewriter"; export default async (request, context) => { return new HTMLRewriter() .on("p", { element(element) { element.tagName = "h1"; } }) .transform(await context.next()); }; [#](#reference) Reference -------------------------- This reference covers the following: * Netlify-specific [`Context` object](#netlify-specific-context-object) * [`Netlify` global object](#netlify-global-object) * Supported [Web APIs](#web-apis) You may encounter undocumented APIs as you work with Edge Functions. These are not supported in any way and you should not use them. Using undocumented APIs may lead to unexpected or broken functionality. Searching for type definitions? For TypeScript, you can import the types for the `Context` and `Config` objects from `@netlify/edge-functions`. The types for the `Request` and `Response` objects are in the global scope. ### [#](#netlify-specific-context-object) Netlify-specific `Context` object The `Context` object exposes the following properties: * **`account`:** an object containing Netlify team account information with the following property: * **`id`:** unique ID of the team that the site and function belong to. * **`cookies`:** a simplified interface for reading and storing [cookies](https://deno.land/std@0.148.0/http/cookie.ts?s=Cookie) : * **`cookies.get(name)`:** reads a cookie with a given name from the incoming request. * **`cookies.set(options)`:** sets a cookie on the outgoing response, using the same format as the `options` value in [the `CookieStore.set` web standard](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore/set) . * **`cookies.delete(name)`** or **`cookies.delete(options)`:** adds an instruction to the outgoing response for the client to delete a cookie. Following [the `CookieStore.delete` web standard](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore/delete) , accepts a string representing the name of the cookie, or an options object. Setting cookies across subdomains only works for custom domains `netlify.app` is listed in the Mozilla Foundation’s [Public Suffix List](http://publicsuffix.org/) , which prevents setting cookies across subdomains. You can only set a cookie for all subdomains if your site uses a [custom domain](/domains-https/custom-domains/) instead of `yoursitename.netlify.app`. * **`deploy`:** an object containing Netlify deploy information with the following properties: * **`context`:** the [context](/site-deploys/overview/#deploy-contexts) of the deploy that the function belongs to. * **`id`:** unique ID of the deploy that the function belongs to. * **`published`:** a boolean that indicates whether or not the function belongs to the current [published deploy](/site-deploys/overview/#definitions) . * **`geo`:** an object containing geolocation data for the client with the following properties: * **`city`:** name of the city. * **`country`:** * **`code`:** ISO 3166 code for the country. * **`name`:** name of the country. * **`latitude`:** latitude of the location. * **`longitude`:** longitude of the location. * **`subdivision`:** * **`code`:** ISO 3166 code for the country subdivision. * **`name`:** name of the country subdivision. * **`timezone`:** timezone of the location. * **`postalCode`:** postal (zip) code of the location. We support all regional formats, so the format will vary. * **`ip`:** a string containing the client IP address. * **`next(options?)`:** invokes the [next item in the request chain](/edge-functions/api/#modify-a-response) . The method returns a `Promise` containing the `Response` from the origin that your edge function can modify before returning. Use this method only if you need access to the response body. Accepts an optional `options` object with the following property: * **`sendConditionalRequest`:** set to true if you’d like to use conditional requests. * **`next(request, options?)`:** same method as above, except this one explicitly requires a `Request` object. This variation allows you to read the request body in your edge function and then pass a new request object with an unread body to the next item in the request chain. Without this, the `next()` call could fail as a request body can only be read once. * **`params`:** object containing the parameters set for the edge function’s `path` in the [configuration object](/edge-functions/get-started/#create-an-edge-function) and the values they receive from the incoming request URL. For example, for an edge function configured to run at `/pets/:name`, the `params` value for a request to `/pets/winter` will be `{"name":"winter"}`. To access the query string, use `request.url` instead. * **`requestId`:** a string containing the Netlify request ID; for example, `01FDWR77JMF2DA1CHF5YA6H07C`. * **`server`:** an object containing server metadata with the following property: * **`region`:** the region code where the deployment is running; for example, `us-east1`. * **`site`:** an object containing Netlify site metadata with the following properties: * **`id`:** unique ID for the site; for example, `1d01c0c0-4554-4747-93b8-34ce3448ab95`. * **`name`:** name of the site, its Netlify subdomain; for example, `petsof`. * **`url`:** URL representing the main address to your site. It can be either a Netlify subdomain or your own custom domain if you set one; for example, `https://petsof.netlify.app` or `https://www.petsofnetlify.com`. ### [#](#netlify-global-object) `Netlify` global object The `Netlify` global object exposes the following properties: * **`context`:** the [Netlify-specific `context` object](#netlify-specific-context-object) . This property is scope-dependent The context object is only available when `Netlify.context` is accessed from within the [scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope) of a function handler or one of its child scopes. If accessed from somewhere else, like the global scope, it returns `null`. * **`env`:** an object providing access to [environment variables](/functions/environment-variables/) with the following properties: * **`delete(name)`:** in the context of the invocation, deletes an environment variable with a given name. * **`get(name)`:** returns the string value of an environment variable with a given name; if the environment variable is not defined, `undefined` is returned. * **`has(name)`:** returns a boolean value containing `true` if an environment variable with a given name exists, and `false` otherwise. * **`set(name, value)`:** in the context of the invocation, sets an environment variable with a given name and value. * **`toObject()`:** returns a plain object containing all the environment variables and their values. ### [#](#web-apis) Web APIs Edge Functions support the following Web APIs: * [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console) . When you use `console.log`, the [Edge Functions logs](/edge-functions/get-started/#monitor) include which edge function generated the log message. * [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/atob) * [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa) * [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) * `fetch` * `Request` * `Response` * `URL` * `File` * `Blob` * [TextEncoder](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) * [TextDecoder](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) * [TextEncoderStream](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) * [TextDecoderStream](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) * [Performance](https://developer.mozilla.org/en-US/docs/Web/API/Performance) * [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) * `randomUUID()` * `getRandomValues()` * [SubtleCrypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) * [WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) * [Timers](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) * `setTimeout` * `clearTimeout` * `setInterval` * [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API) * `ReadableStream` * `WritableStream` * `TransformStream` * [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URLPattern) Last updated: November 11, 2024 ← [Get started](/edge-functions/get-started/) [Declarations](/edge-functions/declarations/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with Edge Functions | Netlify Docs This page will help you get started with Edge Functions. It describes how to create, test, deploy, invoke, and monitor your edge functions. [#](#create-an-edge-function) Create an edge function ------------------------------------------------------ To create an edge function to deploy with your site, write a JavaScript or TypeScript file stored in your [edge functions directory](/edge-functions/optional-configuration/#edge-functions-directory) . The default edge functions directory is `YOUR_BASE_DIRECTORY/netlify/edge-functions`. For example, create a function file at `netlify/edge-functions/hello.js`: export default () => new Response("Hello world"); export const config = { path: "/test" }; The file includes two parts: * The default export contains the handler function that runs when you make requests to the edge function. It often contains logic to modify requests and responses. * The `config` export configures the file as an edge function and provides the path on which the edge function will be invoked. In this example, requests to `/test` will trigger the edge function and it will respond with `Hello world`. Beyond the basics * To have nuanced control over the order in which edge functions run, [configure your edge function paths in `netlify.toml`](/edge-functions/declarations/#declare-edge-functions-in-netlify-toml) instead of inline in the function file. * For even faster response times, you can [cache edge function responses](/edge-functions/optional-configuration/#response-caching) . * In case of an error, you can [customize error handling](/edge-functions/optional-configuration/#error-handling) . * Avoid using Edge Functions in your site to request assets from the same site using `fetch()` ### [#](#edge-functions-with-jsx-or-tsx) Edge functions with `.jsx` or `.tsx` You also have the option to use `.jsx` and `.tsx` files for your edge functions. This can be helpful if you want your function to handle server-side rendering (SSR) at the network edge. For example, this `.tsx` file contains the code to stream React SSR at the edge without a meta-framework: import React from "https://esm.sh/react"; import { renderToReadableStream } from "https://esm.sh/react-dom/server"; import type { Config, Context } from "@netlify/edge-functions"; export default async function handler(req: Request, context: Context) { const stream = await renderToReadableStream( Hello

Hello {context.geo.country?.name}

); return new Response(stream, { status: 200, headers: { "Content-Type": "text/html" }, }); } export const config: Config = { path: "/hello", }; Looking for type definitions? For TypeScript, you can import the types for the `Context` and `Config` objects from `@netlify/edge-functions`. The types for the `Request` and `Response` objects are in the global scope. [#](#test-locally) Test locally -------------------------------- You can use [Netlify CLI](/cli/get-started/) to test edge functions locally before deploying them to Netlify. 1. Ensure you have the latest version of Netlify CLI installed: npm install netlify-cli -g 2. Launch [Netlify Dev](/cli/local-development/) to start a development environment that executes edge functions on local requests: netlify dev 3. Visit [localhost:8888/test](http://localhost:8888/test) to execute the `hello` edge function declared for the `/test` route. Changes to edge functions are applied on new requests. 1. Edit `hello.js` to change the `Response`: export default () => new Response("Updated hello!"); export const config = { path: "/test" }; 2. Save your updated function file. 3. Reload [localhost:8888/test](http://localhost:8888/test) and note that the response has changed. To debug edge functions locally, launch Netlify Dev with the `edge-inspect` or `edge-inspect-brk` flag. For details, visit the [CLI docs](https://cli.netlify.com/commands/dev/) . By default, the `geo` location used is the location of your local environment. To override this to a default mock location of San Francisco, CA, USA, use the `--geo=mock` flag. To mock a specific country, use `--geo=mock --country=` with a two-letter country code. For more information about the `--geo` flag, visit the [CLI docs](https://cli.netlify.com/commands/dev/) . [#](#deploy) Deploy -------------------- Use [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) or [Netlify CLI manual deploys](/cli/get-started/#manual-deploys) to deploy your edge functions. Use CLI version 12.2.8 or later for manual deploys Manual deploys of edge functions are supported with Netlify CLI version 12.2.8 or later. Deploys made with older CLI versions will result in deployment errors. If a project has TypeScript and JavaScript edge functions with the same name, for example, `my-function.ts` and `my-function.js`, the TypeScript function is ignored while the JavaScript function is deployed. [#](#invoke) Invoke -------------------- Invoke the deployed production version of your `hello` edge function declared for the `/test` route by accessing `yoursitename.netlify.app/test` Deploys of edge functions are atomic. This means that when a new deploy includes changes to function logic or declarations, the behavior of edge functions in old deploys won’t be impacted. Updates to edge functions move to production only when you publish a new production deploy. [#](#monitor) Monitor ---------------------- To access logs for your production edge functions: 1. In the Netlify UI, for your chosen site, visit **Logs \> Edge Functions** . To access logs for other versions of your edge functions: 1. In the Netlify UI, go to your site’s **Deploys** tab. 2. Find the deploy of interest. 3. Follow the **Edge Functions** link in the deploy detail page header. ### [#](#log-contents) Log contents Netlify provides a log of any console statements output by your edge functions. The log for each console statement includes the name of the edge function that generated the output. #### [#](#date-filter) Date filter By default, the Edge Function log displays a live tail of the latest activity in **Real-time**. You can also filter to review data from a specific time period, including the **Last hour**, **Last day**, **Last 7 days**, or select **Custom** to input a specific date and time range. #### [#](#text-filter) Text filter To make debugging easier, you can filter the logs by edge function name or path. If desired, you can also use [pattern matching](https://www.npmjs.com/package/glob#glob-primer) as part of your query. ### [#](#log-retention) Log retention Logs are retained for at least 24 hours of edge function activity, even after a new edge function deployment. This log retention period increases to 7 days for certain [pricing plans](https://www.netlify.com/pricing/?category=developer#features-edge-functions-log-retention) . ### [#](#log-drains) Log Drains This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. You can connect your edge function logs to third-party monitoring services for analysis using Netlify’s Log Drains feature. Check out our [Log Drains](/monitor-sites/log-drains/) doc for more information. [Optional configuration for edge functions: edge functions directory](/edge-functions/optional-configuration/#edge-functions-directory) Last updated: January 17, 2025 ← [Overview](/edge-functions/overview/) [API](/edge-functions/api/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Create an Edge Functions integration | Netlify Docs It’s possible for frameworks and other tools to dynamically create edge function files and declarations through integrations with the build process. For inspiration, you can explore the [framework-specific examples](/edge-functions/overview/#use-cases) on the Edge Functions overview. The examples highlight different use cases for developing build-generated edge functions. Not a framework author? Create edge functions using the Netlify SDK If you want to build a tool or integration that is unrelated to a framework, we recommend using the [Netlify SDK](https://developers.netlify.com/sdk/get-started/introduction/) instead. You can develop an extension that [injects edge functions](https://developers.netlify.com/sdk/edge-functions/overview/) during the build step for a site and take advantage of the other functionality and features that come with the Netlify SDK. Learn more about [extending Netlify](/integrations/extend-netlify/#general-extensions) . This page will help you learn how to integrate your framework with Edge Functions by generating edge function files and declarations. If your framework’s build process uses Vite, then you can use [the Netlify Edge Functions Vite plugin](https://github.com/netlify/vite-plugin-netlify-edge/) to generate a catch-all edge function file and declaration to serve all requests. [#](#generate-function-files) Generate function files ------------------------------------------------------ To generate edge function files, a framework emits one function file per edge function under `.netlify/edge-functions`. Build-generated edge function files go in this internal directory so as to not interfere with user-created files. The generated function must be compatible with the [Deno](https://deno.land/) runtime. This means the following: * Imports of Node built-in modules must be prefixed with `node:`, for example `import { randomBytes } from "node:crypto"`. * All npm modules must be bundled in the function or changed to use URL imports. You can make a URL import directly in the edge function, for example `import React from "https://esm.sh/react"`, or by using an [import map](/edge-functions/api/#import-maps) . * The generated file should use ES Modules format. * If your bundler supports build targets, it should target `browser` or `worker`. [#](#generate-declarations) Generate declarations -------------------------------------------------- The framework must generate declarations either inline in the function files or in a manifest file at `.netlify/edge-functions/manifest.json`. The manifest file is a JSON object with the same structure as the [`edge_functions` object from `netlify.toml`](/edge-functions/declarations/#declare-edge-functions-in-netlify-toml) . Avoid collisions between integrations If you expect your integration to be used in conjunction with other integrations, avoid overwriting declarations from other integrations and be mindful about declaration order. Declarations for build-generated edge functions support additional properties not available to user-created edge functions. Which additional properties are supported depends on whether the function is declared inline or in `manifest.json`. | Build-generated property | Supported inline | Supported in `manifest.json` | | --- | --- | --- | | `generator` | **✓** | **✓** | | `name` | **✓** | **✓** | | `import_map` | | **✓** | | `version` | | **✓** | These additional properties are for the following purposes: * `generator` is an optional property for noting the integration that generated the edge function. Setting this for your integration helps Netlify’s observability; this does not affect the user experience. We recommend using a value with a format of `@integration-name/plugin-name@1.2.3`, where the plugin version is included at the end. * `name` is an optional property that allows you to set a display name for the function that appears in the Netlify UI. * `import_map` is an optional property for specifying the path to an import map file. If this path is relative, it will be resolved in relation to the manifest file itself. The `manifest.json` declaration example below uses an import map found at `.netlify/edge-functions/import_map.json`, for example: { "imports": { "example": "https://example.com", "netlify:edge": "this will be ignored, netlify: is a reserved prefix" } } Note that any imports prefixed with `netlify:` are reserved, and may be overridden by built-in definitions. * `version` is a required metadata property for `manifest.json` that tracks the version of the manifest format being used. Set this to `1` as demonstrated in the `manifest.json` example below. Here are examples of build-generated declarations: * Loading error: Refresh the page to access this code sample import type { IntegrationsConfig } from "@netlify/edge-functions"; export default async () => new Response("Hello, world!", { headers: { 'cache-control': 'public, s-maxage=3600' } }); export const config: IntegrationsConfig = { path: "/hello", generator: "@cool-framework/nice-plugin@1.0.0", name: "greeting", cache: "manual", onError: "bypass" }; { "functions": [\ {\ "path": "/admin",\ "function": "auth",\ "generator": "@cool-framework/nice-plugin@1.0.0",\ "name": "/admin auth handler",\ "onError": "/unavailable"\ },\ {\ "pattern": "^/dashboard(?:/([^/#\\?]+?))[/#\\?]?$",\ "function": "auth",\ "name": "/dashboard/* auth handler"\ },\ {\ "path": "/blog/*",\ "excludedPath": "/blog/img/*",\ "function": "rewriter",\ "cache": "manual",\ "onError": "bypass",\ },\ {\ "pattern": "/products/(.*)",\ "excludedPattern": "/products/things/(.*)",\ "function": "highlight"\ }\ ], "import_map": "./import_map.json", "version": 1 } [#](#contact-us) Contact us ---------------------------- If you’d like to create an Edge Functions integration for a framework or other developer tool, we encourage you to let us know by reaching out through our [technology partner program](https://www.netlify.com/partners/technology/) so we can help you. We welcome your feedback on building integrations with this feature. Visit our [Forums](https://answers.netlify.com/categories)  to join the conversation about Edge Functions. Last updated: October 2, 2024 ← [Limits](/edge-functions/limits/) [Usage & billing](/edge-functions/usage-and-billing/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Edge Functions declarations | Netlify Docs Unlike regular functions, edge functions aren’t automatically assigned a URL route for you to use as a function endpoint. Instead, you configure your edge functions to run on specific URL patterns. You can configure the edge function path [inline in the function code](#declare-edge-functions-inline) or [in `netlify.toml`](#declare-edge-functions-in-netlify-toml) . [#](#declare-edge-functions-inline) Declare edge functions inline ------------------------------------------------------------------ To configure the edge function path in the same file as the function code, export a `config` object with the following properties: * **`path`:** [`URLPattern`](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API#pattern_syntax) expression on which paths to run the edge function. Must start with `/`, for example `path = "/*"`. * **`excludedPath`:** optional `URLPattern` exclusion to limit the routes matched by `path`. Must also start with `/`, for example `excludedPath = "/*.css"`. Accepts a single string or an array of strings. * **`pattern`:** alternative to the `path` property that allows for regex path matching. * **`excludedPattern`:** optional regex exclusion to limit the routes matched by `pattern`. Accepts a single regex or an array of regex. * **`method`:** optional HTTP methods that should run the edge function. Accepts a string or an array of strings. * **`onError`:** optional setting to control how this function [handles errors](/edge-functions/optional-configuration/#error-handling) . * **`cache`:** optional setting to opt in to [response caching](/edge-functions/optional-configuration/#response-caching) . import type { Config } from "@netlify/edge-functions"; export default async () => new Response("Hello, world!"); export const config: Config = { path: "/test", }; This property can be a string if you want the edge function to run on a single path or an array of strings if you want to configure multiple paths. In both cases, you can use [`URLPattern` expressions](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API#pattern_syntax) to match multiple paths. import type { Config } from "@netlify/edge-functions"; export default async () => new Response("Hello, world!"); export const config: Config = { path: ["/", "/products/*"], }; To limit the paths matched, use `excludedPath`. import type { Config } from "@netlify/edge-functions" export default async () => new Response("Hello, world!") export const config: Config = { path: "/*", excludedPath: ["/*.css", "/*.js"] } This example shows an edge function that runs on all requests except for requests to CSS or JS files. Values for `path` and `excludedPath` must start with `/`, for example `path: "/*"`. [#](#declare-edge-functions-in-netlify-toml) Declare edge functions in `netlify.toml` -------------------------------------------------------------------------------------- If you would like to declare multiple edge functions to run on the same path and customize the order they run in, configure edge function paths in `netlify.toml` instead of inline in the function file. You can use the following properties to configure `edge_functions` in `netlify.toml`: * **`function`:** name of the edge function you’re configuring. * **`path`:** [`URLPattern`](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API#pattern_syntax) expression on which paths to run the edge function. Must start with `/`, for example `path = "/*"`. * **`excludedPath`:** optional `URLPattern` exclusion to limit the routes matched by `path`. Must also start with `/`, for example `excludedPath = "/*.css"`. Accepts a single string or an array of strings. * **`pattern`:** alternative to the `path` property that allows for regex path matching. * **`excludedPattern`:** optional regex exclusion to limit the routes matched by `pattern`. Accepts a single regex or an array of regex. * **`cache`:** optional setting to opt in to [response caching](/edge-functions/optional-configuration/#response-caching) . Each edge function declaration associates one or more site paths or patterns with one function to execute on requests that match the paths or patterns. A single request can execute a chain of edge functions from a series of declarations. A single edge function can be associated with multiple paths across various declarations. Edge functions run in order of declaration in the file, from top to bottom, with the exception that edge functions [configured for caching](/edge-functions/optional-configuration/#response-caching) always run after those that are not. [[edge_functions]] path = "/admin" function = "auth" [[edge_functions]] path = "/admin" function = "injector" cache = "manual" [[edge_functions]] path = "/blog/*" function = "auth" [[edge_functions]] path = "/blog/*" function = "rewriter" [[edge_functions]] pattern = "/products/(.*)" excludedPattern = "/products/things/(.*)" function = "highlight" [[edge_functions]] path = "/*" excludedPath = "/img/*" function = "common" This example shows how both paths and functions can be configured across multiple declarations. * A request for `/admin` would invoke the `auth` function first, then `common`, and finally `injector`. Because it is configured for caching, the `injector` function runs after the other functions even though it is declared between them. * The `auth` function runs for the `/admin` path and any child paths of `/blog`. [#](#declaration-processing-order) Declaration processing order ---------------------------------------------------------------- In general, edge functions are processed in the following order: * edge functions [declared in a configuration file](#declare-edge-functions-in-netlify-toml) run before those [declared inline](#declare-edge-functions-inline) * framework-generated edge functions run before user-created edge functions * edge functions that are not configured for caching run before edge functions that are [configured for caching](/edge-functions/optional-configuration/#response-caching) This section outlines the processing order, and [any exceptions](#processing-order-caveats) , in more detail. When a request is made for a path, such as `/admin`, edge functions run in the following order. Netlify loops through this order twice — the first time running edge functions that are not configured for caching and the second time running edge functions that are configured for caching. 1. Edge functions your framework generates and declares for the path in a configuration file. 2. Edge functions you declare for the path in `netlify.toml`. If you declare multiple edge functions for the same path, they run in order of declaration in the file, from top to bottom. Note that if you declare the same edge function both in `netlify.toml` and inline, Netlify merges the configurations and treats them as inline declarations (refer to step 4). The inline configuration takes precedence for any duplicate fields. 3. Edge functions your framework and enabled integrations generate and declare for the path with inline configuration. 4. Edge functions you declare for the path with inline configuration. If you use inline configuration to declare multiple edge functions for the same path, they run in alphabetical order by function file name. Once all edge functions for the path run, Netlify moves on to evaluate any redirect rules — unless the last [edge function returns a response](#processing-order-caveats) and ends the request chain. A redirect might request a new path that also requires edge functions and the above steps will repeat for that new path. The request chain continues until it eventually serves static content or returns a request from a serverless function. Learn more about [request handling](/edge-functions/api/#request-handling) with edge functions. Use `netlify.toml` to be explicit about edge function order If you want to customize the order in which multiple edge functions run on a given path, we recommend that you [add the declarations to `netlify.toml`](#declare-edge-functions-in-netlify-toml) instead of using inline declarations. ### [#](#processing-order-caveats) Processing order caveats Keep the following caveats in mind as you write and configure your edge functions as these items can interrupt or change the expected order of events: * If the edge function for a path [returns a response](/edge-functions/api/#return-a-response) and terminates the request, redirects for that path do not occur. * If you declare an edge function for the target path of a [static routing rewrite](/routing/redirects/rewrites-proxies/) , the page at the target path will be served but the edge function will not execute for rewritten requests. * If the edge function uses `fetch()` for internal requests or `URL()` for internal rewrites, the command will start a new request chain and Netlify will run any edge functions that match that path first. If you want to request a specific static asset or serverless function with the same internal path, and not re-run the same edge functions, use `context.next()` instead. * If an edge function fails, what happens next depends on its [error handling](/edge-functions/optional-configuration/#error-handling) configuration. Along with considering these caveats, we recommend you also review the [edge functions feature limitations](/edge-functions/limits/#feature-limitations) . Last updated: November 5, 2024 ← [API](/edge-functions/api/) [Optional configuration](/edge-functions/optional-configuration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Edge Functions limits | Netlify Docs Keep the following limitations in mind when working with Edge Functions. [#](#operation-limits) Operation limits ---------------------------------------- Edge functions have limits for their size and the amount of memory and execution time they can use: * **Code size limit:** 20 MB after compression This is the maximum edge function bundle size supported. * **Memory per set of deployed edge functions:** 512 MB * **CPU execution time per request:** 50 ms This tracks all time spent running your scripts. Execution time does not include time spent waiting for resources or responses. * **Response header timeout:** 40 s [#](#invocation-limits) Invocation limits ------------------------------------------ The number of invocations allowed per month varies by team plan. Refer to the [pricing page](https://www.netlify.com/pricing#features-edge-functions) for details. Cached responses from edge functions [configured for caching](/edge-functions/optional-configuration/#response-caching) do not count toward edge function invocations. [#](#feature-limitations) Feature limitations ---------------------------------------------- * If a site has [Netlify’s Split Testing](/site-deploys/split-testing/) enabled, requests to that site will not execute edge functions. * If a site is using [Netlify’s Custom Headers](/routing/headers/) , including [basic authentication headers](/routing/headers/#basic-authentication-headers) , they will not apply to edge functions. * If a site has [prerendering](/site-deploys/post-processing/prerendering/) enabled, it will not apply to paths where the response is served from an edge function. * Unexpected collisions may occur if a site has multiple framework plugins generating edge functions as part of the build. * Edge functions can only [rewrite requests](/edge-functions/api/#return-a-rewrite) to same-site URLs. To fetch content hosted on another Netlify site or an external site, use the [`fetch` Web API](/edge-functions/api/#web-apis) . * Edge functions [configured for caching](/edge-functions/optional-configuration/#response-caching) always shadow static files that actually exist within the site. If an edge function configured for caching is declared to run on `/*` and there’s a `cat.png` static file, a request to `/cat.png` serves the edge function rather than the static file. * There is no local caching for edge functions. Any HTTP headers for cache configuration in an edge function are ignored in local testing. * Netlify Edge Functions is not currently supported as part of our HIPAA-compliant hosting offering. For more information, visit our [Trust Center](https://trust-center.netlify-corp.com) and download our reference architecture for HIPAA-compliant composable sites on Netlify. Learn more about the edge function processing order and caveats Along with the above limitations, we recommend you review our docs on the [declaration processing order](/edge-functions/declarations/#declaration-processing-order) and [caveats](/edge-functions/declarations/#processing-order-caveats) to consider when you create edge functions. Last updated: October 15, 2024 ← [Optional configuration](/edge-functions/optional-configuration/) [Create an integration](/edge-functions/create-integration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Enhanced security with Secrets Controller | Netlify Docs With Secrets Controller, your team can protect and manage environment variable values that require additional layers of security. Flag which environment variables are secrets, and Netlify will apply stricter requirements to them. While Netlify handles all environment variables securely, including encrypted storage, Secrets Controller protects environment variable secrets with an opinionated policy and additional security features. This page outlines the environment variable [secrets policy](#environment-variable-secrets-policy) , how to [manage](#manage-secret-values) environment variable secrets on Netlify, and how [secrets scanning](#secrets-scanning-overview) proactively finds embedded secrets before they’re exposed. [#](#environment-variable-secrets-policy) Environment variable secrets policy ------------------------------------------------------------------------------ Not all environment variables are created equal. Environment variable secrets are sensitive values that would have a detrimental impact on your organization or end users if they were accessed by the wrong party. When you flag environment variables as secret, Netlify’s opinionated policy enforces how these values are accessed and which scopes and features you can use with them. This policy’s design removes options that could allow your team to inadvertently expose secrets and drives your team to be explicit about where secret values should be accessible. Environment variable secrets have the following policy applied to them: * Secret values are write-only. After setting a value using the UI, CLI, or API, you will no longer have access to a human-readable version of the value. * Secret values must be set to explicit [deploy contexts](/environment-variables/overview/#value-per-deploy-context) and [scopes](/environment-variables/overview/#scopes) to avoid unexpected exposure. * After an environment variable is flagged as a secret, you cannot remove the flag to reveal the secret’s value. * Environment variable secrets cannot have the `post processing` [scope](/environment-variables/overview/#scopes) to avoid inadvertently exposing the value through features like [snippet injection](/site-deploys/post-processing/snippet-injection/) . * Only code running on Netlify’s systems can read the original, unmasked values. Your code running on edge functions, serverless functions, build process, etc. will have the original unmasked values of the environment variables. Code running **outside** of Netlify’s hosted systems will have masked versions of the environment variable values. * A value set in the environment variable’s `dev` [deploy context](/environment-variables/overview/#value-per-deploy-context) will **not** have this policy applied to it. As such, only the value for the `dev` deploy context will be unmasked from the UI, CLI, and API. This will allow developers to continue developing with non-secret values that are explicitly for development. None of these policy enforcements can be changed or customized using any form of configuration. Values are masked except in dev context Our UI, CLI, and API won’t return unmasked values of environment variable secrets for any [deploy context](/environment-variables/overview/#value-per-deploy-context) besides `dev`. Using the CLI to do a production build with `netlify build` won’t include the raw, unmasked values. Per the policy, only code running on our systems have access to the unmasked value. [#](#manage-secret-values) Manage secret values ------------------------------------------------ Environment variables that are marked as secret use the same underlying systems for configuring and managing values as other environment variables do. As such, you can use the same flows for [creating](/environment-variables/get-started/#create-environment-variables) and [modifying](/environment-variables/get-started/#modify-and-delete-environment-variables) environment variables. During those flows you can flag variables as secret if the values contain secrets. ### [#](#configure-environment-variable-secrets) Configure environment variable secrets Environment variables are configured through Netlify’s UI, CLI, or API. For each method, you can specify values as secrets: * In the Netlify UI, create and modify variables under **Site configuration \> Environment variables** or under **Team settings \> Environment variables** . For new or existing variables, select `Contains secret values` to flag that an environment variable contains a secret. ![](/images/environment-variables-contains-secret-values.png) * If importing from an `.env` file in the Netlify UI, import all variables first, then select **Options \> Edit** and select `Contains secret values` to flag specific environment variables as secrets. * With the Netlify CLI, use `env:set` with the `--secret` flag to create or modify a site environment variable to be an environment variable secret. Review our [Get Started with Netlify CLI](/cli/get-started/#manage-environment-variables) guide to learn more. * With the Netlify API, use [`createEnvVars`](https://open-api.netlify.com/#tag/environmentVariables/operation/createEnvVars) and [`updateEnvVar`](https://open-api.netlify.com/#tag/environmentVariables/operation/updateEnvVar) to create or modify a site environment variable with the `is_secret` field set to `true`. Review our [Get Started with Netlify API](/api/get-started/#environment-variables) guide to learn more. Environment variable secret values can be created and modified, but they’re not human-readable from the UI, CLI, or API after they’re flagged as secret. To avoid allowing access to secret values, once you flag an environment variable as a secret, this flag cannot be removed. ### [#](#use-secret-values) Use secret values Environment variable secrets are environment variables that have restricted access. Per the secrets policy, only code running on Netlify will receive the raw, unmasked values. Within your code, you [use environment variable secrets](/environment-variables/get-started/#use-environment-variables) the same way as you use traditional environment variables. Only values that are configured for the `dev` [deploy context](/configure-builds/file-based-configuration/#deploy-contexts) are human readable from the UI, CLI, and API. This allows developers to use development context environment variables locally. All other contexts have restricted access based on our [environment variables secrets policy](#environment-variable-secrets-policy) . [#](#secrets-scanning-overview) Secrets scanning overview ---------------------------------------------------------- When you explicitly mark which environment variables have secret values, Netlify proactively protects your team with secrets scanning. This process scans your repository code and build output files for the existence of secret values. If the scanning process finds secret values, it fails the build and adds the location of the secret values to the deploy log. Secrets scanning happens before publish and deploy steps to ensure secret values aren’t exposed publicly or stored in files that are downloadable by members of your Netlify team. It’s easy to inadvertently add code that injects secrets into server and client code. When this happens, it can go undetected a long time after the initial leak. Secrets exposure can cost your company a lot of time, money, and customer trust. Secrets scanning is an essential security layer to protect your teams and end users. Do I need Netlify secrets scanning if I’m scanning secrets on my repo? We recommend using all security tools available to keep your team and users safe. While repository-specific secret scanning is a helpful tool for scanning secrets that your repository is aware of, there are secret values on Netlify that your code repo is unlikely to discover. For example, database passwords or server secret keys provided at runtime are unlikely to be in your code repository’s list of secrets. ### [#](#secrets-scanning-process) Secrets scanning process Secrets scanning searches all files that are in your site’s build, including code pulled from the repo and files generated during the build. To reduce the chances of false positives, secrets scanning only searches for environment variable secret values that have more than four characters and are not booleans. In the common build steps that inject data into files or bundles, you don’t always use the plaintext version of those values. Given this, Netlify’s secret scanning will search for different permutations of values in the following formats: * plaintext * base64-encoded * URI-encoded In addition to the different encodings, any values that appear to be a multi-line string will also have their full value searched as a single line string and in multi-line form. For example, with an environment variable secret such as `SECRET_ALPHABET="abc\ndef\nghi"` the scanner will find four matches in the following file. abc\ndef\nghi <- plaintext YWJjCmRlZgpnaGk= <- base64 encoded abc%0Adef%0Aghi <- uri encoded abc def ghi <- the multi line value ### [#](#configure-secrets-scanning) Configure secrets scanning When using environment variable secrets, secrets scanning is enabled automatically. Netlify will begin scanning on the next build after an environment variable is marked as secret. You may configure how the scanning works by setting any of the following environment variables at the site or team level. Set these environment variables to some or all deploy contexts to customize secrets scanning for your site or team needs: * **`SECRETS_SCAN_ENABLED`:** default is `true`. Set to `false` to entirely disable secrets scanning protections for the site/team. * **`SECRETS_SCAN_OMIT_KEYS`:** default is _empty_. Set to a comma separated list of key names that should **not** be scanned for within this site or team. * **`SECRETS_SCAN_OMIT_PATHS`:** default is _empty_. Set to a comma separated list of file paths (relative to the repository root) that should **not** be scanned within this site or team. Values can be substrings of paths or use a glob pattern format. When you set the values at the team level, you may use site-specific environment variable values to override the team level settings. Review the environment variable [overrides](/environment-variables/overview/#overrides) section to understand how to apply these settings to meet your team’s needs. [#](#enhancing-the-sensitive-variable-policy) Enhancing the sensitive variable policy -------------------------------------------------------------------------------------- Netlify provides all customers who are using public repositories the ability to keep sensitive variables private and away from untrusted deploys through the [sensitive variable policy](/environment-variables/get-started/#sensitive-variable-policy) . This feature provides you with the ability to protect sensitive variables on sites that use **public** repositories. To provide the sensitive variable policy capabilities, Netlify attempts to detect sensitive values based on heuristics such as the key name and the shape of the value. Secrets Controller is designed to offer advanced security around explicitly flagged secrets. When using Secrets Controller with a public repository, the sensitive variable policy applies to these environment variables: * any variables that Netlify automatically detects as sensitive, even if they are not specifically flagged with `Contains secret values` * any variables explicitly flagged as sensitive by selecting `Contains secret values` With the sensitive variable policy, you can choose how to manage access to sensitive values for deploys from your public repo. Explicitly marked secret values are included in this policy. Last updated: November 12, 2024 ← [Get started with environment variables](/environment-variables/get-started/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with environment variables | Netlify Docs Netlify offers multiple ways to securely create, update, and use environment variables for your sites. This page outlines how to [create and manage](#create-environment-variables) site environment variables and shared environment variables, how to [use environment variables](#use-environment-variables) once they are declared, how to work with [`.env` files](#work-with-env-files) on Netlify, and how to configure your site’s [sensitive variable policy](#sensitive-variable-policy) . [#](#create-environment-variables) Create environment variables ---------------------------------------------------------------- You can create environment variables with the Netlify UI, CLI, or API, or with a Netlify configuration file. Once you create environment variables, build and deploy your site for the additions to take effect. ### [#](#create-variables-with-the-netlify-ui-cli-or-api) Create variables with the Netlify UI, CLI, or API When you create environment variables using the Netlify UI, CLI, or API, they are set and securely stored on Netlify. This means you can avoid committing any sensitive values to your repository. The Netlify UI reflects any changes made using the CLI or API and vice versa. You can create [site environment variables](#site-environment-variables) and [shared environment variables](#shared-environment-variables) . Be aware that variables set in a Netlify [configuration file](#create-variables-with-a-netlify-configuration-file) override variables set with the Netlify UI, CLI, or API. #### [#](#site-environment-variables) Site environment variables There are three ways to create site environment variables: * In the Netlify UI, create site variables under **Site configuration \> Environment variables** . You can create variables individually or import variables from a `.env` file. * With the Netlify CLI, use `env:set` to create a site environment variable, and `env:import` to import from a `.env` file. Review our [Get Started with Netlify CLI guide](/cli/get-started/#manage-environment-variables) to learn more. * With the Netlify API, use `createEnvVars` to create a new site environment variable. Review our [Get Started with Netlify API guide](/api/get-started/#environment-variables) to learn more. If a shared environment variable and a site environment variable exist with the same key name and scope, the site environment variable’s contextual values take precedence in each deploy context. In addition, variables set in the `netlify.toml` will override those with the same key set in the Netlify UI. Review the [overrides](/environment-variables/overview/#overrides) section to learn more. #### [#](#shared-environment-variables) Shared environment variables This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. There are two ways to create shared environment variables: * In the Netlify UI, create shared variables under **Team settings \> Environment variables** . * With the Netlify API, use `createEnvVars` to create a new shared environment variable. Review our [Get Started with Netlify API guide](/api/get-started/#environment-variables) to learn more. Variables set at the team level are shared by all sites owned by the team. Only Team Owners can read and access shared variables through the Netlify UI, CLI, and API. If a shared environment variable and a site environment variable exist with the same key name and scope, the site environment variable’s contextual values take precedence in each deploy context. Review the [overrides](/environment-variables/overview/#overrides) section to learn more. ### [#](#create-variables-with-a-netlify-configuration-file) Create variables with a Netlify configuration file You can create site environment variables with a Netlify [configuration file](/configure-builds/file-based-configuration/) stored in your repository. This file-based configuration method allows you to set different environment variables for different [deploy contexts](/configure-builds/file-based-configuration/#deploy-contexts) . Note that you can’t set scopes for variables declared using the configuration file. All variables declared using this method have the **Builds** and **Post processing** scope. Since `netlify.toml` is stored in your repository, we recommend setting sensitive values with the [Netlify UI, CLI, or API](#create-variables-with-the-netlify-ui-cli-or-api) instead, where possible. Here is an example of how to declare variables in `netlify.toml`: # Production context: all deploys from the Production branch # set in your site’s Branches settings in the UI will inherit # these settings. You can define environment variables # here but we recommend using the Netlify UI for sensitive # values to keep them out of your source repository. [context.production] publish = "output/" command = "make publish" environment = { NODE_VERSION = "14.15.3" } # Here is an example of how to define context-specific # environment variables. Be mindful when using this # option and avoid committing sensitive values to public # source repositories. [context.deploy-preview.environment] NOT_PRIVATE_ITEM = "not so secret" # Branch Deploy context: all deploys that are not from # a pull/merge request or from the Production branch # will inherit these settings. [context.branch-deploy.environment] NODE_ENV = "development" # Dev context: environment variables set here # are available for local development environments # run using Netlify Dev. These values can be # overwritten on branches that have a more specific # branch context configured. [context.dev.environment] NODE_ENV = "development" # Specific branch context: all deploys from # this specific branch will inherit these settings. [context.staging.environment] # “staging” is a branch name NODE_ENV = "development" Variables set in a configuration file override variables set with the Netlify UI, CLI, or API. [#](#modify-and-delete-environment-variables) Modify and delete environment variables -------------------------------------------------------------------------------------- There are multiple ways to edit or delete environment variables that you set using the Netlify UI, CLI, or API. Note that only Team Owners can read and modify shared variables. Need to export your variables? Review the [export variables for your `.env`](#export-variables-for-env-files) section below. To apply environment variable changes, build and deploy. Environment variable changes require a build and deploy to take effect. ### [#](#update-variables-with-the-netlify-ui) Update variables with the Netlify UI To edit or delete site environment variables: 1. Navigate to **Site configuration \> Environment variables** for site environment variables or to **Team settings \> Environment variables** for shared environment variables. 2. Filter the list of variables by key name to find the variable you want to modify. Then, select the variable from the list to expand the variable details. 3. Select **Options \> Edit** or **Options \> Delete** and then follow the prompts to complete your change. ### [#](#update-variables-with-the-netlify-cli-or-api) Update variables with the Netlify CLI or API You can use the Netlify CLI to update site environment variables and the Netlify API to update both site and shared environment variables. * With the Netlify CLI, use `env:set` to update a site environment variable, `env:import` to import from an updated `.env` file, and `env:unset` to delete a site environment variable and all of its contextual values. * With the Netlify API, use `updateEnvVar` to update all values for an environment variable, `setEnvVarValue` to update or create a single value for an existing variable, `deleteEnvVar` to delete a variable and all of its values, or `deleteEnvVarValue` to delete a specific value. Review our [Get Started with Netlify CLI guide](/cli/get-started/#manage-environment-variables) and our [Get Started with Netlify API guide](/api/get-started/#environment-variables) to learn more. [#](#use-environment-variables) Use environment variables ---------------------------------------------------------- Once you’ve created environment variables, there are many different ways you can use them: * Use environment variables [during the build process](/configure-builds/environment-variables/#access-variables) — such as in the `netlify.toml`, to install private npm modules, in Node.js script files, and in build plugins. * Use a custom script or framework-specific variables to [copy values into the site](/frameworks/environment-variables/#embed-variable-values-in-the-site-build) code during the build process, for use while your site runs. * Use a [function](/functions/environment-variables/#access-environment-variables) to access values during runtime. * Use variables for spam prevention with [forms](/forms/spam-filters/#custom-recaptcha-2) or to specify [signed proxy redirects](/routing/redirects/rewrites-proxies/#signed-proxy-redirects) . * Use [snippet injection](/site-deploys/post-processing/snippet-injection/#environment-variables) to access values during post-processing. If you inject values into the site using a build script or snippet injection, make sure to only include non-sensitive values. [#](#work-with-env-files) Work with `.env` files ------------------------------------------------- When you build on Netlify, the build system does not read `.env` files. Instead, you can [import the variables](#import-variables-from-env-files) from your `.env` file into Netlify before you build. This way your environment variables remain secure and out of your shared repository. For local builds, the Netlify CLI will read the `.env` files you have stored in your local environment. These variables will therefore be available to your site for use. Using Netlify configuration variables in `.env` files for your framework If your framework references your `.env` file during the build step and you need to use Netlify’s configuration or read-only variables, review our docs on [how to add Netlify variable values to your `.env`](/frameworks/environment-variables/#env-files-and-netlify-variables) . ### [#](#import-variables-from-env-files) Import variables from `.env` files We recommend that you import the variables from your `.env` file into Netlify so that they are available during the build step. You can import environment variables using the [Netlify UI](#import-variables-with-the-netlify-ui) or the [Netlify CLI](#import-variables-with-the-netlify-cli) . Environment variables in a `.env` file are formatted as key-value pairs. That is, a list of variables where each variable is on a new line and is formatted with the key name, followed by an equals sign, and then the value. A single `.env` file represents the variables for a specific environment. Here is an example of a production `.env` file: YOUR_API_KEY=a production secret NODE_VERSION=16 NODE_ENV=production To learn more about the parsing rules the Netlify UI and CLI follow for `.env` imports, review the [dotenv docs](https://www.npmjs.com/package/dotenv#what-rules-does-the-parsing-engine-follow) . #### [#](#import-variables-with-the-netlify-ui) Import variables with the Netlify UI With the Netlify UI, you can import a `.env` file to your site environment variables or shared environment variables. Imported variables are merged with existing environment variables. If existing variables have any of the key names in the `.env` file you’re importing, you can specify how Netlify should handle those conflicts. 1. Navigate to **Site configuration \> Environment variables** for site environment variables or to **Team settings \> Environment variables** for shared environment variables. 2. Select **Add a variable \> Import from a .env file** . 3. Copy the contents of your `.env` file into the form. 4. Set the **Scopes** and **Deploy contexts** to use for these variables and values. All variables imported through this form submission will have the same scope and deploy context settings. 5. If the variables to import include keys that conflict with existing variables, a **Merge strategy** section will appear in the form. You can choose to either **Skip conflicts** and ignore any new values, or **Update conflicts** and set new [contextual values](/environment-variables/overview/#value-per-deploy-context) for the existing variables. 6. Select **Import variables** to add the variables. Scope changes may be ignored for environment variable conflicts Scope changes only apply to existing variables when you select **All deploy contexts** to apply the same value for use across all deploy contexts. If an environment variable already exists with the same key name and you’re adding specific contextual values with this import, changes to the scope will be ignored. #### [#](#import-variables-with-the-netlify-cli) Import variables with the Netlify CLI Use the Netlify CLI command `env:import` to import environment variables from a `.env` file. As the CLI works on a site level, you can only use it to import site environment variables. The imported variables are set to all scopes and with the same value for all deploy contexts. By default, environment variables you import are merged with any existing ones on Netlify. If you would rather remove all existing variables and replace them with what is in the imported file, use the `--replace-existing` flag. For example: # Warning: using the --replace-existing flag will delete all # existing variables and keep only those imported from the .env netlify env:import .env --replace-existing ### [#](#export-variables-for-env-files) Export variables for `.env` files If you would like to export variables set and stored on Netlify, you can export them in `.env` format using the [Netlify UI](#export-variables-with-the-netlify-ui) or the [Netlify CLI](#export-variables-with-the-netlify-cli) . #### [#](#export-variables-with-the-netlify-ui) Export variables with the Netlify UI As `.env` files include variables for a specific environment, you can export environment variables from the Netlify UI for each deploy context. 1. Navigate to **Site configuration \> Environment variables** for site environment variables or to **Team settings \> Environment variables** for shared environment variables. 2. Select a deploy context in the **Context** filter. 3. Select the clipboard icon to copy the filtered list in `.env` format to your clipboard. 4. Paste the results in your local `.env` file or [import the variables](#import-variables-with-the-netlify-ui) into another Netlify site. ![](/images/environment-variables-export-env-ui.png) #### [#](#export-variables-with-the-netlify-cli) Export variables with the Netlify CLI You can export environment variables for each deploy context using the Netlify CLI command `env:list --plain`. With the `--plain` flag, the CLI outputs the results in plain text format that you can copy into your `.env` file locally. By default, only those values set for the `Local development (Netlify CLI)` deploy context are output. To export the values from another deploy context, use the `--context` flag. For example, to export all of the `production` deploy context values in `.env` format, use this command: # list the production deploy context values in .env format netlify env:list --plain --context production # list the production deploy context values in .env format # and pipe results into a .env file netlify env:list --plain --context production > .env [#](#sensitive-variable-policy) Sensitive variable policy ---------------------------------------------------------- Some environment variables you may want to keep private. This can pose a challenge for sites connected to public repositories, where anyone can trigger a Deploy Preview by making a pull/merge request from a fork. Deploys from people, automated services, or bots from outside your Netlify team ([unrecognized authors](/site-deploys/overview/#deploy-permissions) ) are always treated as untrusted deploys. Site members’ deploys are trusted Git provider accounts connected to a site member can trigger deploys without restrictions, even from forks. If a site member’s deploys are being treated as untrusted, make sure they [connect their Git provider account](/accounts-and-billing/user-settings/#connect-your-git-provider-accounts) to their Netlify user. Netlify allows you to control whether untrusted deploys can access sensitive environment variables by choosing a sensitive variable policy. The policy is only available for sites connected to public repositories, and it includes the following options: * **Require approval** (default)**:** policy that requires all untrusted deploys to be approved by a [site member](/accounts-and-billing/team-management/manage-team-members/#manage-site-member-access) before the build can start. Deploys awaiting approval can be found at the top of the deploy list on the site **Deploys** tab. Accepting or rejecting a deploy request does not affect the status of the originating pull/merge request. ![deploy list entry for an untrusted deploy request, including the Deploy Preview number, Git author username, link to review changes, and buttons to accept or reject.](/images/environment-variables-sensitive-variable-policy-deploy-request.png) * **Deploy without sensitive variables:** policy that lets untrusted deploys build automatically, but variables identified as sensitive will not be passed to the deploy environment. You can adjust your site code to accommodate builds without sensitive variables present, or you can declare “public” variable values for the `deploy-preview` context. * **Deploy without restrictions:** policy that treats untrusted deploys like any other Deploy Preview, building automatically with all variables present. Use this option only if you are not concerned about the potential exposure of any of your site’s environment variables. By default, when Netlify detects potentially sensitive environment variables in your site configuration, we automatically apply the default setting above, requiring approval for all untrusted deploys. For customers using Netlify’s [Secrets Controller](/environment-variables/secrets-controller) feature, all environment variables marked as `Contains secret values` are included in the sensitive variable policy enforcement. You can change this policy at any time in **Site configuration \> Environment variables \> Site policies** . ![](/images/environment-variables-overview-sensitive-variable-policy.png) Sensitive variable policy for GitHub Enterprise Server or GitLab self-managed Because [GitHub Enterprise Server and GitLab self-managed instances](/git/self-hosted-git/) enable a higher degree of access control, we treat all repositories from these instances as private. This means you won’t be able to set a sensitive variable policy for a site linked to a GitHub Enterprise Server or GitLab self-managed repository. #### [#](#deploy-request-notifications) Deploy request notifications When your sensitive variable policy is set to require approval for all untrusted deploys, you can add deploy notifications to trigger when a deploy request is **pending**, **approved**, or **rejected**. Visit the [deploy notifications doc](/site-deploys/notifications/) to learn more about the types of notifications available and how to configure them. Last updated: November 29, 2024 ← [Overview](/environment-variables/overview/) [Secrets Controller](/environment-variables/secrets-controller/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Edge Functions usage and billing | Netlify Docs You can check your team’s Edge Functions service usage under **Billing \> Current services \> Plan details** . This shows your current usage level and tracks the following metric: * **Invocations:** metric that counts each time an edge function is invoked on a site owned by your team during the current billing period. If a [cached response](/edge-functions/optional-configuration/#response-caching) is available and served, no edge function invocation is made and no usage is incurred against your Edge Functions allotment. For paid plans, [Edge Functions pricing](https://www.netlify.com/pricing/?category=developer#features-edge-functions) is metered on a team basis and scales with usage. When usage reaches the plan limit, the team will automatically add an extra usage package. Free tier accounts are also metered based on usage and [have a limit](/accounts-and-billing/billing-faq/#free-tier-limits) . [#](#more-usage-and-billing-resources) More usage and billing resources ------------------------------------------------------------------------ * [Billing FAQ](/accounts-and-billing/billing-faq/) * [Billing](/accounts-and-billing/billing/) Last updated: December 2, 2024 ← [Create an integration](/edge-functions/create-integration/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Optional configuration for edge functions | Netlify Docs This document describes optional configuration settings you can use for more control over how your edge functions are built and executed. [#](#edge-functions-directory) Edge functions directory -------------------------------------------------------- The default edge functions directory is `YOUR_BASE_DIRECTORY/netlify/edge-functions`. You can specify a custom edge functions directory with the `edge_functions` key in `netlify.toml`. For example, to use the `my-custom-directory` directory, add the following to the `build` section in `netlify.toml`: [build] edge_functions = "my-custom-directory" The path is an absolute path relative to the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. To help keep your site secure, make sure your edge functions directory is outside of your [publish directory](/configure-builds/overview/#definitions-1) so that your source files aren’t deployed as part of your site. [#](#response-caching) Response caching ---------------------------------------- You have the option to cache edge function responses for even faster response times. When the edge function gets a request and a cached response is available, we will serve the response directly from the edge cache. This bypasses the edge function invocation altogether and serves the response from as close to the user as possible for fast response times. ### [#](#when-to-use-caching) When to use caching If an edge function is [used as an endpoint](/edge-functions/api/#return-a-response) to return a response directly and that response can be reused for different requests from multiple clients, we recommend that you configure the edge function for caching to further optimize performance. If, however, the edge function is [used as middleware](/edge-functions/api/#modify-a-response) to inform routing or transform requests / responses, we recommend that you do not configure the edge function for caching. This guarantees that the edge function will be invoked for every single request and can generate unique responses for different requests. Here are some example use cases and recommendations: * **Server-side rendering should use caching.** Imagine an edge function tasked with server-side-rendering a page and producing the HTML output. Since the output is the same for all requests, the initial response can be reused for future requests. * **Personalization should not use caching.** Imagine an edge function that rearranges the order of items on a products page based on a set of preferences captured in a cookie. Since the outcome is unique to the specific client that is making the request, the logic for reading the cookie and rearranging the items needs to be invoked for every single request. ### [#](#configure-an-edge-function-for-caching) Configure an edge function for caching There are two parts to configuring an edge function for caching: * [Opt in to caching](#opt-in-to-caching) by setting the `cache` property to `manual` * [Customize cache behavior](#customize-cache-behavior) by specifying HTTP headers If you do one part but not the other, your edge function responses will not be cached. They will use the default behavior and every request to the edge function will invoke the function for a fresh response. Keep the [Edge Functions feature limitations](/edge-functions/limits/#feature-limitations) in mind when configuring caching. #### [#](#opt-in-to-caching) Opt in to caching You can set the `cache` property to `manual` inline in the function code, or in `netlify.toml`. For inline configuration, use the `config` object in your edge function file. import type { Config } from "@netlify/edge-functions" export default async () => new Response("Hello, world!") export const config: Config = { cache: "manual", path: "/hello" } For file-based configuration, use the `edge_functions` property in `netlify.toml`. [[edge_functions]] cache = "manual" path = "/hello" function = "hello-world" #### [#](#customize-cache-behavior) Customize cache behavior You must specify caching headers inline in the function code. import type { Context, Config } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { return new Response("Hello world", { headers: { 'cache-control': 'public, s-maxage=3600' } }); } ### [#](#supported-headers) Supported headers We support the following HTTP headers for edge functions configured for caching: * **[`Cache-Control`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) **, **`CDN-Cache-Control`**, and **`Netlify-CDN-Cache-Control`:** visit our [caching](/platform/caching/) doc to learn more about how Netlify handles these headers, including their order of precedence and supported directives. * **[`Expires`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires) :** store and reuse the cached response until this date/time. Overridden by `max-age` and `s-maxage`. * **[`Vary`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary) ** and **`Netlify-Vary`:** visit our [caching](/platform/caching/) doc to learn more about how Netlify handles these headers, including supported instructions and guidance on when to use which option. By default, [cached responses respect atomic deploys](/platform/caching/#automatic-invalidation-with-atomic-deploys) . This means that `s-maxage`, `max-age`, and `Expires` are voided by a new deploy in an identical [deploy context](/site-deploys/overview/#deploy-contexts) (such as the same Deploy Preview number, or the same branch deploy). For example, imagine an edge function in published production deploy `A` that is configured for caching with `"cache-control": "public, s-maxage=3600"`. If deploy `B` becomes the new published production deploy five minutes later, we discard any responses previously cached. Even though the previously cached responses are configured to be stored and reused for one hour, they are discarded since they belong to a different deploy. [#](#error-handling) Error handling ------------------------------------ Because edge function failures can have different consequences in different contexts, you can customize what happens after an edge function errors. By default, when an edge function errors, we stop the request chain and serve a [generic error page](https://edge-functions-examples.netlify.app/error) . ![Error page with error message and next steps for site visitors and site owners.](/images/edge-functions-error.png) Alternatively, you can choose to serve a rewrite to a specific custom path or have the request chain continue. ### [#](#when-to-customize-error-handling) When to customize error handling If an edge function is responsible for critical business logic, errors should block access (_fail closed_). Depending on your audience and content, the default error page may suffice or you may want to rewrite to a custom path. If, however, the edge function is used for progressive enhancement, errors should allow access (_fail open_). In these cases letting the request proceed to serve baseline essential content is a better user experience than stopping the request and serving an error page. Here are some example use cases for edge functions and recommendations for error handling: * **Authentication on an internal site should serve the default generic error page.** If the edge function errors and the user cannot be authenticated, stopping the request chain and serving an error page protects your gated content. In the case of an internal site, the default error page is helpful to your engineering team because it provides a link to the edge function logs for troubleshooting. * **Authentication on a customer-facing site should rewrite to a custom path.** If the edge function errors and the user cannot be authenticated, stopping the request chain and serving a custom error page protects your gated content. In the case of a customer-facing site, rewriting to a custom path allows you to provide a branded error message with more specific guidance to your site visitors to keep them engaged and get them unblocked. * **Localization that is nice to have but not business-critical should be bypassed.** If the edge function errors and content can’t be translated based on the user’s location, it’s okay to let the request proceed and serve untranslated content. In this case, though the user experience isn’t ideal, the user can still engage with your content by using an external translation tool to read unlocalized text. ### [#](#configure-error-handling-for-an-edge-function) Configure error handling for an edge function To customize error handling, use the `onError` property inline in the function code. Supported values are: * **`fail`:** serve a generic error page. This is the default if `onError` is not specified. * **`/YOUR_CUSTOM_PATH`:** rewrite to the specified same-site path. Must start with `/`. The path is served without invoking any edge functions that may be declared for that path. * **`bypass`:** skip the erroring edge function and continue the request chain. * Loading error: Refresh the page to access this code sample import { Config } from "@netlify/edge-functions" export default async () => { throw new Error("error"); }; export const config: Config = { path: "/hello", onError: "fail" } import { Config } from "@netlify/edge-functions" export default async () => { throw new Error("error"); }; export const config: Config = { path: "/hello", onError: "/unavailable" } import { Config } from "@netlify/edge-functions" export default async () => { throw new Error("error"); }; export const config: Config = { path: "/hello", onError: "bypass" } Last updated: January 16, 2024 ← [Declarations](/edge-functions/declarations/) [Limits](/edge-functions/limits/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Forms usage and billing | Netlify Docs You can check your Forms service usage under **Forms \> Usage and configuration \> Usage** . This shows your current usage level and tracks your usage of the following services: * **Submissions**: This counts the total number of verified [form submissions](/forms/submissions/) across all forms on your site during this billing period. * **File uploads**: This tracks the total storage size of all [files uploaded](/forms/submissions/#file-uploads) through verified form submissions to your site during the current billing period. For paid plans, [Forms pricing](https://www.netlify.com/pricing/) is metered on a per-site basis and scales with usage. When usage reaches a level limit, the site will automatically upgrade to the next level or package. Free tier accounts are also metered based on usage and [have a limit](/accounts-and-billing/billing-faq/#free-tier-limits) . [#](#change-levels) Change levels ---------------------------------- Any team member with the ability to change the configuration for your site can also change levels for services on that site. To do this, go to **Forms \> Usage and configuration \> Usage** , and select **Change level**. Level fees will be prorated and charged at the end of the billing cycle, to the team’s payment method. [#](#more-usage-and-billing-resources) More usage and billing resources ------------------------------------------------------------------------ * [Billing FAQ](/accounts-and-billing/billing-faq/) * [Billing](/accounts-and-billing/billing/) Last updated: November 12, 2024 ← [Troubleshooting tips](/forms/troubleshooting-tips/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Edge Functions overview | Netlify Docs Edge Functions connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. Using TypeScript and JavaScript, you can modify network requests to localize content, serve relevant ads, authenticate users, personalize content, redirect visitors, and much more. Edge Functions also support a new generation of edge-first web frameworks allowing your entire app to run at the edge, dramatically increasing performance in many cases. All this dynamic processing happens in a secure runtime based on [Deno](https://deno.land/)  directly from the worldwide network edge location closest to each user for fast response times. Plus, you have the option to cache edge function responses for even faster response times. With Netlify, your edge functions are version-controlled, built, and deployed along with the rest of your Netlify site. This eliminates overhead and brings the power of Deploy Previews and rollbacks to your edge functions. [#](#use-cases) Use cases -------------------------- To learn more about what’s possible with Edge Functions, explore the following. Reference examples of common patterns: * [Transform responses with content includes](https://edge-functions-examples.netlify.app/example/include) * [Set custom HTTP request headers](https://edge-functions-examples.netlify.app/example/set-request-header) * [Localize content with geolocation](https://edge-functions-examples.netlify.app/example/localized-content) * [Rewrite responses from another URL](https://answers.netlify.com/t/new-syntax-for-rewrites-in-edge-functions/88257) * [A/B tests using cookies](https://edge-functions-examples.netlify.app/example/abtest) * [Calculate responses with WebAssembly](https://edge-functions-examples.netlify.app/example/wasm) Framework-specific examples: * [Astro](https://astro.build/blog/netlify-edge-functions/) * [Eleventy](https://www.11ty.dev/blog/eleventy-edge/) * [Hydrogen](https://github.com/netlify/hydrogen-template) * Next.js: [React Server Components](https://github.com/netlify/next-react-server-components) , [Edge Middleware](https://github.com/netlify/next-edge-middleware) * [Nuxt 3](https://nitro.unjs.io/deploy/providers/netlify) * [Remix](https://github.com/netlify/remix-edge-template) * [SvelteKit](https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify) * [Qwik](https://qwik.builder.io/deployments/netlify-edge/) [#](#documentation) Documentation ---------------------------------- To learn how to create your own edge functions, check out the documentation. * [**Get started**](/edge-functions/get-started/) **:** basic hello world example that covers testing and debugging locally, deploying, invoking, and monitoring an edge function. * [**Edge Functions API**](/edge-functions/api/) **:** introduction to key concepts and a full endpoint reference. * [**Declarations**](/edge-functions/declarations/) **:** configuration details and processing order. * [**Optional configuration**](/edge-functions/optional-configuration/) **:** options for more control over how your edge functions are built and executed, such as configuring edge functions for caching. * [**Limits**](/edge-functions/limits/) **:** operation limits for the runtime environment and feature limitations. * [**Create an integration**](/edge-functions/create-integration/) **:** guidance for framework authors making integrations for developers to use. * [**Usage and billing**](/edge-functions/usage-and-billing/) **:** how to monitor your invocation usage. [#](#more-edge-functions-resources) More Edge Functions resources ------------------------------------------------------------------ * [Full library of reference examples](https://edge-functions-examples.netlify.app/) * [Netlify blog: Edge Functions posts](https://www.netlify.com/blog/tags/netlify-edge-functions/) * [Environment variables and functions](/functions/environment-variables/) * [Use the Netlify Blobs API in an edge function](/blobs/overview/) [#](#feedback) Feedback ------------------------ We welcome your feedback on this feature. Visit our [Forums](https://answers.netlify.com/categories)  to join the conversation about Edge Functions. Last updated: September 11, 2024 [Get started](/edge-functions/get-started/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Spam filters | Netlify Docs All form submissions are filtered for spam [using Akismet](https://www.netlify.com/blog/2019/02/12/improved-netlify-forms-spam-filtering-using-akismet/) , an industry leader in spam detection. Only submissions that pass the filter are included in your form’s **Verified submissions** list in the [form submissions UI](/forms/submissions/#form-submissions-ui) . Submissions flagged as spam by Akismet can be found by switching to your form’s **Spam submissions** list. Tip You can [change the state of a submission](/forms/submissions/#change-a-form-submission-s-state) from spam to verified or vice versa. [#](#extra-spam-prevention) Extra spam prevention -------------------------------------------------- For additional protection to help prevent abuse of your forms, you can add a [honeypot field](/forms/spam-filters/#honeypot-field) , a [reCAPTCHA 2](/forms/spam-filters/#recaptcha-2-challenge) , or both. We automatically reject submissions that do not pass these challenges. Junk submissions caught by a honeypot field or reCAPTCHA 2 won’t even be included in your form’s spam submissions. The **Submissions** page for a form will indicate if it has any extra spam prevention enabled. ### [#](#honeypot-field) Honeypot field “Honeypot” fields are hidden form fields that lure bot users into completing a field that human users can’t detect. A form submitted with a completed honeypot field can be safely rejected because only a bot would detect and complete the field. You can alert Netlify to a hidden honeypot field by adding a `netlify-honeypot` attribute to your `
` with the name of your hidden field. Then make sure that field is present in the form, but hidden via CSS or JavaScript. Here’s an example:

When Netlify parses the static HTML during post-processing, the build system automatically strips the `netlify-honeypot` attribute from the `
` tag, leaving the honeypot input field in place. In the example above, if a spambot enters any value in `bot-field`, Netlify will quietly reject the form submission. If you [submit your form with AJAX](/forms/setup/#submit-javascript-rendered-forms-with-ajax) , make sure that the honeypot field name is included in the body of the POST request. This happens automatically if you use `FormData()` to encode the body of the request. ### [#](#recaptcha-2-challenge) reCAPTCHA 2 challenge If you would like to add a [reCAPTCHA 2 challenge](https://developers.google.com/recaptcha/) to a form, Netlify can include one for you, or you can [add your own](/forms/spam-filters/#custom-recaptcha-2) . #### [#](#netlify-provided-recaptcha-2) Netlify-provided reCAPTCHA 2 To have Netlify provide the CAPTCHA: 1. Add a `data-netlify-recaptcha="true"` attribute to your `` tag. 2. In the place where you’d like the CAPTCHA to appear, add an empty `
` element inside your form with the same `data-netlify-recaptcha="true"` attribute. When your site is published, the form will include the necessary HTML to render the CAPTCHA. Here’s an example:

When a visitor submits the form, our servers will validate the CAPTCHA server-side. If the validation fails, we’ll redirect the visitor back to the same page and reject the form submission. You can include one Netlify-provided reCAPTCHA 2 challenge per page. To use multiple challenges on one page, add [custom reCAPTCHA 2](#custom-recaptcha-2) . #### [#](#custom-recaptcha-2) Custom reCAPTCHA 2 You can also add your own reCAPTCHA 2 code in your site and let Netlify validate that form submissions come from a human. This is useful if you want to have more control over your validations, if you use a JavaScript library to inject a CAPTCHA in your forms, or if you need more than one CAPTCHA on a page. In this case, Netlify needs your reCAPTCHA 2 site key and secret for validating that the captcha response is correct. You can provide these values with [environment variables](/environment-variables/overview) in your site configuration. Use `SITE_RECAPTCHA_KEY` to set your site key, and use `SITE_RECAPTCHA_SECRET` to set the secret provided by reCAPTCHA 2. To set up a custom reCAPTCHA: 1. [Sign up for a reCAPTCHA API key pair](http://www.google.com/recaptcha/admin) and follow the instructions for adding reCAPTCHA to your site. This typically involves adding a script before the closing `` of your HTML template, and a snippet at the end of the `
` where you want the reCAPTCHA widget to appear. 2. Create the following environment variables for your site [using the Netlify UI, CLI, or API](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) : * A variable with the key name of `SITE_RECAPTCHA_KEY` and a value set to your reCAPTCHA API site key. If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include both **Builds** and **Runtime**. * A variable with the key name of `SITE_RECAPTCHA_SECRET` and a value set to your reCAPTCHA API secret key. If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Runtime**. 3. Add a `data-netlify-recaptcha="true"` attribute to the HTML form that has the custom reCAPTCHA widget.
The Netlify servers will check the submissions from that form, and accept them only if they include a valid `g-recaptcha-response` value. If you [submit your form with AJAX](/forms/setup/#submit-javascript-rendered-forms-with-ajax) , make sure the `g-recaptcha-response` field is included in the body of the POST request. This happens automatically if you use `FormData()` to encode the body of the request. Last updated: June 26, 2023 ← [Setup](/forms/setup/) [Submissions](/forms/submissions/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Form notifications | Netlify Docs Stay updated on the latest form submissions and trigger your own custom workflows with form notifications. Send form notifications to email, webhooks, or a Slack workspace. Set up notifications for verified submissions to a specific form or for all verified submissions to any form on your site. To send form notifications to email or webhooks: * Go to **Site configuration \> Notifications \> Emails and webhooks \> Form submission notifications** . To send form notifications to a Slack workspace: * Check out our docs on setting up the [Netlify App for Slack](/slack-app/) . [#](#slack-notifications) Slack notifications ---------------------------------------------- Surface form submissions in Slack with just a few clicks. Learn more in the [Netlify App for Slack docs](/slack-app/) . [#](#email-notifications) Email notifications ---------------------------------------------- By default, form notification emails are sent from formresponses@netlify.com, and any replies to a notification go to that address. To respond to a form submitter, you need to enter their address manually. We recommend that you add an `` with `name="email"` to your form. This sets the `Reply-to` value on the form notification email, allowing you to reply directly to the form submitter without manually entering their email. ### [#](#customize-the-email-subject-line) Customize the email subject line You can completely customize the email subject line in the email notifications that Netlify sends when someone submits a form from your site. If you don’t customize the email subject line in the Netlify UI or in your Netlify HTML form, then your form will automatically apply a default email subject line. You can customize the email subject line from the Netlify UI or in the HTML markup for your form. We recommend that you choose one way to customize your email subject line since whatever you set in the HTML form overrides the settings in the Netlify UI. As an overview of these options, consider the following: * To reference anything programmatically in the email subject line and keep the subject line version controlled, set the email subject line in your HTML form. Check out [the example HTML forms](/forms/notifications/#example-html-forms) . * To manage your form’s email subject line in the Netlify UI, set the email subject line at **Site configuration \> Notifications \> Emails and webhooks \> Form submission notifications** . To change the email subject line, additionally select **Options > Edit notifications**. You many need to remove any email subject line specified in your forms’ HTML to keep the email subject line you specify in the Netlify UI. You can also apply predefined variables to your email subject line, such as `%{formName}` , `%{siteName}`, or `%{submissionId}`. For example, your email subject line can be `New lead from %{formName} (%{submissionId})`. Use these variables in the HTML form or in the Netlify UI. ### [#](#example-html-forms) Example HTML forms This example sets the email subject line for your form notification to `Sales inquiry from mysitename.netlify.app`:

The `Reply-to` email is whatever value the form submitter entered in the `Your Email:` field. This example uses [predefined variables](/forms/notifications/#customize-the-email-subject-line) to dynamically set your email subject line to `New lead from %{formName} (%{submissionId})`:

Older form or want to remove \[Netlify\] from subject line? The example above assumes your form was created after May 5, 2023. Forms created before this date will have an automated `[Netlify]` prefix in your email subject line. To remove `[Netlify]` from the subject line of your form submission email notification, check out our [`[Netlify]` prefix removal docs](/forms/notifications/#remove-netlify-prefix-from-your-email-subject-line) . For greater control of form-triggered emails, or to connect other services, you can use the Netlify app on [Zapier](#zapier-integrations) or [n8n](#n8n-integrations) . ### [#](#remove-netlify-prefix-from-your-email-subject-line) Remove `[Netlify]` prefix from your email subject line Forms created before May 5, 2023 included `[Netlify]` as a default and automated prefix in the email subject line. Now you can remove the `[Netlify]` prefix from your email subject line and completely customize your email subject line. To remove `[Netlify]` from the email subject line of your form submission notification email: * If you have an email subject line specified in your HTML form, decide whether to [modify your existing email subject line in the HTML form](/forms/notifications/#remove-netlify-prefix-in-the-html-form) or opt to [use the Netlify UI](/forms/notifications/#customize-the-email-subject-line) instead. * If you do not have an email subject line specified in your HTML form, you can just [edit the form notification settings in the Netlify UI](/forms/notifications/#customize-the-email-subject-line) . All new forms will not include `[Netlify]`. #### [#](#remove-netlify-prefix-in-the-html-form) Remove `[Netlify]` prefix in the HTML form To remove the `[Netlify]` prefix from your subject line and keep using the HTML form to specify the subject line, add the `data-remove-prefix` attribute to your HTML form’s email subject input field:
In this example, your email subject line is `Sales inquiry from mysitename.netlify.app`. This removes `[Netlify]` from your new form notification emails. Learn more about this update in this [support Forums post](https://answers.netlify.com/t/customize-the-email-subject-line-for-form-submission-notifications/91534) . Note that if you have an HTML form with a different email subject specified, that subject will take precedence over any updates you make to the email subject line in the Netlify UI. [#](#zapier-integrations) Zapier integrations ---------------------------------------------- Netlify is available on Zapier, where you can connect Netlify with over 1,000 other applications. You can set up a “Zap” action to be triggered when there is a verified form submission on your website. You can [find out more on our blog](https://www.netlify.com/blog/2018/11/07/automate-your-netlify-sites-with-zapier/) , or use one of the templates below to get started: [#](#n8n-integrations) n8n integrations ---------------------------------------- Netlify is available on [n8n](https://n8n.io/) , an open source tool that allows you to connect Netlify with other applications. By using one of n8n’s Netlify nodes, you can create your own automated workflow. To get started, you can use the [Netlify node](https://n8n.io/integrations/netlify/) , [Netlify Trigger node](https://n8n.io/integrations/netlify-trigger/) , or you can use the existing workflow below: Last updated: October 2, 2024 ← [Submissions](/forms/submissions/) [Troubleshooting tips](/forms/troubleshooting-tips/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Form troubleshooting tips | Netlify Docs This document provides troubleshooting tips for setting up a form. If you have questions that aren’t answered here, visit our Support Forums to get more advice about [how to debug your form](https://answers.netlify.com/t/common-issue-how-to-debug-your-form/92) . [#](#custom-success-page) Custom success page ---------------------------------------------- If you’re having trouble using the form `action` to customize the [success page](/forms/setup/#success-messages) , try linking to your custom success page from somewhere on the same page as the form. Use the same exact path in your test link as you’re trying to use for the `action` attribute, and make sure the link works there before digging further into your form. [#](#extra-spam-prevention) Extra spam prevention -------------------------------------------------- If you’re adding a [honeypot field](/forms/spam-filters/#honeypot-field) or [reCAPTCHA 2 challenge](/forms/spam-filters/#recaptcha-2-challenge) , you can check the form detail page to confirm whether or not the **Extra spam prevention** has been successfully enabled. [#](#missing-submissions) Missing submissions ---------------------------------------------- Here are some common causes and solutions for missing form submissions. ### [#](#test-submissions-flagged-as-spam) Test submissions flagged as spam If you’re sending test [submissions of your form](/forms/submissions/) and not finding them in your **Verified submissions** list, it’s possible they’re getting [flagged as spam by Akismet](/forms/spam-filters/) . Use the menu above the list to switch to **Spam submissions** and then recheck for your tests. To avoid having your tests flagged as spam in the first place, we recommend you * enter a real email address instead of a fake one such as test@test.com. * write some full sentences in any textareas rather than a few nonsense characters. * spread out the rate of submissions from a single IP address. ### [#](#form-detection-disabled) Form detection disabled If you’re not finding new form submissions in your **Verified submissions** list for updated or newly added forms, ensure that [form detection](/forms/setup/#automatic-form-detection) is enabled for your site. If this is your first time enabling form detection, go to **Forms** to turn on the setting. If you previously enabled form detection, go to **Forms \> Usage and configuration \> Form detection** to review the setting. Once you [enable](/forms/setup/#enable-form-detection) or [re-enable form detection](/forms/setup/#re-enable-form-detection) , make sure you redeploy your site. Once you redeploy, Netlify will automatically scan your deploys for forms and will accept form submissions. [#](#missing-data-from-old-submissions) Missing data from old submissions -------------------------------------------------------------------------- If you recently changed the name or type of a form field, data for that field from old submissions will no longer appear in the Netlify UI. This is because the Netlify UI only shows the form fields and data that correspond to the last deployed version of your form. Fortunately, all of your previous submission data are still available through the Netlify API. You can request form data with the [listFormSubmissions endpoint](https://open-api.netlify.com/#tag/submission/operation/listFormSubmissions) . If you would like to review the data from both the old and current form fields in the Netlify UI, we recommend that you mark old form fields as “hidden” instead of removing or replacing them entirely. [#](#next-js-runtime-v5-support) Next.js Runtime v5 support ------------------------------------------------------------ If you’re using Netlify Forms with Next.js Runtime v5, you need to extract your form definitions to a dedicated static HTML file and make sure that the form submission uses AJAX rather than full-page navigation. Refer to [the Next.js v5 breaking changes](/frameworks/next-js/overview/#v5-breaking-changes) for more information. Last updated: October 23, 2024 ← [Notifications](/forms/notifications/) [Usage & billing](/forms/usage-and-billing/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Environment variables overview | Netlify Docs Netlify environment variables allow you to configure your site’s build and functionality based on different parameters and deploy contexts. This page describes the different environment variable options at Netlify, their override rules, limitations, and how to get started. [#](#environment-variables-at-netlify) Environment variables at Netlify ------------------------------------------------------------------------ Netlify offers a few different options for how you can [configure](/environment-variables/get-started/#create-environment-variables) and [use](/environment-variables/get-started/#use-environment-variables) environment variables: * There are two types of environment variables: shared environment variables that are available to all sites in your team and site environment variables set for specific sites. Site environment variables can override shared environment variables. * Environment variables have a key name, [scope](#scopes) , and one or more [contextual values](#value-per-deploy-context) . At Netlify, an environment variable’s contextual value is the value set for a specific [deploy context](/site-deploys/overview/#deploy-contexts) . By default, environment variables are available to all scopes and have the same value for all deploy contexts. * You can mark environment variables as `Contains secret values` for additional access restrictions and security features with our [Secrets Controller](/environment-variables/secrets-controller) feature. * Netlify provides a set of [configuration variables](/configure-builds/environment-variables/#netlify-configuration-variables) and [read-only variables](/configure-builds/environment-variables/#read-only-variables) for use during the build process. * There is a [sensitive variable policy](/environment-variables/get-started/#sensitive-variable-policy) that you can configure to control access to sensitive variables for sites connected to public repositories. * You can use the Netlify [CLI](/cli/get-started/#manage-environment-variables) and the Netlify [API](/api/get-started/#environment-variables) to access and modify environment variables stored on Netlify. Any updates made using the CLI or API will be reflected in the Netlify UI. * The Netlify UI offers the ability to review environment variables at a glance and to filter variables by key name, scope, and deploy context. Once you add a deploy context filter, you can use the Netlify UI to [copy the filtered data in `.env` format](/environment-variables/get-started/#export-variables-with-the-netlify-ui) . * All environment variable changes made in the Netlify UI, CLI, and API are captured in the [team audit log](/accounts-and-billing/team-management/team-audit-log/) so you can keep track of any variables that you and other team members create, modify, or delete. For example, you can use the Netlify UI, CLI, or API to configure an environment variable that only functions can use and that has one value for use with production and another value for Deploy Previews: * Key: `API_KEY` * Scope: `Functions` * Values: * Production: `a production secret` * Deploy Previews: `a non-production secret` ![Example list of environment variables with scopes and contextual values in the Netlify UI](/images/environment-variables-overview-environment-variables-list.png) [#](#configuration-options-and-limitations) Configuration options and limitations ---------------------------------------------------------------------------------- Netlify supports two ways of setting and storing environment variables — with the Netlify UI, CLI, or API, or with a Netlify configuration file. Depending on which method you use, there are different environment variable options available. We recommend using the Netlify UI, CLI, or API, where possible, to avoid storing sensitive values in your repository. | | [Netlify UI, CLI, or API](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) | [Netlify configuration file](/environment-variables/get-started/#create-variables-with-a-netlify-configuration-file) | | --- | --- | --- | | Stored on Netlify | ✓ | | | Stored in your repository | | ✓ | | Set site environment variables | ✓ | ✓ | | Set shared environment variables | ✓ | | | Set a single value that is available to all deploy contexts | ✓ | ✓ | | Set a different value for each deploy context | ✓ | ✓ | | Set specific scopes for variables | ✓ | | | Available to [builds](/configure-builds/environment-variables/) | ✓ | ✓ | | Available to [Functions](/functions/overview/)
, [Edge Functions](/edge-functions/overview/)
, and [On-demand Builders](/configure-builds/on-demand-builders/) | ✓ | | | Available to [snippet injection](/site-deploys/post-processing/snippet-injection/) | ✓ | ✓ | | Available to [forms](/forms/spam-filters/#custom-recaptcha-2) | ✓ | | | Available to [signed proxy redirects](/routing/redirects/rewrites-proxies/#signed-proxy-redirects) | ✓ | | | Changes captured in [team audit log](/accounts-and-billing/team-management/team-audit-log/) | ✓ | | ### [#](#value-per-deploy-context) Value per deploy context By default, environment variables have one value that is available to all [deploy contexts](/site-deploys/overview/#deploy-contexts) . Alternatively, you can choose to set a different value for each of the following deploy contexts: * `Production`: for the main site’s deployment. * `Deploy Previews`: for previews we build for your pull/merge requests. * `Branch deploys`: for all branch deploys. You can override this value on individual branches using a `Branch` value, outlined below. * `Dev server`: for any [dev servers](/platform/dev-server) running for that site. By default, this context inherits all values defined for `Local development`. * `Local development`: for local development using the Netlify CLI. You also have the option to set a `Branch` value for use on a specific branch, such as `staging` or `docs`. The `Branch` value will be used for deploy permalinks, Deploy Previews, and branch deploys for the specified branch. At Netlify, the value set for a specific deploy context is sometimes referred to as the environment variable’s contextual value. The ability to set contextual values opens up more possibilities for how you can leverage environment variables on Netlify. For example: * Analytics or experiments you wish to run only on the live site in production * Modifying which CMS environment to use for production versus Deploy Previews * Adding new functionality that requires a specific token and testing the change in a Deploy Preview before it goes live ### [#](#scopes) Scopes This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. By default, environment variables apply to all scopes. Alternatively, you can limit variables to one or more of the following scopes: * **Builds**: includes [site builds](/configure-builds/overview/) . You can use environment variables with this scope during the build step to configure your site, framework, and function builds. Learn more about [build environment variables](/configure-builds/environment-variables/) . * **Functions**: includes [Functions](/functions/overview/) , [Edge Functions](/edge-functions/overview/) , and [On-demand Builders](/configure-builds/on-demand-builders/) . You can use environment variables with this scope to securely provide sensitive values for your functions to use while they run – values such as API keys and tokens. Learn more about [environment variables and functions](/functions/environment-variables/) . * **Runtime**: includes [forms](/forms/spam-filters/#netlify-provided-recaptcha-2) and [signed proxy redirects](/routing/redirects/rewrites-proxies/#signed-proxy-redirects) . You can use environment variables with this scope to provide security tokens for your forms and redirects to use while your site runs in the browser. * **Post processing**: includes [snippet injection](/site-deploys/post-processing/snippet-injection/) . You can use environment variables with this scope as Netlify serves your site in the browser – for example, you may add [data for the analytics script](/site-deploys/split-testing/#use-snippet-injection-for-more-flexibility) that you inject for split testing. By making variables available only to the scopes that need them, such as builds only or functions only, you can more tightly control where Netlify uses your sensitive data and avoid hitting any value [limits](#limitations) for certain scopes. ### [#](#overrides) Overrides There are a few overrides to be aware of: * Environment variables set in `netlify.toml` override environment variables set with the same key name using the Netlify UI, CLI, and API. * If a site environment variable and a shared environment variable exist with the same key name, the site environment variable takes precedence for each of its scopes and for each deploy context it has a value for. * If you set environment variable values for different deploy contexts, the [deploy context precedence rules](/configure-builds/file-based-configuration/#deploy-contexts) apply. For example, if you use the Netlify UI to declare the following environment variables: | Variable type | Key | Scope | Contextual values | | --- | --- | --- | --- | | Shared | GREETING | all | * Production: `hello`
* Deploy Previews: `konnichiwa`
* Branch:staging: `bonjour` | | Site | GREETING | builds | * Production: `aloha`
* Branch deploys: `guten tag` | The following values will be used for `GREETING`: | Scope | Deploy context | Contextual value | | --- | --- | --- | | Builds | Production | `aloha` | | Functions | Production | `hello` | | Builds | Deploy Previews | `konnichiwa` | | Builds | Branch deploy for branch `staging` | `bonjour` | | Builds | Branch deploys for all other branches except for `staging` | `guten tag` | | Functions | Local development (Netlify CLI) | `undefined` | ### [#](#limitations) Limitations The following limitations apply for environment variables: * **Reserved variable names**. Netlify offers some read-only environment variables for [builds](/configure-builds/environment-variables/#read-only-variables) and [functions](/functions/environment-variables/#netlify-read-only-variables) . The keys used by these read-only variables are reserved by Netlify. You can’t override these variables or their values. * **Accepted characters**. Keys can only include alphanumeric characters and underscores, and the first character must be a letter. For example, `KEY1` is valid but `1KEY` and `_KEY1` are not valid. * **Character and value limits**. Keys can contain up to 255 characters, and values can contain up to 5,000 characters. Values used by functions should fall within AWS’s [environment property limits](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) . * **Shared variable access limitations**. Only Team Owners can read and edit shared environment variable values. [#](#get-started) Get started ------------------------------ We recommend you start using environment variables at Netlify by taking the following steps: 1. Add and set [site environment variables](/environment-variables/get-started/#site-environment-variables) or [shared environment variables](/environment-variables/get-started/#shared-environment-variables) with the Netlify UI. 2. Once you add a few variables, try to access or update your variables with the [Netlify CLI](/cli/get-started/#manage-environment-variables) or the [API endpoints](/api/get-started/#environment-variables) . 3. Update your site code or configuration to [use environment variables](/environment-variables/get-started/#use-environment-variables) during the build process, in functions, and more. 4. If your site is connected to a public repository, review your [sensitive variable policy settings](/environment-variables/get-started/#sensitive-variable-policy) to control whether untrusted deploys can access sensitive environment variables. 5. Check the [team audit log](/accounts-and-billing/team-management/team-audit-log/) to review changes as you work with environment variables. [#](#more-environment-variables-resources) More environment variables resources -------------------------------------------------------------------------------- * [Build environment variables](/configure-builds/environment-variables/) * [Environment variables and functions](/functions/environment-variables/) * Verified Support Guide on [how to use build environment variables](https://answers.netlify.com/t/support-guide-using-environment-variables-on-netlify-correctly/267) * [Get started guide - use environment variables with functions](/get-started/#use-environment-variables) * [Injecting environment variable values in your `netlify.toml` file](/configure-builds/file-based-configuration/#inject-environment-variable-values) * [Environment variables for different deploy contexts](/site-deploys/overview/#deploy-contexts) * [Configure your deploy environment](/site-deploys/manage-deploys/#configure-your-deploy-environment) * [Deploy to Netlify button - require or set environment variables](/site-deploys/create-deploys/#require-or-set-environment-variables) * [Environment variables for signed proxy redirects](/routing/redirects/rewrites-proxies/#signed-proxy-redirects) * [Gatsby environment variables](/frameworks/gatsby/?gatsby-version=adapters#environment-variables) * [Hugo version environment variable](/frameworks/hugo/#hugo-version) * [Node.js functions runtime settings](/functions/optional-configuration/?fn-language=js#node-js-version-for-runtime-2) [Create environment variables](/environment-variables/get-started/#create-environment-variables) [Create environment variables with the Netlify UI, CLI, or API](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) [Site environment variables](/environment-variables/get-started/#site-environment-variables) [Shared environment variables](/environment-variables/get-started/#shared-environment-variables) [Create environment variables with a Netlify configuration file](/environment-variables/get-started/#create-variables-with-a-netlify-configuration-file) [Sensitive variable policy](/environment-variables/get-started/#sensitive-variable-policy) [Use environment variables](/environment-variables/get-started/#use-environment-variables) Last updated: November 12, 2024 [Get started](/environment-variables/get-started/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Astro on Netlify | Netlify Docs Astro is a framework that focuses on performance — by default, it ships zero client-side JavaScript. When needed, Astro adds partial hydration to make use of the [Islands Architecture](https://docs.astro.build/en/concepts/islands/) . You can also use your favorite framework (like Vue, React, or Svelte) inside your Astro projects. Explore an Astro site [Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/netlify-templates/astro-platform-starter) Prefer to explore working examples first? Return to this guide to understand key features and for extra setup help. * [Demo repo](https://github.com/netlify-templates/astro-platform-starter) * [Demo site](https://astro-platform-starter.netlify.app/) * [Edge Functions example](https://astro-platform-starter.netlify.app/edge/not-australia/) * [Image CDN example](https://astro-platform-starter.netlify.app/image-cdn/) * [Blobs example](https://astro-platform-starter.netlify.app/blobs/) * [Revalidation example](https://astro-platform-starter.netlify.app/revalidation) [#](#key-features) Key features -------------------------------- These features provide important benefits for Astro projects, including those built by and deployed with Netlify. * **Partial hydration.** Astro is biased towards minimal JavaScript but occasionally projects need to include some interactive components too. With partial hydration, Astro enables you to use JavaScript just for those components and not entire pages. * **Server islands (experimental).** To balance performance and personalization, use a server island to add dynamic content to a page with static HTML components. Learn more about server islands in this [working example](https://server-islands.com/) , this [Astro blog](https://astro.build/blog/astro-4120/) , or our [developer guide](https://developers.netlify.com/guides/how-astros-server-islands-deliver-progressive-rendering-for-your-sites/) . * **Image optimization.** Astro’s [`` component](https://docs.astro.build/en/guides/images/#images-in-astro-files) , backed by [Netlify Image CDN](#netlify-image-cdn) , automatically displays optimized versions of your images. * **Page-level custom headers**. Astro gives developers full control of caching headers with [`Astro.response.headers`](https://docs.astro.build/en/guides/server-side-rendering/#astroresponseheaders) , which allow developers to gain the benefits of Netlify’s durable cache and Incremental Static Regeneration (ISR). Learn more from examples in our [Astro guide](https://developers.netlify.com/guides/how-to-do-advanced-caching-and-isr-with-astro/) or from our framework-agnostic [Advanced Caching guide](https://developers.netlify.com/guides/advanced-caching-made-easy/) . * **Use one or more frameworks.** When you use Astro, you can continue using your favorite frameworks. You can mix and match multiple framework components inside your Astro files — letting you choose what works best for your project. * **Server-side rendering**. Server-side rendering (SSR) with Astro enables you to do things like track login states and render data without shipping client-side JavaScript. [#](#netlify-integration) Netlify integration ---------------------------------------------- When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Astro, Netlify provides a suggested build command and output directory: `astro build` and `dist`. You can deploy an Astro project to Netlify in several ways: the Netlify UI, the Netlify CLI, or a `netlify.toml` file in your repo. For manual configuration, check out the [typical build settings](/frameworks/#astro) for Astro. ### [#](#netlify-image-cdn) Netlify Image CDN When deploying your Astro applications to Netlify, the Astro `` component automatically uses [Netlify Image CDN](/image-cdn/overview/) to transform images on demand without impacting build times. Netlify Image CDN also handles content negotiation to use the most efficient image format for the requesting client. To transform a source image hosted on another domain, you must first configure allowed domains in your `astro.config.mjs` file. Visit the [Astro docs](https://docs.astro.build/en/guides/images/#authorizing-remote-images) to learn more. ### [#](#astro-server-side-rendering) Astro server-side rendering Astro SSR enables you to add useful functionality to your app like implementing login sessions and rendering data from an API called dynamically. SSR is powered by [Netlify Functions](/functions/overview/) . #### [#](#deploy-an-astro-app-with-ssr-on-netlify) Deploy an Astro app with SSR on Netlify To deploy an Astro app with SSR enabled on Netlify, you need to use the `@astro/netlify` adapter and make some changes in your Astro configuration file. Check out the [Astro guide for Netlify](https://docs.astro.build/en/guides/deploy/netlify/#adapter-for-ssr) for step-by-step help on enabling SSR for your Astro app. Learn more in the [`@astrojs/netlify` adapter repository](https://github.com/withastro/adapters/tree/main/packages/netlify) . ### [#](#edge-functions-examples) Edge Functions examples Use [Edge Functions](/edge-functions/overview/) to build fast, personalized web experiences with an open runtime standard at the network edge. Learn by example with these Edge Functions resources: * [Working example on Astro demo site](https://astro-platform-starter.netlify.app/edge/not-australia/) * [Edge Functions reference examples](https://edge-functions-examples.netlify.app/) For more details on using Edge Functions, check out: * [Edge Functions documentation](/edge-functions/overview/) [#](#more-resources) More resources ------------------------------------ * [Typical Astro build settings](/frameworks/#astro) * [Netlify Blog: Astro posts](https://www.netlify.com/tags/astro/) * [Astro + Netlify Starter repo](https://github.com/netlify-templates/astro-platform-starter) * [Astro documentation](https://docs.astro.build/en/getting-started/) * [Connect JavaScript client](/connect/access-data/#use-the-connect-client) - the recommended library for querying Connect data layer APIs in Astro cached SSR sites. Last updated: November 6, 2024 ← [Frameworks overview](/frameworks/#astro) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Form submissions | Netlify Docs This document covers features you can use to manage your form submissions and recommendations for sensitive data. To learn how you can be made aware of new form submissions, visit our [form notifications](/forms/notifications/) page. [#](#form-submissions-ui) Form submissions UI ---------------------------------------------- You can find all submissions to your Netlify forms in your site’s **Forms** tab. Select a form name from the **Active forms** list to access the submissions for that form. By default, only verified submissions are listed. You can switch to [spam submissions](/forms/spam-filters/) using a menu above the list. Note If you’ve [disabled form detection](/forms/setup/#disable-form-detection) , Netlify will not process any new or changed forms in your HTML files during deploys. You can still access form submissions for any preexisting and unchanged forms, but any newly deployed or updated forms won’t support new submissions while form detection is disabled. ### [#](#export-form-submissions-to-csv) Export form submissions to CSV You can export verified form submissions to a CSV file. From the **Forms** tab, select the form you want to export, then select **Download as CSV** near the top of the form detail page. ### [#](#change-a-form-submission-s-state) Change a form submission’s state You can change the state of a submission from spam to verified or vice versa. To do so, check the box next to each submission title to select one or multiple submissions and then use the **Mark as spam** or **Mark as verified** button. ### [#](#delete-a-form-submission) Delete a form submission You can delete both verified submissions and spam submissions. To do so, check the box next to each submission title to select one or multiple submissions. After you select the submissions, a red **Delete submission** button will become available. When you select **Delete submission**, you’ll be prompted to confirm the deleting action. Once you confirm, your selected submissions will be deleted permanently. ### [#](#delete-a-form) Delete a form You can delete a form and all of its submissions by selecting **Delete form**. You’ll be prompted to confirm the deleting action. Once you confirm, future submissions to the form will result in a `404` error and previous submissions will no longer be available. You may want to [export form submissions to CSV](/forms/submissions/#export-form-submissions-to-csv) before you delete your form. [#](#api-endpoints) API endpoints ---------------------------------- You can use the [API](/api/get-started/#forms) to get verified/spam submissions, delete submissions, delete forms, and more. [#](#file-uploads) File uploads -------------------------------- When a form is submitted with one or more [file uploads](/forms/setup/#file-uploads) , a link to each uploaded file will be included in the form submission details. These are accessible in the Netlify app, in email notifications, in CSV exports, and from our API. [#](#manage-sensitive-form-data) Manage sensitive form data ------------------------------------------------------------ Form submission data is securely stored in our user database. If your form collects personally identifiable information (PII), we recommend that you actively manage the data by exporting form submissions and deleting them regularly. Forms that include file uploads with personally identifiable information should use the [Very Good Security](https://www.netlify.com/integrations/very-good-security/) integration to protect this data. [#](#automatic-sanitization) Automatic sanitization ---------------------------------------------------- Our form handling automatically sanitizes form submissions to keep your site and business secure. Any code that gets submitted through Netlify Forms, such as ` If someone tries to submit this through your form, we transform the code into the following to make it harmless: <script>alert('Surprise!')</script> [#](#form-triggered-functions) Form-triggered functions -------------------------------------------------------- You can integrate your forms with Netlify Functions by triggering a serverless function when a form submission is verified. Find out more in the [Functions](/functions/trigger-on-events/) docs. Last updated: March 21, 2024 ← [Spam filters](/forms/spam-filters/) [Notifications](/forms/notifications/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Forms setup | Netlify Docs Netlify’s serverless form handling allows you to manage forms without extra API calls or additional JavaScript. Once enabled, the built-in form detection feature allows our build system to automatically parse your HTML at deploy time, so there’s no need for you to make an API call or include extra JavaScript on your site. To get started, enable [automatic form detection](#automatic-form-detection) and then add a `netlify` attribute to your [HTML form](#html-forms) . Wondering how Netlify handles form submissions? Visit our [form submissions](/forms/submissions/) doc to learn more about the form submissions UI, API endpoints, and more. [#](#automatic-form-detection) Automatic form detection -------------------------------------------------------- If you would like Netlify to automatically manage your form submissions, you need to enable form detection. ### [#](#enable-form-detection) Enable form detection To enable form detection for your site: 1. In the Netlify UI, go to **Forms** . 2. Select **Enable form detection**. Starting with your next site deploy, Netlify will automatically scan your deploys for forms that require submission handling. If you previously used Netlify Forms and disabled automatic form detection, follow the steps to [re-enable form detection](#re-enable-form-detection) and start accepting submissions again. ### [#](#disable-form-detection) Disable form detection You may want to disable form detection if your site doesn’t have forms anymore or if you decide not to use Netlify to manage your forms. Disabling form detection will reduce post processing and may speed up deploys. To disable form detection for your site: 1. In the Netlify UI, go to **Forms \> Usage and configuration \> Form detection** . 2. Select **Disable form detection**. 3. A confirmation prompt will appear. To continue, enter the name of your site and select **Disable form detection**. Starting with your next site deploy, Netlify will no longer scan your deploys for forms and will disable [form submission](/forms/submissions/#form-submissions-ui) handling for any new or updated forms. Warning Disabling form detection is intended only for sites that don’t use Netlify Forms. If your site does use Netlify Forms, we recommend removing forms from your site code or altering your code to handle submissions by other means before disabling form detection. ### [#](#re-enable-form-detection) Re-enable form detection If you previously used Netlify Forms and disabled automatic form detection, follow these steps to re-enable form detection: 1. In the Netlify UI, go to **Forms \> Usage and configuration \> Form detection** . 2. Select **Enable form detection**. 3. Redeploy your site. Once you redeploy your site, Netlify will automatically scan your deploys for forms and start accepting submissions again. [#](#html-forms) HTML forms ---------------------------- Once you [enable form detection](#enable-form-detection) , add an HTML form to your site with a `data-netlify="true"` or a `netlify` attribute in the `
` tag. Deploy your site with that form included and you can start receiving [submissions](/forms/submissions/) in your Netlify site admin panel. Your form’s `name` attribute determines what we call the form in the Netlify UI. If you have more than one form on a site, each form should have a different `name` attribute. Here’s an example of how to use the `data-netlify="true"` attribute or the `netlify` attribute in your form: * Loading error: Refresh the page to access this code sample

When Netlify parses the static HTML for a form you’ve added, the build system automatically strips the `data-netlify="true"` or `netlify` attribute from the `
` tag and injects a hidden input named `form-name`. In the resulting HTML that’s deployed, the `data-netlify="true"` or `netlify` attribute is gone, and the hidden `form-name` input’s `value` matches the `name` attribute of `` like this: ### [#](#submit-html-forms-with-ajax) Submit HTML forms with AJAX You don’t have to, but you can submit static HTML forms using AJAX. A static HTML form submitted this way must have `data-netlify=true` or a `netlify` attribute inside its `` tag. For an example of how to set these attributes, review the [HTML forms](#html-forms) section. Here’s an AJAX form submission example using the `fetch` API for a static HTML form: const handleSubmit = event => { event.preventDefault(); const myForm = event.target; const formData = new FormData(myForm); fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(formData).toString() }) .then(() => console.log("Form successfully submitted")) .catch(error => alert(error)); }; document.querySelector("form").addEventListener("submit", handleSubmit); Requirements for the request: * The body of the request must be URL-encoded. In the above example, the form is passed to a `FormData` constructor. That object is then encoded using the `URLSearchParams` constructor and converted to a string. Note that Netlify Forms does not support JSON form data at this time. * If the form accepts alphanumeric data only, the request should include the header `"Content-Type": "application/x-www-form-urlencoded"`. If the form accepts [file uploads](/forms/setup/#file-uploads) , including a `Content-Type` header is not recommended. [#](#javascript-forms) JavaScript forms ---------------------------------------- You don’t need to include extra JavaScript on your site to use Netlify Forms. But, if you want to, you can use JavaScript to render a form client-side. You can also submit JavaScript-rendered forms over AJAX. ### [#](#forms-for-next-js-or-ssr-frameworks) Forms for Next.js or SSR frameworks If you’re using a pure JavaScript form or SSR (Server Side Rendering), you must include an HTML form that meets this [HTML form criteria](https://answers.netlify.com/t/support-guide-form-problems-form-debugging-404-when-submitting/92#p-141-form-handling-works-automatically-for-html-forms-that-meet-the-following-requirements-2) , including all the input tags with the same names as the JavaScript form. For instructions and examples specific to Next.js 13.5 and above, visit [breaking changes for the Next.js runtime](/frameworks/next-js/overview/#v5-breaking-changes) . ### [#](#work-with-javascript-rendered-forms) Work with JavaScript-rendered forms The Netlify build system finds your forms by parsing the HTML of your site when the build completes. This means that if you’re using JavaScript to render a form client-side, our build system won’t find it in the pre-built files. You can work around this: * Create a hidden HTML form with the `data-netlify="true"` attribute or a `netlify` attribute and input fields with `name` attributes to match the inputs of your JavaScript-rendered form. You need to apply the same work around if you want to use our [reCAPTCHA 2 integration](/forms/spam-filters/#recaptcha-2-challenge) , and create a `div` element in the hidden HTML with the `data-netlify-recaptcha="true"` attribute. * Add a hidden input to the JavaScript-rendered form or JSX form: You can also find related tutorials on our blog: * [How to Integrate Netlify’s Form Handling in a React App](https://www.netlify.com/blog/2017/07/19/how-to-integrate-netlifys-form-handling-in-a-react-app/) * [How to Integrate Netlify forms in a Vue App](https://www.netlify.com/blog/2018/09/07/how-to-integrate-netlify-forms-in-a-vue-app/) While the two articles are fairly framework-specific, the code demonstrates how to prerender forms when working with them in a web application. ### [#](#submit-javascript-rendered-forms-with-ajax) Submit JavaScript-rendered forms with AJAX To submit a JavaScript-rendered form built with a framework like Gatsby or Nuxt, you can send an AJAX POST request to any path on your site. Requirements for the request: * You need to URL-encode your form data in the body of the request. * If you haven’t added a hidden `form-name` input to your JavaScript-rendered form, you need to send a `form-name` attribute in the AJAX POST request body. * If the form accepts alphanumeric data only, the request should include the header `"Content-Type": "application/x-www-form-urlencoded"`. If the form accepts [file uploads](/forms/setup/#file-uploads) , including a `Content-Type` header is not recommended. Here’s an AJAX form submission code sample using the `fetch` API for a JavaScript-rendered form. It uses Gatsby’s `navigate` function to redirect to a custom page on form submission success. const handleSubmit = event => { event.preventDefault(); const myForm = event.target; const formData = new FormData(myForm); fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(formData).toString() }) .then(() => navigate("/thank-you/")) .catch(error => alert(error)); }; For a JavaScript-rendered form, you need to add a hidden `input` with `name="form-name"` to the returned form elements. Here’s an example: return (
); In the code sample above, a `handleChange` function updates the form’s state, which ultimately gets sent in a POST request to Netlify. [#](#success-messages) Success messages ---------------------------------------- By default, when visitors complete a form, they are redirected to a page with a generically styled success message with a link back to the form page. ![Generic forms success message displayed.](/images/forms-default-generic-success-message.png) ### [#](#custom-success-page) Custom success page You can replace the default success page with a custom page you create by adding an `action` attribute to the `
` tag, entering the path of your custom page (like `"/pages/success"`) as the value. The path must be relative to the site root, starting with a `/`. Here’s an example:
If you submit your form using AJAX, reference this [Gatsby-specific example](#submit-javascript-rendered-forms-with-ajax) of how to set a custom success page. ### [#](#custom-success-alert) Custom success alert If you use AJAX to submit the form, you can substitute an alert instead of redirecting to a generic or custom page. Here’s an example for an HTML form: const handleSubmit = event => { event.preventDefault(); const myForm = event.target; const formData = new FormData(myForm); fetch("/", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(formData).toString() }) .then(() => alert("Thank you for your submission")) .catch(error => alert(error)); }; document.querySelector("form").addEventListener("submit", handleSubmit); [#](#file-uploads) File uploads -------------------------------- Netlify Forms can receive files uploaded with form submissions. To do this, add an input with `type="file"` to any form. Although most browsers will detect the encoding automatically, you can optionally include `enctype="multipart/form-data"` in the `
` tag, Here’s a sample HTML form with a file upload field:

### [#](#file-upload-security) File upload security Forms that accept file uploads that contain personally identifiable information (PII) require additional security configuration. We recommend using the [Very Good Security](https://www.netlify.com/integrations/very-good-security/) integration for this type of secure form upload. ### [#](#limitations) Limitations Keep the following considerations in mind when working with file uploads in forms. * Only one file upload per field is supported. For multiple file uploads, use multiple fields. * The form request has a maximum size limit of 8 MB. * File uploads time out after 30 seconds. ### [#](#submit-file-uploads-with-ajax) Submit file uploads with AJAX When submitting a form with a file upload, including a `Content-Type` header is not recommended. The browser should detect and set the `Content-Type` automatically. Here’s an AJAX form submission code sample using the `fetch` API for the above HTML form with file upload: document.forms.fileForm.addEventListener("submit", event => { event.preventDefault(); const result = document.querySelector(".result"); fetch("/", { body: new FormData(event.target), method: "POST" }) .then(() => { result.innerText = "Success"; }) .catch(error => { result.innerText = `Failed: ${error}`; }); }); [#](#set-up-notifications) Set up notifications ------------------------------------------------ To monitor the content of your form submissions, you can set up notifications to send the content of the form submissions to an email address or to an external service with an HTTP POST request. Learn more about [forms notifications](/forms/notifications/) . To set up notifications for your site’s form submissions: 1. For your site go to **Configuration \> Notifications \> Form submission notifications** , and select **Add notification**. [#](#review-forms-usage) Review forms usage -------------------------------------------- For the last month (or billing period), you can review how many verified form submissions were made and the total storage size of all files uploaded. 1. For your site, go to **Forms \> Usage and configuration \> Usage** . Learn more about [reviewing and managing forms usage](/forms/usage-and-billing/) . [#](#more-forms-resources) More Forms resources ------------------------------------------------ * [Spam filters](/forms/spam-filters/) * [Form submissions](/forms/submissions/) * [Form submission notifications](/forms/notifications/) * [Form-triggered functions](/functions/trigger-on-events/) * [Troubleshooting tips](/forms/troubleshooting-tips/) * [Forms usage and billing](/forms/usage-and-billing/) Last updated: November 6, 2024 [Spam filters](/forms/spam-filters/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Frameworks API | Netlify Docs 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. 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. 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. [#](#features) Features ------------------------ ### [#](#netlify-v1-config-json) `.netlify/v1/config.json` Use the `config.json` file to configure how Netlify builds and deploys a site. It’s a subset of the [user-facing file-based configuration](/configure-builds/file-based-configuration/) (using JSON instead of TOML) and it supports the following properties. * [`edge_functions`](#edge-functions) * [`functions`](#functions) * [`headers`](#headers) * [`images`](#images) * [`redirects`](#redirects) #### [#](#edge-functions) `edge_functions` Accepts edge function declarations with the [same properties as the user-facing configuration](/edge-functions/declarations/#declare-edge-functions-in-netlify-toml) . While edge functions can be [configured in the same file as the function code](#configuration-options) , 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. { "edge_functions": [\ {\ "function": "auth",\ "path": "/admin"\ },\ {\ "cache": "manual",\ "function": "injector",\ "path": "/admin"\ },\ {\ "function": "auth",\ "path": "/blog/*"\ },\ {\ "function": "rewriter",\ "path": "/blog/*"\ },\ {\ "excludedPattern": "/products/things/(.*)",\ "function": "highlight",\ "pattern": "/products/(.*)"\ },\ {\ "excludedPath": "/img/*",\ "function": "common",\ "path": "/*"\ }\ ] } Entries of the `edge_functions` array in the `config.json` file only take a single path per edge function. This means that if you want to configure the edge function to run on `/path1` and `/path2`, 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. { "edge_functions": [\ {\ "function": "my-framework-edge-function-1",\ "path": "/path1"\ },\ {\ "function": "my-framework-edge-function-2",\ "path": "/path1"\ },\ {\ "function": "my-framework-edge-function-2",\ "path": "/path2"\ },\ {\ "function": "my-framework-edge-function-1",\ "path": "/path2"\ }\ ] } #### [#](#functions) `functions` Accepts function configuration options, including any property from [the inline configuration options](#configuration-options-2) . When you define the properties, we prefer snake case — for example, use `included_files` instead of `includedFiles`. { "functions": { "directory": "myfunctions/", "included_files": ["files/*.md"] } } 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 `my_framework_`, it can target them within the `functions` object. { "functions": { "my_framework_*": { "included_files": ["files/*.md"] } } } #### [#](#headers) `headers` Specifies [custom headers](/routing/headers/) that Netlify serves with the site when a client makes a request. It follows the same capabilities as the `headers` array of the [user-facing file-based configuration.](/configure-builds/file-based-configuration/#headers) { "headers": [\ {\ "for": "/*",\ "values": {\ "Basic-Auth": "someuser:somepassword anotheruser:anotherpassword",\ "X-Frame-Options": "DENY",\ "cache-control": "max-age=0,no-cache,no-store,must-revalidate"\ }\ }\ ] } #### [#](#images) `images` Configures the [Netlify Image CDN](/image-cdn/overview/) . You can specify [allowed domains for remote image transformations](/image-cdn/overview/#remote-path) . The `remote_images` property accepts an array of [regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) , which can represent specific subdomains or directories. 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 `https://example.com/`. { "images": { "remote_images": ["https:\\/\\/example.com\\/.*"] } } #### [#](#redirects) `redirects` Specifies [redirect and rewrite rules](/routing/redirects/) that Netlify evaluates when a client makes a request. It follows the same syntax as the `redirects` array of the [user-facing file-based configuration.](/configure-builds/file-based-configuration/#redirects) { "redirects": [\ {\ "force": false,\ "from": "/old-path",\ "status": 301,\ "to": "/new-path",\ "conditions": {\ "Country": ["US"],\ "Language": ["en", "es"]\ },\ "query": {\ "path": ":path"\ }\ },\ {\ "from": "/news",\ "to": "/blog"\ }\ ] } These rules are appended to any rules defined by the user in [the `_redirects` file](/routing/redirects/#syntax-for-the-redirects-file) or [the `netlify.toml` file](/routing/redirects/#syntax-for-the-netlify-configuration-file) . 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. If you want to change this behavior and ensure that the rules defined by the framework are evaluated first, you can use the `redirects!` 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. { "redirects!": [\ {\ "from": "/some-path",\ "to": "/new-path"\ }\ ] } ### [#](#netlify-v1-blobs) `.netlify/v1/blobs` Upload [blobs](/blobs/overview/) to the [deploy-specific store](/blobs/overview/#deploy-specific-stores) . 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. Our build system traverses the `.netlify/v1/blobs/deploy` directory and generates a blob for each `blob` file it finds. The blob key is the path of the file relative to the `.netlify/v1/blobs/deploy` directory (without a leading slash). .netlify/ └── v1/ └── blobs/ └── deploy/ ├── example.com/ │ └── blob └── netlify.com/ ├── blob └── blob.meta.json For example, the directory tree above would generate two blobs: * a blob with the key `example.com`, holding the contents of the file at `.netlify/v1/blobs/deploy/example.com/blob` * a blob with the key `netlify.com`, holding the contents of the file at `.netlify/v1/blobs/deploy/netlify.com/blob` Optionally, you can include a `blob.meta.json` file that contains an object with arbitrary metadata, encoded as JSON, which you can then retrieve with the [`getMetadata`](/blobs/overview/#getmetadata) and [`getWithMetadata`](/blobs/overview/#getwithmetadata) client methods. Root key You can’t place a `blob` file directly under the `.netlify/v1/blobs/deploy` 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 `my-cache`, and treat `my-cache` as `/` and `my-cache/child` as `/child`. 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 [functions](#netlify-v1-functions) and [edge functions](#netlify-v1-edge-functions) check whether there’s a blob for a given URL before making an HTTP call. // .netlify/v1/functions/my-framework-cache.ts import { getDeployStore } from "@netlify/blobs"; import type { Config, Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { const { domain } = context.params; const cache = getDeployStore(); const cachedResponse = await cache.get(domain, { type: "stream" }); if (cachedResponse !== null) { return new Response(cachedResponse); } const response = await fetch(`https://${domain}`); const body = await response.blob(); await cache.set(domain, body); return response; } export const config: Config = { // Accepts requests on paths like "/cache/example.com". path: "/cache/:domain" } To pre-warm the cache with a response for `https://example.com`, you could fetch it at build time and write the response to a file at `.netlify/v1/blobs/deploy/example.com/blob`. Additionally, you could modify the example above to also persist the headers of cached responses. To write a metadata object for the same `example.com` key, write a JSON object to `.netlify/v1/blobs/deploy/example.com/blob.meta.json` with a payload like: { "headers": { "Content-Type": "text/html; charset=UTF-8", "Date": "Wed, 12 Jun 2024 09:14:11 GMT" } } ### [#](#netlify-v1-edge-functions) `.netlify/v1/edge-functions` Generate [edge functions](/edge-functions/overview/) for a site and configure the URL paths on which they run. 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. For example, you could generate an edge function that intercepts requests for JSON (by inspecting [the `Accept` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) ) and [rewrite them](/edge-functions/api/#return-a-rewrite) to a path that implements your framework’s API route. If a client requests `https://example.com/products/123` and asks for a JSON response, the edge function would serve the contents of the `https://example.com/api/products/123` path. To create this edge function, your framework would write the code below to a file at `.netlify/v1/edge-functions/my-framework-api-route-handler.ts`. import type { Config, Context } from "@netlify/edge-functions"; export default async (req: Request, context: Context) => { if (req.headers.get("accept") === "application/json") { const { pathname } = new URL(req.url) return new URL(`/api${pathname}`, req.url) } } export const config: Config = { // Configures the paths on which the edge function runs. // The value below lets you intercept requests for any path. path: "/*", // Sometimes it's useful to exclude certain paths. // This example will ignore requests that are // already targeting an `/api/` path. excludedPath: ["/api/*"] }; #### [#](#configuration-options) Configuration options To configure generated edge functions from within the function file, export a `config` object. It accepts the following properties: * `path` (`string` or `string[]`): 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 [the `URLPattern` web standard syntax](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) . * `excludedPath` (`string` or `string[]`): 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 [the `URLPattern` web standard syntax](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) . * `method` (`string` or `string[]`): 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. * `cache` (`string`): Opts in to [response caching](/edge-functions/optional-configuration/#response-caching) . * `name` (`string`): A human-friendly name for the edge function. It is shown instead of the filename in build logs and in the UI. * `generator` (`string`): 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. * `onError` (`string`): Defines the behavior for [when the edge function terminates unexpectedly](/edge-functions/optional-configuration/#error-handling) . You can choose to serve a generic error page (`fail`, the default value), skip the erroring edge function and continue the request chain (`bypass`), or provide a URL path that requests are rewritten to in the event of an error (for example, `/my-framework-error-page`). * `rateLimit` (`object`): Sets [custom rate limiting rules](/security/secure-access-to-sites/rate-limiting/#function-edge-function-examples) for the edge function. Static values only The `config` object must be defined in [the edge function’s main file](/edge-functions/get-started/#create-an-edge-function) 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. #### [#](#bundling) Bundling 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 [third-party modules](https://www.netlify.com/blog/support-for-npm-modules-in-edge-functions/) , into a single file. Optionally, you can choose to handle this process yourself, using tools like [esbuild](https://esbuild.github.io/) or [Vite](https://vitejs.dev/) 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. There are some things to consider if you choose to do this: * It’s important to note that [edge functions run on Deno](/edge-functions/api/#runtime-environment) , not Node.js. This has the following implications: * You shouldn’t rely on Node.js built-ins. * You should always generate ESM code (not CommonJS) with the latest syntax. * If you’re bundling your code using esbuild, set [the `platform` property](https://esbuild.github.io/api/#platform) to `neutral` and set [`target` to `esnext`](https://esbuild.github.io/api/#target) . * For Vite, set [`target` to `webworker`](https://github.com/netlify/remix-compute/blob/124b930bf0a72427240d744bb96e17cb2f258536/packages/remix-edge-adapter/src/plugin.ts#L49) and [mark all Node.js built-ins as external](https://github.com/netlify/remix-compute/blob/124b930bf0a72427240d744bb96e17cb2f258536/packages/remix-edge-adapter/src/plugin.ts#L51) . #### [#](#import-maps) Import maps You can customize the resolution of module specifiers in edge functions using [import maps](/edge-functions/api/#import-maps) . To do this, place a file following [the import map syntax](https://html.spec.whatwg.org/multipage/webappapis.html#import-maps) at `.netlify/v1/edge-functions/import_map.json`. For example, the file below would let you rewrite the bare specifier `html-rewriter` to a specific remote URL, and point `utils` to a local directory so you can import `utils/ab-test.ts` instead of `./nested/directory/utils/ab-test.ts`. { "imports": { "html-rewriter": "https://ghuc.cc/worker-tools/html-rewriter/index.ts", "utils/": "./nested/directory/utils" } } ### [#](#netlify-v1-functions) `.netlify/v1/functions` 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 [user-defined functions](/functions/get-started/?fn-language=ts) . Functions are a way to dynamically render parts of your application, like API routes. You can also use them to power your framework’s [server-side rendering](https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Web_frameworks) capabilities. For example, you could generate an SSR function by writing the following code to `.netlify/v1/functions/my-framework-ssr.ts`. import type { Config, Context } from "@netlify/functions"; import { renderPage } from "./your-framework-code.ts"; export default async (req: Request, context: Context) => { const html = await renderPage(req); return new Response(html, { headers: { "content-type": "text/html" } }); }; export const config: Config = { path: "/*" // Sometimes it's useful to exclude certain paths. // This example will ignore requests that are // already targeting an `/api/` path. excludedPath: ["/api/*"] }; #### [#](#configuration-options-2) Configuration options Generated functions can be configured from within the function file using an exported `config` object. It accepts the following properties: * `path` (`string` or `string[]`): The URL path or set of paths for which the function is invoked. It supports wildcards and named parameters using [the `URLPattern` web standard syntax](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) . * `excludedPath` (`string` or `string[]`): A URL path or set of paths for which the 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 [the `URLPattern` web standard syntax](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) . * `preferStatic` (`boolean`): 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 `preferStatic: true`. * `displayName` (`string`): A human-friendly name for the function. It is shown instead of the filename in build logs and in the UI. * `generator` (`string`): 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. * `includedFiles` (`string[]`): List of additional paths to include in the function bundle. Although Netlify includes statically referenced files (like `require("./some-file.js")`) by default, you can specify additional files or directories and reference them dynamically in function code. You can use `*` to match any character or prefix an entry with `!` to exclude files. Paths are absolute paths relative to the base directory. * `nodeBundler` (`string`): 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 `esbuild` if you want to use [esbuild](https://esbuild.github.io/) to bundle everything into a single file, which usually leads to a smaller payload; you can set it to `none` if you want to use [your own bundling process](#bundling-2) . * `externalNodeModules` (`string[]`): When setting `nodeBundler` to `esbuild`, this property lets you provide a list of npm packages that are marked as [external](https://esbuild.github.io/api/#external) , which means their original structure is kept in a `node_modules` directory as opposed to being inlined with the function code. * `ignoredNodeModules` (`string[]`): When setting `nodeBundler` to `esbuild`, this property lets you provide a list of npm packages that are marked as [external](https://esbuild.github.io/api/#external) but whose source is not preserved in the `node_modules` 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. * `nodeVersion` (`string`): Sets the major version of Node.js to run the function with. It takes values like `20` to use Node.js 20.x, for example. * `schedule` (`string`): When defined, turns the function into a [scheduled function](/functions/scheduled-functions/) and defines the schedule on which it runs. * `rateLimit` (`object`): Sets [custom rate limiting rules](/security/secure-access-to-sites/rate-limiting/#function-edge-function-examples) for the function. Static values only The `config` object must be defined in [the function’s main file](/functions/get-started/#route-requests) 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. #### [#](#bundling-2) Bundling 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. 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 (`nodeBundler` and `includedFiles`) in the function’s `config` object. import type { Config, Context } from "@netlify/functions"; export default async (req: Request, context: Context) => { return new Response("Hello world"); } export const config: Config = { // Setting `nodeBundler` to `none` lets you opt out of the // automatic bundling process. nodeBundler: "none", // When using a custom bundling process, you must provide the // full list of files to include in the deployable package. // You can use the `includedFiles` property, which supports globs. includedFiles: ["my-framework-bundle-output/**"] }; [#](#merging-configurations) Merging configurations ---------------------------------------------------- All Netlify platform primitives can be provisioned and configured directly by developers — for example, a developer can create a redirect rule by [writing a `_redirects` file](/routing/redirects/#syntax-for-the-redirects-file) or deploy a function by [writing a file to the functions directory](/functions/get-started/#create-function-file) . 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: * For properties that are “additive” (like the [allowed domains for the Netlify Image CDN](/image-cdn/overview/#remote-path) or [the list of serverless functions](/frameworks-api/#netlify-v1-functions) ), any entries from the Frameworks API are appended to the ones defined by the user; if order is relevant, user-defined configuration takes precedence * For properties that are mutually-exclusive (like the [functions directory](#functions) ), any user-defined configuration takes precedence Avoid collisions with user-defined functions 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, `my-framework-ssr.ts`. [#](#versioning) Versioning ---------------------------- 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. 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. To this end, all features have a version identifier in their file paths (for example, `.netlify/v1/config.json`). A breaking change to that feature would be released as `.netlify/v2/config.json`, with no changes to the previous path, giving framework authors the choice to update their implementation at their own schedule. Last updated: November 25, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Express on Netlify | Netlify Docs Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. [#](#key-features) Key features -------------------------------- These features provide important benefits for Express apps, including ones built and deployed with Netlify. * **Routing**. Express provides a robust routing API that allows you to perform complex routing tasks. With this API, you can split code on a per-route basis and not be strictly limited by Netlify’s file-based routing for Functions. * **Middleware**. Express provides a comprehensive set of HTTP utility methods and middleware that you can use to develop a robust API for your application. [#](#netlify-integration) Netlify integration ---------------------------------------------- Express apps on Netlify work because of [Netlify Functions](/functions/overview/) . When you deploy an Express app on Netlify as serverless functions, you get to leverage all of the benefits of running on-demand, server-side code without having to run a dedicated server. [#](#deploy-an-express-app-on-netlify) Deploy an Express app on Netlify ------------------------------------------------------------------------ This section demonstrates how to deploy an Express project on Netlify — either alongside a frontend app that uses another framework, or as a standalone Express app. ### [#](#use-express-with-a-frontend-app) Use Express with a frontend app Before you begin, make sure you have [Node.js](https://nodejs.org/en/download) version 18.14.0 or later installed on your machine. Then, you can start a new project using Express. 1. Install the following dependencies. If your Express project uses JavaScript, you can exclude `@netlify/functions` and `@types/express`. npm i express serverless-http @netlify/functions @types/express 2. [Create a Netlify Function file](/functions/get-started/#create-function-file) for either TypeScript or JavaScript. For example, you might create a function file called `api.ts`. 3. In the newly created file, write the function that will import Express and create a router object to handle routing. Here is an example: // YOUR_BASE_DIRECTORY/netlify/functions/api.ts import express, { Router } from "express"; import serverless from "serverless-http"; const api = express(); const router = Router(); router.get("/hello", (req, res) => res.send("Hello World!")); api.use("/api/", router); export const handler = serverless(api); 4. Add the following configuration in your `netlify.toml`: [functions] external_node_modules = ["express"] node_bundler = "esbuild" [[redirects]] force = true from = "/api/*" status = 200 to = "/.netlify/functions/api/:splat" In the `redirects` section is a rewrite that enables Express to parse the URLs configured in your function file. In this example, Express can now successfully parse `/api`, which we configured above with `api.use('/api/', router);`. If you don’t wish to add the rewrite, you might have to change the configuration in your function to specify the functions path, such as `api.use('/.netlify/functions/', router);`. 5. You can now use these routes in your frontend code. In the above example, you can access the `/hello` route at `/api/hello` and any other route that you might add at `/api/`. 6. Follow the steps below to [deploy your Express app](#deploy-your-express-app-with-netlify-cli) . ### [#](#use-express-without-a-frontend) Use Express without a frontend It’s possible to deploy Express apps on Netlify without a frontend. If you do this, you can access the routes from other frontend apps deployed separately, just as you would with any other API endpoints. In this case, you might have to configure CORS to allow access to the routes from other domains. To deploy an Express app without a frontend: 1. Follow the steps [documented above](#use-express-with-a-frontend-app) to install Express, create a Netlify Function with your routing code, and create a `netlify.toml` file to register the function and redirects required. 2. In the `netlify.toml` or the Netlify UI, set a placeholder [build command](/configure-builds/overview/#build-settings) to ensure Netlify builds your functions. For example, the command could be `echo Building Functions`. 3. Follow the steps below to [deploy your Express app](#deploy-your-express-app-with-netlify-cli) . ### [#](#deploy-your-express-app-with-netlify-cli) Deploy your Express app with Netlify CLI Whether you use Express with a frontend or not, the steps to deploy are the same. You can [deploy your project from the command line](/site-deploys/create-deploys/#netlify-cli) using [Netlify CLI](/cli/get-started/) . 1. To ensure you have the latest version of Netlify CLI installed, run this command from any directory in your terminal: npm install netlify-cli -g 2. In the directory for your project, run the following command to create a new Netlify site: netlify init Didn’t initialize a Git repository? When you run `netlify init` without initializing a Git repository first, the CLI prompts you to connect your local directory to GitHub. Follow the steps in your terminal to link your local directory with a remote repo in order to use continuous deployment for your site. 3. Follow the prompts to create your site, select a team if necessary, and optionally create a site name. If you already initialized a Git repository, you can authorize your Git provider and set your build command and directory. 4. If you used continuous deployment, your site is now published! To learn how to manually deploy a site, check out the [manual deploy docs](/cli/get-started/#manual-deploys) . [#](#limitations) Limitations ------------------------------ 1. Since Express apps are deployed as Netlify Functions, all of the [function limitations](/functions/overview/#default-deployment-options) apply. This includes execution and memory limits. 2. It is not recommended to deploy Express apps as background or scheduled functions. [#](#more-resources) More resources ------------------------------------ * [Netlify Functions](/functions/overview/) * [Express documentation](https://www.expressjs.com/) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#express) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Eleventy on Netlify | Netlify Docs Eleventy (11ty) is a flexible and configurable open source static site generator. Although it’s written in JavaScript, it doesn’t depend on a specific framework for generating or serving content. [#](#key-features) Key features -------------------------------- These features provide important benefits for Eleventy projects, including ones built and deployed with Netlify. * **JavaScript-friendly.** Eleventy was developed as a JavaScript alternative to Jekyll. It’s not dependent on a client-side JavaScript framework or library, which means it doesn’t predetermine your frontend stack. * **Flexible config.** By default, Eleventy requires no configuration, but it has flexible options for custom setup. It is intentionally decoupled from frameworks, build pipelines, and other tools in order to support your preferences. * **Adaptable project structure.** Eleventy works with your project’s existing directory structure and generates HTML based on the templates, content, and data you provide. * **Choice of templating.** By default, Eleventy uses the template language [Liquid](https://www.11ty.dev/docs/languages/liquid/) . However, it supports many [template languages](https://www.11ty.dev/docs/languages/) and allows them to be mixed and combined. This allows a project to migrate to or adopt Eleventy gradually over time. [#](#netlify-integration) Netlify integration ---------------------------------------------- When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Eleventy, Netlify provides a suggested build command and output directory: `eleventy` and `_site`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `eleventy --serve` and `8080`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up an Eleventy site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#eleventy) for Eleventy. ### [#](#edge-functions) Edge Functions Edge Functions connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. You can browse a [full library of reference examples](https://edge-functions-examples.netlify.app/) for different ways to use Edge Functions. For more details, check out the [Edge Functions documentation](/edge-functions/overview/) . Eleventy has [a dedicated plugin](https://www.11ty.dev/docs/plugins/edge/) to take advantage of Edge Functions on Netlify, allowing you to use dynamic template languages on the edge to dynamically render templates and modify build-time generated content. This unlocks [many new use cases](https://demo-eleventy-edge.netlify.app/) in a performance-focused way with zero client-side JavaScript: forms, cookies, user personalization, A/B testing, and more. ### [#](#requirement-for-build-plugins) Requirement for Build Plugins To use a Netlify build plugin with your Eleventy site, you must update your site’s `.gitignore` file. Without this change, installed Netlify build plugins and all current versions of Eleventy will both attempt to use `.netlify/plugins/node_modules/`, resulting in build errors. As a workaround, we recommend you change `node_modules` to `**/node_modules/**` in the `.gitignore` file. [#](#more-resources) More resources ------------------------------------ * [Typical Eleventy build settings](/frameworks/#eleventy) * [Netlify Blog: Eleventy posts](https://www.netlify.com/blog/tags/Eleventy/) * [Learn Jamstack video course](https://www.netlify.com/blog/2020/03/12/learn-jamstack-with-a-free-3.5-hour-video-of-demos-and-examples/#main) with corresponding [Eleventy example site](https://github.com/philhawksworth/fcc-3-build-with-ssg) * [Eleventy documentation](https://www.11ty.dev/docs/) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#eleventy) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Environment variables and frameworks | Netlify Docs Projects on Netlify can use [environment variables](/environment-variables/overview/) at two different stages: during the build process or once the site is built and running in the browser. [#](#use-variables-during-the-build) Use variables during the build -------------------------------------------------------------------- Our docs cover how to [create environment variables](/environment-variables/get-started/#create-environment-variables) and how to use environment variables [during the build process](/configure-builds/environment-variables/#use-variables-during-the-build) . Depending on the framework you use, there are specific [configuration variables](/configure-builds/environment-variables/#netlify-configuration-variables) you may want to set to change an aspect of your build - such as the `HUGO_VERSION` or `NEXTAUTH_SECRET`. Visit the Netlify doc for your [framework](/frameworks/) to find out more. Note that if you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** to be available during the build process. [#](#use-variables-after-the-build-is-complete) Use variables after the build is complete ------------------------------------------------------------------------------------------ If you want to use environment variable values after the site is built, you have a few options: * [Use a function](/functions/environment-variables/) , including serverless functions and edge functions, to access values during runtime. This is the best option to avoid revealing sensitive values. * [Embed variable values](#embed-variable-values-in-the-site-build) in the site code during the build process. * [Leverage snippet injection](/site-deploys/post-processing/snippet-injection/#environment-variables) to access values during post-processing. ### [#](#embed-variable-values-in-the-site-build) Embed variable values in the site build You can embed environment variables into your site while it’s building, for use within your site after the build is complete. You should not copy sensitive values into your build as these values are accessible to anyone inspecting your app files in the browser. Along with your framework’s built-in environment variables, you may want to use custom variables or Netlify variables in your site. #### [#](#custom-variables) Custom variables To set custom variables in the Netlify UI or the `netlify.toml` and then use them within your site, most frameworks require the use of a framework-specific prefix in the name of each [variable you declare](/environment-variables/get-started/#create-environment-variables) . Here are a few examples of frameworks and the prefix to use for each: * Create React App: `REACT_APP_` * Gatsby: `GATSBY_` * Next: `NEXT_PUBLIC_` * Nuxt: `NUXT_ENV_` * Vue CLI: `VUE_APP_` For example, here is a non-sensitive custom variable `GREETING` set in `netlify.toml` for the production context. To make it work with React, use the name `REACT_APP_GREETING`: [context.production.environment] REACT_APP_GREETING = "Hello" You can then use the custom environment variable in your React site code in production:

This is my greeting: { process.env.REACT_APP_GREETING }

Check the docs for your framework to confirm if a prefix is necessary. ##### [#](#setting-variables-for-use-with-server-side-rendering) Setting variables for use with server-side rendering If your project uses server-side rendering (SSR) or deferred static generation (DSG), Netlify automatically handles these pages using Netlify [Functions](/functions/overview/) or Netlify [Edge Functions](/edge-functions/overview/) . As the `netlify.toml` file is only read during the build process and not accessible by functions, you need to set custom variables in the Netlify [UI, CLI, or API](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) if you want your SSR or DSG pages to access them during runtime. If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your custom environment variables, the scope must include both **Functions** and **Builds** to support both server-side and client-side rendering. To access Netlify configuration or [read-only variables](/configure-builds/environment-variables/#read-only-variables) in SSR or DSG pages, create variables with these values in the build command as outlined in the following section. #### [#](#netlify-variables) Netlify variables To use Netlify’s build environment variables in your site, create variables in your project code (where applicable, these should be framework-prefixed variables) and assign the Netlify variables as their values. The recommended way to do this is to create the variables in-line before your project’s build command. For example, to access Netlify’s `CONTEXT` variable in your Create React App site, update the build command in the `netlify.toml` to set `REACT_APP_CONTEXT=$CONTEXT` before running the build: [build] command = "REACT_APP_CONTEXT=$CONTEXT npm run build" You can do the same update to the [build command](/configure-builds/overview/#build-settings) in the Netlify UI. Note that it’s not possible to use Netlify variables as values in the environment variables sections of the Netlify UI or `netlify.toml`. Depending on your framework, however, it might be possible to use variables as values in [a `.env` file](#env-files-and-netlify-variables) . As the framework builds your site, it retrieves the environment variable `CONTEXT` from the build environment and uses the variable’s value when it injects the framework-prefixed variable, such as `REACT_APP_CONTEXT`, into your site. You can then access the variable in your JavaScript files using the format `process.env.VARIABLE_NAME`, such as `process.env.REACT_APP_CONTEXT`: if (process.env.REACT_APP_CONTEXT === `deploy-preview`){ console.log(`This is a preview version of our site.`); } ##### [#](#env-files-and-netlify-variables) `.env` files and Netlify variables While Netlify may not read your `.env` files, depending on where you [build your project](/configure-builds/environment-variables/#prepare-your-build-environment) , your framework may read the files during the framework’s build step. If you would like to use Netlify environment variables as values in a `.env` file for your framework to access, such as `REACT_APP_CONTEXT=$CONTEXT`, your project needs to support variable expansion. Framework support for variable expansion, the term for retrieving variables from the build environment for use as values in `.env` files, varies. Some frameworks, such as [Create React App](https://create-react-app.dev/docs/adding-custom-environment-variables/#expanding-environment-variables-in-env) and [Vue](https://cli.vuejs.org/guide/mode-and-env.html#environment-variables) , have built-in variable expansion support. Some frameworks support similar functionality in their unique configuration files, such as Nuxt with [`nuxt.config.js`](https://nuxtjs.org/docs/directory-structure/nuxt-config/#env) . Other frameworks will require the use of a separate library, such as [`dotenv-expand`](https://github.com/motdotla/dotenv-expand) , to make this work. We recommend searching your framework’s docs for “expand variables” or “variable expansion” to confirm what’s possible. Last updated: March 12, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Angular on Netlify | Netlify Docs Angular is a component-based open source framework for building enterprise-grade single-page applications (SPAs) with client-side routing, server-side rendering, and prerendering. Scully, an open source static site generator, is built specifically for Angular apps. [#](#key-features) Key features -------------------------------- These features provide important benefits for Angular projects, including ones built and deployed with Netlify. * **Robust integrated tooling.** Using declarative templates, you can extend Angular’s template language for more customization. You can also get immediate Angular-specific help and feedback with popular IDEs and editors. * **Helpfully opinionated.** As a framework, Angular predetermines certain project decisions, but this reduces the number of choices a team has to make. Using features like the [`ng generate`](https://angular.io/cli/generate) command and without relying on third-party libraries, your team can focus on building an app, not the setup. * **Image optimization**. The [`NgOptimizedImage` directive](https://angular.io/guide/image-directive#getting-started-with-ngoptimizedimage) , backed by [Netlify Image CDN](#netlify-image-cdn) , makes it easier to adopt performance best practices for loading images. * **Supported by Google.** Angular is Google’s largest application and has the reliability of being backed and maintained by the company. The team also adheres to Long-Term Support (LTS) and has a [public roadmap](https://angular.io/guide/roadmap) . * **Built with TypeScript.** When building out Angular applications, you can take advantage of type safety and tooling using TypeScript. [Strict mode](https://angular.io/guide/strict-mode) can help you avoid type errors before hitting production. In addition to the Angular-specific items above, Netlify gives you control over [branch and deploy](/site-deploys/overview/#branches-and-deploys) settings. This allows you to set up continuous deployment according to your project needs, such as only deploying particular branches or creating Deploy Previews on `git push`. [#](#netlify-integration) Netlify integration ---------------------------------------------- Angular applications on Netlify can benefit from integrations such as automatic framework detection and built-in redirects functionality. ### [#](#automatic-framework-detection) Automatic framework detection When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Angular, Netlify provides a suggested build command: `ng build --prod`. Based on your `angular.json`, Netlify automatically configures the publish directory. If your site has server-side rendering enabled, this is automatically configured using an Edge Function. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `ng serve` and `4200`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up an Angular app on Netlify. ### [#](#netlify-image-cdn) Netlify Image CDN When deploying your Angular applications to Netlify, `NgOptimizedImage` automatically uses [Netlify Image CDN](/image-cdn/overview/) to optimize and transform images on demand without impacting build times. Netlify Image CDN also handles content negotiation to use the most efficient image format for the requesting client. To transform a source image hosted on another domain, you must first configure allowed domains in your `netlify.toml` file: [images] remote_images = ["https://my-images.com/.*", "https://animals.more-images.com/[bcr]at/.*"] The `remote_images` property accepts an array of regex. If your images are in specific subdomains or directories, you can use regex to allow just those subdomains or directories. Visit the [Angular docs](https://angular.io/guide/image-directive#getting-started-with-ngoptimizedimage) to learn more. ### [#](#redirects) Redirects Although we recommend [prerendering your Angular app](https://www.netlify.com/blog/2021/02/08/pre-rendering-with-angular-universal/) or using Scully to produce static files, you may need to use [redirects](/routing/redirects/) to enable Angular routing and page refresh functionality for pages with client-side rendering. You can use a `_redirects` file or a [Netlify configuration file](/configure-builds/file-based-configuration/#redirects) to configure these. In `_redirects`: /* /index.html 200 Make sure you include the `_redirects` file in your `angular.json` assets array so that Angular will include a copy of the file when building your project: "assets": [\ "src/_redirects"\ ] In `netlify.toml`: [[redirects]] from = "/*" to = "/index.html" status = 200 Redirects on SSR Pages utilizing [Server-Side Rendering (SSR)](https://angular.dev/guide/ssr) are not subject to redirects placed in `_redirects` or `netlify.toml`. This is because SSR uses Edge Functions, which run before redirects are evaluated. Instead, use Angular's built-in redirects feature: [Setting up redirects](https://angular.dev/guide/routing/common-router-tasks#setting-up-redirects) ### [#](#accessing-request-and-context-during-server-side-rendering-ssr) Accessing `Request` and `Context` during Server-Side Rendering (SSR) During server-side rendering, you can access the incoming `Request` object and the Netlify-specific `Context` object via the `netlify.request` and `netlify.context` providers: import type { Context } from "@netlify/edge-functions" export class FooComponent { constructor( // ... @Inject('netlify.request') @Optional() request?: Request, @Inject('netlify.context') @Optional() context?: Context, ) { console.log(`Rendering Foo for path ${request?.url} from location ${context?.geo?.city}`) // ... } } The `Request` and `Context` objects will not be available on the client-side or during [prerendering](https://angular.dev/guide/prerendering#prerendering-parameterized-routes) . To test this in local development, run your Angular project using `netlify serve`. [#](#more-resources) More resources ------------------------------------ * [Video: Angular in the Jamstack](https://www.youtube.com/playlist?list=PLzlG0L9jlhEO5HFKx36Pd6LZ6aY44oseL) * [Netlify Blog: Angular posts](https://www.netlify.com/tags/angular/) * [Netlify redirect rules for Angular apps](https://medium.com/@seraya/netlify-redirect-rules-for-angular-6-apps-d9f27ad40449) * [Angular documentation](https://angular.io/docs) * [Scully documentation](https://scully.io/docs/learn/overview/) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#angular) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Hydrogen on Netlify | Netlify Docs Hydrogen is a headless stack built by Shopify on top of Remix that enables you to build custom Shopify storefronts. With Netlify, you can deploy your storefront using Netlify Edge Functions for improved performance and faster rendering. Explore a Hydrogen site [Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/hydrogen-template) Get started with a new Hydrogen site on your Netlify account or view the demo. * [Demo repo](https://github.com/netlify/hydrogen-template) * [Demo site](https://hydrogen-remix-template.netlify.app/) [#](#netlify-integration) Netlify integration ---------------------------------------------- Hydrogen apps on Netlify use [Netlify Edge Functions](#edge-functions) to deploy your app to Netlify Edge, bringing serverless capabilities closer to your customers. To successfully deploy a Hydrogen app to Netlify, you should use Netlify’s [starter template](https://github.com/netlify/hydrogen-template) . This template creates everything you need to deploy to Netlify. ### [#](#create-a-new-hydrogen-app-to-deploy-to-netlify) Create a new Hydrogen app to deploy to Netlify Using the command line, you can create a new project based on the Netlify starter template for Hydrogen. Before you begin, make sure you have [Node.js](https://nodejs.org/en/download) version 18.0.0 or later and [Netlify CLI](/cli/get-started/) version 17.0.0 or later. 1. In your terminal, run the following to create your project: npm create @shopify/hydrogen@latest -- --template https://github.com/netlify/hydrogen-template 2. Enter the project directory and prepare the development environment: cp .env.example .env 3. Run your Hydrogen app: npm run dev From here you can customize your site. Check out your project's README for some tips or read the [How to deploy a Shopify Hydrogen storefront to Netlify guide](https://developers.netlify.com/guides/how-to-deploy-a-shopify-hydrogen-storefront-to-netlify/) for more detailed instructions. ### [#](#edge-functions) Edge Functions [Edge Functions](/edge-functions/overview/) connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. To get the latest support for Edge Functions in your Hydrogen site, use the latest [starter template](https://github.com/netlify/hydrogen-template) . You can browse a [full library of reference examples](https://edge-functions-examples.netlify.app/) for different ways to use Edge Functions. For more details, check out the [Edge Functions documentation](/edge-functions/overview/) . [#](#limitations) Limitations ------------------------------ * Currently, only [Netlify Edge Functions](#edge-functions) can be used to power Hydrogen's Server-Side Rendering (SSR). **[Netlify Functions](/functions/overview/) are not officially supported for Hydrogen SSR**. * **The [Remix Classic Compiler](https://remix.run/docs/en/main/guides/vite#classic-remix-compiler-vs-remix-vite) is not officially supported**. Only Remix Vite is supported. Hydrogen [provides a convenient command to migrate an existing Hydrogen app to Remix Vite](https://shopify.dev/docs/api/shopify-cli/hydrogen/hydrogen-setup-vite) . For more details, check out [Remix's Vite migration guide](https://remix.run/docs/en/main/guides/vite#migrating) . [#](#more-resources) More resources ------------------------------------ * [How to deploy a Shopify Hydrogen storefront to Netlify](https://developers.netlify.com/guides/how-to-deploy-a-shopify-hydrogen-storefront-to-netlify/) * [Hydrogen documentation](https://shopify.dev/custom-storefronts/hydrogen) * [Netlify Hydrogen starter template](https://github.com/netlify/hydrogen-template) * [Troubleshooting Hydrogen on Netlify](https://github.com/netlify/hydrogen-template/blob/main/README.md#faq-and-troubleshooting) Last updated: September 17, 2024 ← [Frameworks overview](/frameworks/#hydrogen) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Hugo on Netlify | Netlify Docs Hugo is a fast and flexible open source static site generator written in Go. [#](#key-features) Key features -------------------------------- These features provide important benefits for Hugo sites, including ones built and deployed with Netlify. * **Build speed.** Hugo boasts near-instant build times of less than one millisecond per page. For large sites with a lot of pages, this can translate into significant time savings during site development and Netlify build and deploy processes. * **Choice of themes.** The Hugo ecosystem includes a wide range of premade [themes](https://themes.gohugo.io/) for styling static content. * **Robust templating.** Hugo uses Go templates with `html/template` and `text/template` libraries to control templating. * **Instant previews.** The [LiveReload](https://gohugo.io/getting-started/usage/#livereload) tool is integrated into Hugo for a hot reloading experience during development. * **URL management.** Hugo has built-in support for [URL manipulations](https://gohugo.io/content-management/urls/) and [redirects](https://gohugo.io/content-management/urls/#aliases) . * **Functions and variables.** When building out templates, you can use Go functions, built-in [Hugo-specific functions](https://gohugo.io/functions/) , and a variety of [variables](https://gohugo.io/variables/) . [#](#netlify-integration) Netlify integration ---------------------------------------------- Hugo sites on Netlify can benefit from automatic framework detection and control over Hugo version selection. They also require theme setup considerations. ### [#](#automatic-framework-detection) Automatic framework detection When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Hugo, Netlify provides a suggested build command and publish directory: `hugo` and `public`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `hugo server -w` and `1313`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up a site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#hugo) for Hugo. ### [#](#hugo-version) Hugo version In order to install Hugo on the [build image](/configure-builds/overview/#build-image-selection) , you will need to set a `HUGO_VERSION` environment variable. You can set the variable to the version string for any released version after 0.19, for example, `0.80.0`. 1. First, confirm your local Hugo version with `hugo version`. 2. Then add an [environment variable](/environment-variables/overview/) in the Netlify UI as you set up your site or in a [Netlify configuration file](/configure-builds/file-based-configuration/) stored in your repository. * Follow the steps to [import from an existing repository](/welcome/add-new-site) and on the **Configure site and deploy** step, select **Add environment variables**. Select **New variable** and then enter the key and value. ![](/images/integrations-frameworks-hugo-build-settings.png) * Alternatively, add the following to `netlify.toml` in your site’s [base directory](/configure-builds/overview/#definitions-1) , where `YOUR_HUGO_VERSION` is a version string such as `0.80.0`. [build] command = "hugo" publish = "public" [build.environment] HUGO_VERSION = "YOUR_HUGO_VERSION" Failed build? If you get an error with `exit code: 255` when building a Hugo site on Netlify, remember to set `HUGO_VERSION` to the version you are using locally. ### [#](#hugo-themes) Hugo themes Hugo themes work by default on Netlify. Like any continuous integration system, however, Netlify can’t use a theme installed by the `git clone` method. Instead, you should install a Hugo theme for your site as a [git submodule](https://git-scm.com/docs/gitsubmodules) . Here’s an example: cd YOUR_PROJECT_DIRECTORY git init git submodule add https://github.com/THEME_CREATOR/THEME_NAME [#](#more-resources) More resources ------------------------------------ * [Typical Hugo build settings](/frameworks/#hugo) * [Host Hugo on Netlify](https://gohugo.io/hosting-and-deployment/hosting-on-netlify/) * [Hugo documentation](https://gohugo.io/documentation/) Last updated: January 6, 2025 ← [Frameworks overview](/frameworks/#hugo) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Frameworks | Netlify Docs This page describes commonly used [build settings](/configure-builds/overview/#build-settings) and other configuration tips for popular build tools and project architectures. Your particular settings may be different. As a framework user, you can also check out common configurations for [monorepos](/configure-builds/monorepos/) , generic [JavaScript SPAs](/configure-builds/javascript-spas/) , [ignoring builds](/configure-builds/ignore-builds/) , and using [environment variables with frameworks](/frameworks/environment-variables/) . As a framework author, explore our [frameworks API](/frameworks-api/) to get started with defining how your framework deploys sites to Netlify. For even more build configuration advice and to ask questions of your own, visit our [Support Forums](https://answers.netlify.com/categories) . [#](#definitions) Definitions ------------------------------ The following sections outline the typical **build command** and **publish directory** settings for popular frameworks. * **Build command:** the command to run to build your site if you are using a static site generator or other build tool. For example, `npm run build`. The build command runs in the Bash shell, allowing you to add Bash-⁠compatible syntax to the command. * **Publish directory:** directory that contains the deploy-ready HTML files and assets generated by the build. The directory is relative to the base directory, which is root by default (`/`). Only files in the publish directory are deployed Files and assets located outside of the publish directory won’t be included in site deploys. [#](#angular) Angular ---------------------- Our docs provide an overview for using [Angular on Netlify](/frameworks/angular/) , while our blog post [First steps using Netlify & Angular](https://www.netlify.com/blog/2019/09/23/first-steps-using-netlify-angular/) includes task-based setup instructions. The typical build settings are as follows. They differ depending on how you’ve set up your project and whether you’re using [Scully](https://scully.io/) , the static site generator for Angular. * For a standard Angular project: * **Build command:** `ng build --prod` * **Publish directory:** `dist/YOUR_PROJECT_NAME` * Using Angular Universal for prerendering: * **Build command:** `npm run prerender` * **Publish directory:** `dist/YOUR_PROJECT_NAME/browser` * Using Scully: * **Build command:** `ng build —prod && npm run scully` * **Publish directory:** `dist/static` [#](#astro) Astro ------------------ Our docs provide an overview for using [Astro on Netlify](/frameworks/astro/) . You can also check out our introductory [blog post about Astro and SSR](https://www.netlify.com/blog/astro-ssr) . The default build settings are as follows: * **Build command:** `astro build` * **Publish directory:** `dist` [#](#create-react-app) Create React App ---------------------------------------- Check out our docs overview for using [Create React App on Netlify](/frameworks/react/#create-react-app) or read the instructions for [deploying to Netlify](https://create-react-app.dev/docs/deployment/#netlify) in the Create React App docs. The typical build settings are as follows: * **Build command:** `react-scripts build` * **Publish directory:** `build` [#](#eleventy) Eleventy ------------------------ Our docs provide an overview for using [Eleventy on Netlify](/frameworks/eleventy/) , and we have a [Let’s Learn Eleventy](https://www.netlify.com/blog/2020/04/09/lets-learn-eleventy-boost-your-jamstack-skills-with-11ty/) blog post with instructions to get started with the framework. The default build settings are as follows: * **Build command:** `eleventy` * **Publish directory:** `_site` [#](#express) Express ---------------------- Express apps can be deployed to Netlify using Netlify Functions. Our docs provide an overview for using [Express on Netlify](/frameworks/express/) . If paired with a frontend, Express apps on Netlify do not need any specific build settings. Netlify packages and bundles your functions automatically during the build process. [#](#gatsby) Gatsby -------------------- Our docs provide an overview for using [Gatsby on Netlify](/frameworks/gatsby/) , while the Gatsby docs include task-based instructions for [deploying Gatsby sites to Netlify](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/deploying-to-netlify/) . For apps that use Gatsby Functions or can benefit from build caching, we provide the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby#readme) . The typical build settings are as follows: * **Build command:** `gatsby build` * **Publish directory:** `public` [#](#gridsome) Gridsome ------------------------ The Gridsome docs include instructions for [deploying Gridsome to Netlify](https://gridsome.org/docs/deploy-to-netlify/) . The typical build settings are as follows: * **Build command:** `gridsome build` * **Publish directory:** `dist` [#](#grunt) Grunt ------------------ We automatically provide Grunt for you in the build environment in case your build command references it. We’ll run `npm install grunt-cli` for you before running your build command, in case your build command contains the string `grunt`. The typical build settings are as follows: * **Build command:** `grunt build` * **Publish directory:** `dist` [#](#hexo) Hexo ---------------- The Hexo docs include instructions for [deploying Hexo to Netlify](https://hexo.io/docs/one-command-deployment#Netlify) . The typical build settings are as follows: * **Build command:** `hexo generate` * **Publish directory:** `public` [#](#hugo) Hugo ---------------- Our docs provide an overview of [Hugo on Netlify](/frameworks/hugo/) , while the Hugo docs include task-based instructions for [deploying Hugo to Netlify](https://gohugo.io/hosting-and-deployment/hosting-on-netlify/) . The typical build settings are as follows: * **Build command:** `hugo` * **Publish directory:** `public` [#](#hydrogen) Hydrogen ------------------------ Our docs provide an overview of how [Hydrogen works on Netlify](/frameworks/hydrogen) . The typical build settings are: * **Build command:** `remix vite:build` * **Publish directory:** `dist/client` [#](#jekyll) Jekyll -------------------- If your site is built with Jekyll, make sure you have a [Gemfile and a Gemfile.lock](/configure-builds/manage-dependencies/#ruby-dependencies) checked into your repository, specifying the Jekyll version you want to use. The typical build settings are as follows: * **Build command:** `jekyll build` * **Publish directory:** `_site` [#](#middleman) Middleman -------------------------- If your site is built with Middleman, make sure you have a [Gemfile and a Gemfile.lock](/configure-builds/manage-dependencies/#ruby-dependencies) checked into your repository, specifying the Middleman version you want to use. The typical build settings are as follows: * **Build command:** `middleman build` * **Publish directory:** `build` [#](#mkdocs) MkDocs -------------------- If you’re using MkDocs, make sure to [include the dependency](/configure-builds/manage-dependencies/#python-dependencies) in a `Pipfile` or `requirements.txt` file, specifying version 0.9.0 or above. You may also need to set your [Python version](/configure-builds/manage-dependencies/#python) . The typical build settings are as follows: * **Build command:** `mkdocs build` * **Publish directory:** `site` [#](#next-js) Next.js ---------------------- Netlify’s build system can build and deploy all types of Next.js apps to our platform. You can learn more about using [Next.js on Netlify](/frameworks/next-js/overview/) in our docs. The current Next.js adapter is managed in the open as part of [the OpenNext initiative](https://opennext.js.org/) . For information on working with the latest adapter, visit the [Netlify docs on OpenNext](https://opennext.js.org/netlify) . To upgrade to the latest adapter, visit [our Next.js adapter docs](/frameworks/next-js/overview/#upgrade-to-the-latest-adapter) . For Next.js versions 10-13.4, visit [the legacy runtime docs](/frameworks/next-js/runtime-v4/overview/#next-js-runtime-v4) . For apps that use `next export` to generate static HTML, set the `NETLIFY_NEXT_PLUGIN_SKIP` [environment variable](/configure-builds/environment-variables/) to `true`. The typical build settings are as follows. They differ depending on how your site is generated. * For apps that use **server-side rendering** with the Next.js adapter: * **Build command:** `next build` * **Publish directory:** `.next` * For apps that use **static HTML export**: * **Build command:** `next build && next export` * **Publish directory:** `out` [#](#nuxt) Nuxt ---------------- You can get an overview in our [Nuxt on Netlify](/frameworks/nuxt/) doc or read the Nuxt docs for instructions on how to deploy [Nuxt 2](https://nuxtjs.org/docs/2.x/deployment/netlify-deployment) and [Nuxt 3](https://nitro.unjs.io/deploy/providers/netlify) on Netlify. The typical build settings are as follows: * Nuxt 3 * **Build command:** `nuxt build` * **Publish directory:** `dist` * Nuxt 2 * **Build command:** `nuxt generate` * **Publish directory:** `dist` [#](#react) React ------------------ Check out our docs for building on Netlify using these popular React-based frameworks: [Gatsby](/frameworks/gatsby/) , [Next.js](/frameworks/next-js/overview/) , [React Router](/frameworks/react-router/) , [Remix](/frameworks/remix/) . You can also get started with our docs about [Create React App on Netlify](/frameworks/react/#create-react-app) . [#](#react-router) React Router -------------------------------- Our docs provide all the information you need to deploy a [React Router application on Netlify](/frameworks/react-router/) . The typical build settings are as follows. * **Build command:** `react-router build` * **Publish directory:** `build/client` [#](#remix) Remix ------------------ Our docs provide all the information you need to deploy a [Remix application on Netlify](/frameworks/remix/) . The typical build settings are as follows. For projects built with Remix Vite: * **Build command:** `remix vite:build` * **Publish directory:** `build/client` For projects built with the Remix Classic Compiler: * **Build command:** `remix build` * **Publish directory:** `public` [#](#redwoodjs) RedwoodJS -------------------------- The fastest way to deploy a RedwoodJS project on Netlify is to run `yarn rw setup deploy netlify` in your terminal at your project’s root directory. This will create a `netlify.toml` file that contains all the configuration you need. For more details, check out the RedwoodJS docs for [deploying to Netlify](https://docs.redwoodjs.com/docs/deploy/netlify) . [#](#sveltekit-and-svelte) SvelteKit and Svelte ------------------------------------------------ Check out our docs overview for using [SvelteKit on Netlify](/frameworks/sveltekit/) or learn more in the [SvelteKit Netlify adapter README](https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify#readme) . Typical build settings are as follows. For projects built with SvelteKit: * **Build command:** `vite build` * **Publish directory:** `build` For projects built with Svelte: * **Build command:** `npm run build`, `pnpm build`, or `yarn build` * **Publish directory:** `public` [#](#vite) Vite ---------------- Check out our docs overview for using [Vite on Netlify](/frameworks/vite/) or learn more in the [Vite docs](https://vitejs.dev/guide/static-deploy.html#netlify) . Typical build settings are as follows: * **Build command:** `vite build` * **Publish directory:** `dist` [#](#vue-cli) Vue CLI ---------------------- Our docs provide an overview for using the [Vue CLI with Netlify](/frameworks/vue-cli/) , and you can also learn more in the [Vue CLI docs](https://cli.vuejs.org/guide/) . The typical build settings are as follows: * **Build command:** `vue-cli-service build` * **Publish directory:** `dist` [#](#vuepress) VuePress ------------------------ The VuePress docs include instructions for [deploying VuePress to Netlify](https://vuepress.vuejs.org/guide/deployment.html#netlify) . The typical build settings are as follows: * **Build command:** `npm run docs:build` or `yarn docs:build` * **Publish directory:** `docs/.vuepress/dist` Last updated: December 19, 2024 #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Gatsby on Netlify | Netlify Docs Gatsby is a React-based, open source static site generator that pulls in data using a GraphQL API layer that can connect to a wide array of content sources. [#](#key-features) Key features -------------------------------- These Gatsby features provide key benefits for sites and apps, including ones built and deployed with Netlify. * **Content aggregation.** Gatsby provides a diverse ecosystem of data plugins that allow developers to use a centralized GraphQL API to pull in content from files, APIs, and SaaS platforms. This makes development feel familiar, even if content sources are completely different. * **Performance optimizations.** By default, Gatsby optimizes JavaScript bundles, adds preloading and browser optimizations, and includes other performance enhancements. In general, Gatsby sites are performant and fast. * **Image optimization.** Gatsby ships an image component that works with the GraphQL data layer to generate highly optimized images. The images are lazy-loaded and configured for different viewport sizes. This cuts down on page load times and bandwidth usage. You can also use [Netlify Image CDN with Gatsby](/frameworks/gatsby/?gatsby-version=adapters#netlify-image-cdn) for deferred image resizing instead of processing images at build time. * **Serverless functions.** Gatsby includes an integrated [Functions](https://www.gatsbyjs.com/docs/reference/functions/) feature to help create an API for a site or application. * **Server-side rendering (SSR) and deferred static generation (DSG).** You can choose between several rendering modes, including SSR and DSG. This means you can pick the rendering mode that makes sense for your site. [#](#netlify-integration) Netlify integration ---------------------------------------------- Choose your Gatsby version: * 5.12.0 or later * Earlier than 5.12.0 5.12.0 or later Earlier than 5.12.0 When you trigger a build on Netlify for a site that uses Gatsby version 5.12.0 or later, Gatsby detects that you are using Netlify and automatically installs `gatsby-adapter-netlify`. This is a Gatsby adapter that enables [zero-configuration deployments](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/zero-configuration-deployments/) , making it easier to build and deploy your Gatsby sites. The same automatic detection and installation occurs when you trigger a build using the Netlify CLI. You can also choose to [install the adapter yourself](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-adapter-netlify) . Note that if your site already uses the [Gatsby adapter for Netlify](#gatsby-adapter-for-netlify) , you don’t have to use the [Essential Gatsby build plugin](https://github.com/netlify/netlify-plugin-gatsby) . Gatsby 5 requires updated Node.js version [Gatsby 5](https://www.gatsbyjs.com/gatsby-5/) requires Node.js 18. If your build is using another Node.js version, [follow our Node.js docs](/configure-builds/manage-dependencies/#node-js-and-javascript) to manually set the Node.js version to 18. ### [#](#gatsby-adapter-for-netlify) Gatsby adapter for Netlify The official Gatsby adapter for Netlify, `gatsby-adapter-netlify`, enables [zero-configuration deployments](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/zero-configuration-deployments/) for your site. When you trigger a build on Netlify for a site that uses Gatsby version 5.12.0 or later, Gatsby automatically installs the adapter. The adapter prepares your site for deployment on Netlify in a number of ways, including: * Applying HTTP headers to assets * Applying redirects and rewrites * Applying trailing slash behavior to URLs * Setting up user-defined API functions to be used on Netlify * Setting up Deferred Static Generation (DSG) and Server-Side Rendering (SSR) * Storing Gatsby cache after build is complete and restoring it on subsequent builds to decrease build time between builds For more information on adapters, including information on how to create your own, visit [Gatsby’s documentation on adapters](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/adapters/) . #### [#](#install-the-gatsby-adapter-for-netlify) Install the Gatsby adapter for Netlify Gatsby will automatically install `gatsby-adapter-netlify` for new Gatsby sites on Netlify. If you want to install the adapter manually, you can use the use the following command: npm install gatsby-adapter-netlify If you want to further configure the adapter, you can add `gatsby-adapter-netlify` to your `gatsby-config.js` file and configure the `adapter` option. For example: const adapter = require("gatsby-adapter-netlify"); module.exports = { adapter: adapter({ excludeDatastoreFromEngineFunction: false }) }; For more information, visit the [`gatsby-adapter-netlify` docs](https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-adapter-netlify) . #### [#](#limitations) Limitations `StaticImage` and `gatsby-transformer-sharp` don’t work properly for SSR or DSG pages. Instead, you can host your images on a CDN such as [Cloudinary](https://www.gatsbyjs.com/docs/how-to/images-and-media/using-cloudinary-image-service/) or [imgix](https://github.com/imgix/gatsby) . #### [#](#auto-generated-netlify-functions) Auto-generated Netlify Functions To support Gatsby Functions and SSR/DSG render modes, the Gatsby adapter automatically generates Netlify Functions called `SSR` and `DSG`. If your site doesn’t have Gatsby Functions or SSR/DSG pages, then the Netlify Functions won’t be generated. #### [#](#optional-loading-of-the-gatsby-datastore-from-the-cdn) Optional loading of the Gatsby datastore from the CDN By default, Netlify includes the Gatsby datastore in the Netlify Function bundle, which is a deployment package that’s zipped for direct upload to AWS. If you have a larger site, the site’s datastore may exceed the [maximum function deploy size](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution) , preventing you from successfully deploying your website. `GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE` is an environment variable that loads the Gatsby datastore from the CDN rather than bundling it with the function, bypassing the size limitation. Note that enabling loading the datastore from the CDN results in different page load behavior. On the first load of functions that handle SSR and DSG pages, the datastore is downloaded, which can result in a slower initial page load. During the build process, pre-warm requests are sent to the SSR and DSG function endpoints to reduce the user-facing impact of the datastore download. #### [#](#local-development) Local development When developing Gatsby Functions, you can use the built-in `gatsby develop` functions server. However, if you want to run the Netlify Functions that are generated during the build step, you can use [`netlify dev`](/cli/local-development/) . Make sure to run `netlify build` first to generate the Netlify Functions from your Gatsby Functions. ### [#](#suggested-configuration-values) Suggested configuration values When you link a repository for a Gatsby project, Netlify provides a suggested build command and publish directory: `gatsby build` and `public`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify suggests a dev command and port: `gatsby develop` and `8000`. You can override suggested values or set them in a configuration file instead, but suggested values from automatic framework detection may help simplify the process of setting up a Gatsby site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#gatsby) for Gatsby. ### [#](#environment-variables) Environment variables Environment variables prefixed with `GATSBY_` are processed by Gatsby and made available in the browser for client-side JavaScript access. For more information on how to use environment variables in Gatsby, including with SSR or DSG pages, check out the [Environment variables and frameworks doc](/frameworks/environment-variables/) . ### [#](#netlify-image-cdn) Netlify Image CDN Not supported for Gatsby 5.12 If your site uses Gatsby version 5.12.x with a Gatsby adapter, deferred image resizing with a CDN is not supported. Upgrade to Gatsby 5.13.0 or later to use this feature. Gatsby supports deferred image resizing with [Netlify Image CDN](/image-cdn/overview/) . To enable the image CDN, you need to do the following: * Set the environment variable `NETLIFY_IMAGE_CDN` to `true` * Use the Contentful, Drupal, or WordPress source plugins For more information, including how to allow remote images, visit the [Gatsby adapter for Netlify README](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-adapter-netlify/README.md#imagecdn) . When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify detects the framework your site is using. If you are using Gatsby version 5.11.0 or earlier, Netlify will automatically install the [Essential Gatsby build plugin](#essential-gatsby-build-plugin) and provides [suggested configuration values](#suggested-configuration-values-2) . For existing sites already linked to Netlify, you can choose to [install](http://app.netlify.com/plugins/@netlify/plugin-gatsby/install) the plugin yourself. Gatsby 5 requires updated Node.js version [Gatsby 5](https://www.gatsbyjs.com/gatsby-5/) requires Node.js 18. If your build is using another Node.js version, [follow our Node.js docs](/configure-builds/manage-dependencies/#node-js-and-javascript) to manually set the Node.js version to 18. ### [#](#essential-gatsby-build-plugin) Essential Gatsby build plugin The [Essential Gatsby](https://github.com/netlify/netlify-plugin-gatsby#readme) build plugin enables key functionality on sites that use Gatsby versions earlier than 5.12.0. It speeds up Netlify builds by preserving a site’s `public` and `.cache` directories between builds. The plugin supports [Gatsby Functions](https://www.gatsbyjs.com/docs/reference/functions/) and SSR and DSG rendering. If you don’t need those, you can [remove the plugin](/build-plugins/#remove-a-plugin) from your site. Gatsby sites on Netlify need two plugins to support all features: * **[The Essential Gatsby build plugin](#install-the-essential-gatsby-build-plugin) (`@netlify/plugin-gatsby`).** This plugin installs automatically for all Gatsby sites deployed on Netlify. * **[The Gatsby plugin for Netlify](#install-the-gatsby-plugin-for-netlify) (`gatsby-plugin-netlify`).** This needs to be installed manually and is required for SSR rendering, Gatsby redirects, and asset caching rules. #### [#](#install-the-essential-gatsby-build-plugin) Install the Essential Gatsby build plugin New Gatsby sites on Netlify automatically install the Essential Gatsby build plugin. You can confirm this in the build logs. If you want to install it manually, you can use [file-based plugin installation](/build-plugins/#file-based-installation) and add the plugin as `@netlify/plugin-gatsby` in your `netlify.toml` file. [[plugins]] package = "@netlify/plugin-gatsby" #### [#](#install-the-gatsby-plugin-for-netlify) Install the Gatsby plugin for Netlify To enable SSR rendering, Gatsby redirects, and asset caching rules, you must also install the Gatsby plugin [gatsby-plugin-netlify](https://www.gatsbyjs.com/plugins/gatsby-plugin-netlify/) . To install the Gatsby plugin for Netlify, follow the Gatsby plugin process: 1. Add the package as a dependency. npm install -D gatsby-plugin-netlify 2. Add `gatsby-plugin-netlify` to your `gatsby-config.js` file’s plugins array. module.exports = { plugins: ["gatsby-plugin-netlify"] }; For more information, including optional plugin configuration, check out the [`gatsby-plugin-netlify` docs](https://github.com/netlify/gatsby-plugin-netlify/#readme) . #### [#](#limitations-2) Limitations `StaticImage` and `gatsby-transformer-sharp` don’t work properly for SSR or DSG pages. Instead, you can host your images on a CDN such as [Cloudinary](https://www.gatsbyjs.com/docs/how-to/images-and-media/using-cloudinary-image-service/) or [imgix](https://github.com/imgix/gatsby) . #### [#](#auto-generated-netlify-functions-2) Auto-generated Netlify Functions To support Gatsby Functions and SSR/DSG render modes, the Essential Gatsby build plugin automatically generates Netlify Functions called `__api`, `__ssr`, `__dsg`, and `__ipx`. If your site doesn’t have Gatsby Functions or SSR/DSG pages, then the Netlify Functions won’t be generated. You can use one or more of the following build environment variables to directly control generation of these functions. * **`NETLIFY_SKIP_GATSBY_FUNCTIONS`:** skips generation of all functions (`__api`, `__ssr`, `__dsg`, and `__ipx`). Takes precedence over the following function skip environment variables. * **`NETLIFY_SKIP_API_FUNCTION`:** skips generation of the `__api` function. * **`NETLIFY_SKIP_SSR_FUNCTION`:** skips generation of the `__ssr` function. * **`NETLIFY_SKIP_DSG_FUNCTION`:** skips generation of the `__dsg` function. #### [#](#optional-loading-of-the-gatsby-datastore-from-the-cdn-2) Optional loading of the Gatsby datastore from the CDN By default, Netlify includes the Gatsby datastore in the Netlify Function bundle, which is a deployment package that’s zipped for direct upload to AWS. If you have a larger site, the site’s datastore may exceed the [maximum function deploy size](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#function-configuration-deployment-and-execution) , preventing you from successfully deploying your website. `GATSBY_EXCLUDE_DATASTORE_FROM_BUNDLE` is an environment variable that loads the Gatsby datastore from the CDN rather than bundling it with the function, bypassing the size limitation. Note that enabling loading the datastore from the CDN results in different page load behavior. On the first load of functions that handle SSR and DSG pages, the datastore is downloaded, which can result in a slower initial page load. During the build process, pre-warm requests are sent to the SSR and DSG function endpoints to reduce the user-facing impact of the datastore download. #### [#](#local-development-2) Local development When developing Gatsby Functions, you can use the built-in `gatsby develop` functions server. However, if you want to run the Netlify Functions that are generated during the build step, you can use [`netlify dev`](/cli/local-development/) . Make sure to run `netlify build` first to generate the Netlify Functions from your Gatsby Functions. ### [#](#suggested-configuration-values-2) Suggested configuration values When you link a repository for a Gatsby project, Netlify provides a suggested build command and publish directory: `gatsby build` and `public`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify suggests a dev command and port: `gatsby develop` and `8000`. You can override suggested values or set them in a configuration file instead, but suggested values from automatic framework detection may help simplify the process of setting up a Gatsby site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#gatsby) for Gatsby. ### [#](#environment-variables-2) Environment variables Environment variables prefixed with `GATSBY_` are processed by Gatsby and made available in the browser for client-side JavaScript access. For more information on how to use environment variables in Gatsby, including with SSR or DSG pages, check out the [Environment variables and frameworks doc](/frameworks/environment-variables/) . ### [#](#netlify-image-cdn-2) Netlify Image CDN Gatsby supports deferred image resizing with [Netlify Image CDN](/image-cdn/overview/) . To enable the image CDN, you need to do the following: * Set the environment variable `NETLIFY_IMAGE_CDN` to `true` * Use the Contentful, Drupal, or WordPress source plugins For more information, including how to allow remote images, visit the [Essential Gatsby build plugin’s documentation](https://github.com/netlify/netlify-plugin-gatsby/blob/main/docs/image-cdn.md) . [#](#more-resources) More resources ------------------------------------ * [Typical Gatsby build settings](/frameworks/#gatsby) * [Gatsby Adapters: Realize the Full Potential of Gatsby on Your Platform](https://www.netlify.com/blog/gatsby-adapters-realize-the-full-potential-of-gatsby-on-your-platform/) * [Essential Gatsby build plugin documentation](https://github.com/netlify/netlify-plugin-gatsby#readme) * [Five Optimizations for Faster Gatsby Builds](https://www.netlify.com/blog/2020/06/11/5-optimizations-for-faster-gatsby-builds/) * [Gatsby 101: Features, Benefits, and Trade-Offs](https://www.netlify.com/blog/2020/06/25/gatsby-101-features-benefits-and-trade-offs/) * [Improve Gatsby Build Speeds With Parallel Image Processing](https://www.netlify.com/blog/2020/02/25/gatsby-build-speed-improvements-with-parallel-image-processing/) * [Netlify Blog: Gatsby posts](https://www.netlify.com/tags/gatsby/) * [Deploying to Netlify](https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/deploying-to-netlify/) * [Gatsby documentation](https://www.gatsbyjs.com/docs/) Last updated: November 6, 2024 ← [Frameworks overview](/frameworks/#gatsby) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Next.js on Netlify | Netlify Docs [![Netlify Next.js adapter v5 test status](https://runtime-e2e-report.netlify.app/badge)](https://runtime-e2e-report.netlify.app/) Netlify’s Next.js adapter automatically configures Netlify sites to enable key functionality, including cache control, on-demand revalidation, and image optimization. Next.js adapter v5 The information on this page applies to Next.js version 13.5 or later, running with Netlify’s Next.js adapter v5. For earlier Next.js versions, go to the [legacy runtime docs](/frameworks/next-js/runtime-v4/overview/) . [#](#opennext-netlify-adapter) OpenNext Netlify adapter -------------------------------------------------------- Netlify’s current Next.js adapter is maintained in the open as part of [the OpenNext initiative](https://opennext.js.org/) . For information on working with the latest adapter, visit the [Netlify docs on OpenNext](https://opennext.js.org/netlify) . [#](#upgrade-to-the-latest-adapter) Upgrade to the latest adapter ------------------------------------------------------------------ We actively maintain the v5 adapter to support all Next.js versions starting from version 13.5. Unless you’ve manually installed a specific version of the adapter in your `package.json`, you never need to manually update it. We will automatically use the latest version on each site build for you. Automatic installation preferred We recommend that you remove the package from your `package.json` and `netlify.toml` files to allow Netlify to automatically update the adapter when new versions are available. This gives you the benefit of always having the latest features and fixes. Note that we won't provide automatic updates for breaking changes. ### [#](#upgrade-from-v4-x-to-v5-x) Upgrade from v4.x to v5.x 1. If your site is pinned to an earlier runtime version, upgrade Next.js to 13.5 or later, and Node.js to 18 or later. 2. Address the [breaking changes](#v5-breaking-changes) noted below. 3. Change the package name in your `package.json` and `netlify.toml` from `@netlify/plugin-nextjs` to `@opennextjs/netlify`, and ensure the version is at least v5.9. ### [#](#v5-breaking-changes) v5 breaking changes Before upgrading to v5, review the following breaking changes: * **Netlify Forms:** If you’re currently using Netlify Forms, you will likely need to make some changes to your code. Review [the Netlify Forms compatibility doc on OpenNext](https://opennext.js.org/netlify/forms) for details. * **Advanced API routes:** If your site uses [advanced API routes](/frameworks/next-js/runtime-v4/advanced-api-routes/) (background or scheduled functions implemented as Next.js API routes), you will need to convert these to regular Netlify Functions. Review the [notes and code examples](https://github.com/netlify/next-scheduled-bg-function-migration) . ### [#](#known-issues-when-upgrading) Known issues when upgrading If you opt in through the Netlify UI without the correct Next.js or Node version, the following message will appear in your deploy log: ![To upgrade this plugin, please uninstall and re-install it from the Netlify plugins directory](/images/frameworks-nextjs-troubleshooting-log.png) This deploy log message is incorrect. Instead of uninstalling and reinstalling the plugin, you need to update your Next.js to at least version 13.5 and Node.js to at least version 18. [#](#pin-a-specific-adapter-version-to-your-site) Pin a specific adapter version to your site ---------------------------------------------------------------------------------------------- If you find that you need to return to a specific version of the Next.js adapter or runtime, you can pin that version to your site. We recommend that you don’t pin the adapter version. We actively maintain the v5 adapter to support all Next.js versions starting from version 13.5 and, if you don’t pin the version, we will automatically update the adapter to the latest version on each site build for you. 1. Install your desired version of the `@netlify/plugin-nextjs` package: npm i @netlify/plugin-nextjs@1.2.3 2. In your [`netlify.toml`](/configure-builds/file-based-configuration/) , add: [[plugins]] package = "@netlify/plugin-nextjs" [#](#more-resources) More resources ------------------------------------ * [OpenNext adapter docs](https://opennext.js.org/netlify) * [Typical Next.js build settings](/frameworks/#next-js) * [Next.js framework documentation](https://nextjs.org/docs/getting-started) * [Connect JavaScript client](/connect/access-data/#use-the-connect-client) - the recommended library for querying Connect data layer APIs in Next.js cached SSR sites. Last updated: October 23, 2024 ← [Frameworks overview](/frameworks/#next-js) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Troubleshooting Next.js on Netlify | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. If you encounter issues running Next.js on Netlify, the information on this page may help you solve them. [#](#large-function-error) Large function error ------------------------------------------------ You may encounter an error about generated functions being too large. During deployment, each unzipped function bundle is limited to 250 MB in size. The cause of this error could be large dependencies or a large number of pre-rendered pages. The list of largest files shown in the build logs will help you determine the cause. ### [#](#large-dependencies) Large dependencies This is the most common root cause of generated functions being too large. Some node modules are very large, mostly those that include native modules. Examples include `electron` and `chromium`. The function bundler is usually able to find modules that are actually used by your code, but sometimes it will incorrectly include unneeded modules. If this is the case, you can either remove the module from your dependencies if you installed it yourself, or exclude it manually in your `netlify.toml`. [functions] included_files = ["!node_modules/A_LARGE_MODULE/**/*"] In the above example, you should change the value to match the problematic module. The `!` at the beginning of the module path indicates that it should be excluded. If you do need large modules at runtime, you can try changing to a Netlify Function which has less overhead than the equivalent Next.js function. ### [#](#large-numbers-of-pre-rendered-pages) Large numbers of pre-rendered pages A large number of pre-rendered pages can take up a lot of space in the function. To fix this, consider deferring the building of the pages. If you return `fallback: "blocking"` from `getStaticPaths`, the rendering will be deferred until the first user requests the page. This approach reduces build and deploy time, and can make your bundle a lot smaller. [#](#netlify-support-forums) Netlify Support Forums ---------------------------------------------------- Can’t find what you’re looking for? The [Netlify Support Forums](https://answers.netlify.com/tag/nextjs) are a great place to find more information and ask questions that are specific to your needs. Last updated: October 23, 2024 ← [Legacy Next.js on Netlify](/frameworks/next-js/runtime-v4/overview/) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Next.js ISR on Netlify | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. [Incremental static regeneration](https://www.netlify.com/blog/2021/03/08/incremental-static-regeneration-its-benefits-and-its-flaws/) (ISR) is the architecture behind Next.js that allows pages to be updated after a site has been built and deployed. Compared to server-side rendered (SSR) pages and statically-generated pages, ISR pages have distinct advantages. They are not rebuilt for each user, so they load quickly. And they can be periodically updated with new content without a new deploy. [#](#use-isr-on-netlify) Use ISR on Netlify -------------------------------------------- ISR on Netlify is implemented with [On-demand Builders](/configure-builds/on-demand-builders/) , using the Time To Live (TTL) feature. You can enable ISR for a page by returning a value for `revalidate` from the `getStaticProps` function. The value set for `revalidate` is the number of seconds that the page’s content is considered fresh. If a request arrives for a page after the `revalidate` period has elapsed, the page is regenerated. ISR uses a “stale while revalidate” strategy, meaning that the visitor still receives the stale content, but it is regenerated in the background and becomes ready for the next request. The generated page is persisted globally, so it’s available to all visitors wherever they are in the world. This can take a little time before the new content is updated across all CDN nodes if they already had a cached copy. It is also cached in the global Netlify CDN for fast responses. The minimum value for `revalidate` is 60 seconds. Any value less than that will default to 60 seconds. ### [#](#configure-builds-to-use-isr) Configure builds to use ISR If the static regeneration relies on local files in your repository, the files need to be bundled with the handler functions. This can be done by modifying your [file based configuration](/configure-builds/file-based-configuration/) . Under the `functions` option, add an entry to the `included_files` option. Be careful to not include unnecessary files. Particularly large files like images or videos can make your handler function sizes grow quickly. There is a 250 MB size limit for each handler’s unzipped function bundle. Review the [Functions Configuration Docs](/configure-builds/file-based-configuration/#functions) for more information. Update your `netlify.toml` file to include the following (assuming local content is located in the `/content` directory): [functions] included_files = ["content/**"] If a new deploy is made, all persisted pages and CDN cached pages will be [invalidated by default](/platform/caching/#automatic-invalidation-with-atomic-deploys) so that conflicts are avoided. If this did not happen, a stale HTML page might make a request for an asset that no longer exists in the new deploy. By invalidating all persisted pages, you can be confident that this will never happen and that deploys remain [atomic](https://www.netlify.com/blog/2021/02/23/terminology-explained-atomic-and-immutable-deploys/) . [#](#on-demand-isr) On-demand ISR ---------------------------------- On-demand ISR (where a path is manually revalidated) is only supported for [Next.js 13.5 and later and Next.js Runtime v5](/frameworks/next-js/overview/) . [#](#alternatives-to-isr) Alternatives to ISR ---------------------------------------------- ISR is best for situations where there are regular updates to content throughout the day, particularly when you don’t have control over when the updates happen. It is less ideal for certain use cases, such as when a CMS is called for. A CMS is ideal for incremental updates since you can trigger a deploy when a page is added or edited. ### [#](#static-site-generation) Static site generation For high-traffic pages, you can use [static generation](https://nextjs.org/docs/basic-features/data-fetching/get-static-props) without `revalidate`. This deploys static files directly to the CDN for maximum performance. ### [#](#distributed-persistent-rendering) Distributed persistent rendering For less commonly-accessed content, you can return `fallback: "blocking"` from [`getStaticPaths`](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths) and defer builds until the first request. This approach uses [On-demand Builders](/configure-builds/on-demand-builders/) but persists the built page until the next deploy. This is great for long-tail content and archives that don’t change often and aren’t accessed often enough to justify statically-generating them at build time. Last updated: October 23, 2024 ← [Legacy Next.js on Netlify](/frameworks/next-js/runtime-v4/overview/) [Next.js advanced API routes](/frameworks/next-js/runtime-v4/advanced-api-routes/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Next.js redirects and rewrites on Netlify | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. Netlify’s Next.js Runtime supports Next.js [rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites) and [redirects](https://nextjs.org/docs/api-reference/next.config.js/redirects) . These are defined in your `next.config.js` file and have some features that are not included in Netlify redirects and rewrites. [#](#use-netlify-redirects-and-rewrites-on-a-next-js-site) Use Netlify redirects and rewrites on a Next.js site ---------------------------------------------------------------------------------------------------------------- Every site on Netlify supports [redirects and rewrites](/routing/redirects/) , which are defined in a `_redirects` or `netlify.toml` file. Sites that use Next.js Runtime are no exception. However, there are some things to keep in mind when you use Netlify redirects and rewrites on a Next.js site. Next.js Runtime generates several rewrites on its own, which are used to map paths from your site to different Netlify Functions. The functions handle SSR, preview mode, and images, as well as assets in `/_next/static`. Any Netlify redirects or rewrites that you create [take precedence](#redirect-and-rewrite-precedence) over those created by Next.js Runtime. Avoid root-level rewrite Do not add a rewrite from the site root (such as `from = "/"`) in `netlify.toml` or `_redirects`. Your root-level rewrite would take precedence over Next.js Runtime’s generated rewrites and break routing on your site. [#](#redirect-and-rewrite-precedence) Redirect and rewrite precedence ---------------------------------------------------------------------- Redirects and rewrites are processed in the following order: 1. Redirects and rewrites in the `_redirects` file. These are read in order until a match is found, then processing stops. 2. Redirects and rewrites in the `netlify.toml` file. None of these are read if one previous rule has already matched. 3. At this point, if the request targets a static file, then the static file returns without further evaluation of Next.js redirects or rewrites. 4. Any request that does not target a static file will then be passed to Next.js, which will then evaluate redirects and rewrites (defined in the `next.config.js` file). [#](#general-principles) General principles -------------------------------------------- Netlify and Next.js redirects support different features and are evaluated at different points in the request lifecycle. To determine which one to use with your site, consider the following: ### [#](#when-to-use-netlify-redirects-or-rewrites) When to use Netlify redirects or rewrites * Generally, if your redirect can be handled with Netlify redirects, this is the preferred option because they are faster to evaluate. * [Identity](/security/secure-access-to-sites/identity/) , [proxying](/routing/redirects/rewrites-proxies/) , and [country-based redirects](/routing/redirects/) are Netlify-specific features and must use Netlify redirects. * If you need redirects or rewrites to be applied before loading static files, you must use Netlify redirects and rewrites. ### [#](#when-to-use-next-js-redirects-or-rewrites) When to use Next.js redirects or rewrites * If you are using a _rewrite_ that points to a dynamic Next.js page, you must use Next.js rewrites. Next.js has no way of knowing what the rewritten page is when using Netlify rewrites, so the wrong page is likely to be rendered. Note that this only applies to rewrites, not redirects. * If you need Next.js-specific features, such as regex path or header matching, you must use Next.js rewrites. ### [#](#use-redirects-and-headers-files) Use `_redirects` and `_headers` files If you use [`_redirects`](/routing/redirects/#syntax-for-the-redirects-file) or [`_headers`](/routing/headers/#syntax-for-the-headers-file) files rather than a `netlify.toml` file, be aware that these files must be in the published directory of your site, not the root of your repo. To do this, put them in `public` and they will be moved into `.next` at build time. Do not put them directly into `.next`, because it is emptied at build time. Any `_redirects` or `_headers` files in the root of the repo will not be found when deployed. Last updated: October 23, 2024 ← [Legacy Next.js on Netlify](/frameworks/next-js/runtime-v4/overview/) [Next.js ISR](/frameworks/next-js/runtime-v4/incremental-static-regeneration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # React on Netlify | Netlify Docs React is a JavaScript library for building user interfaces (UI). It allows you to create reusable UI components and manage the state of an application. React uses a declarative approach to building UIs and is widely used especially for single-page applications. Here are a few of the common React-based frameworks you can deploy on Netlify: * [Gatsby](/frameworks/gatsby/) * [Next.js](/frameworks/next-js/overview/) * [React Router](/frameworks/react-router/) * [Remix](/frameworks/remix/) You can also use Create React App. Create React App is ideal for quickly getting started building a React application, especially if you want to focus on learning the basics of React. Below, learn about deploying projects built with Create React App on Netlify. [#](#create-react-app) Create React App ---------------------------------------- Create React App is a command line tool that generates a boilerplate React single-page application (SPA) with a pre-configured build pipeline. It simplifies the complexity of setting up a React project, allowing you to focus on building out the app itself. ### [#](#netlify-integration) Netlify integration When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Create React App, Netlify provides a suggested build command and publish directory: `react-scripts build` and `build`. If you’re using the Netlify CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `react-scripts start` and `3000`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up a project with Create React App on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#react-and-create-react-app) for Create React App. ### [#](#environment-variables) Environment variables Environment variables prefixed with `REACT_APP_` are processed and made available in the browser for client-side JavaScript access. For more information on how to use environment variables in React, check out the [Environment variables and frameworks doc](/frameworks/environment-variables/) . [#](#deploy-a-create-react-app-site-on-netlify) Deploy a Create React App site on Netlify ------------------------------------------------------------------------------------------ This section demonstrates how to deploy a Create React App site on Netlify. It covers: * Starting a new project using Create React App * Deploying your Create React App project to Netlify with Netlify CLI ### [#](#start-a-new-project-using-create-react-app) Start a new project using Create React App Before you begin, make sure you have [Node.js](https://nodejs.org/en/download) version 18.14.0 or later installed on your machine. Then, you can start a new project using Create React App. 1. To get started, run the following in your terminal to create your project: npx create-react-app my-app 2. To navigate to your project directory and start your development server: cd my-app npm start From here you can customize your site. You can also create a Git repository for your site to take advantage of [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) . Avoid 404s for SPAs If your project is a single page app (SPA) that uses the history `pushState` method to get clean URLs, you must add a [rewrite rule](/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to serve the `index.html` file no matter what URL the browser requests. ### [#](#deploy-your-create-react-app-project-with-netlify-cli) Deploy your Create React App project with Netlify CLI You can [deploy your project from the command line](/site-deploys/create-deploys/#netlify-cli) using [Netlify CLI](/cli/get-started/) . 1. To ensure you have the latest version of Netlify CLI installed, run this command from any directory in your terminal: npm install netlify-cli -g 2. In the directory for your project, run the following command to create a new Netlify site: netlify init Didn’t initialize a Git repository? When you run `netlify init` without initializing a Git repository first, the CLI prompts you to connect your local directory to GitHub. Follow the steps in your terminal to link your local directory with a remote repo in order to use continuous deployment for your site. 3. Follow the prompts to create your site, select a team if necessary, and optionally create a site name. If you already initialized a Git repository, you can authorize your Git provider and set your build command and directory. 4. If you used continuous deployment, your site is now published! To learn how to manually deploy a site, check out the [manual deploy docs](/cli/get-started/#manual-deploys) . [#](#more-resources) More resources ------------------------------------ * [Typical Create React App build settings](/frameworks/#react-and-create-react-app) * [Deploy React apps in less than 30 seconds](https://www.netlify.com/blog/2016/07/22/deploy-react-apps-in-less-than-30-seconds/) * [React documentation](https://react.dev/learn) * [Create React App documentation](https://create-react-app.dev/) Last updated: December 19, 2024 ← [Frameworks overview](/frameworks/#react-and-create-react-app) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Legacy Next.js on Netlify | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. Next.js is a React-based open source framework that provides a hybrid static / server-side rendered model for enterprise-grade sites and applications. [#](#key-features) Key features -------------------------------- These Next.js features provide important benefits for sites and apps, including those built and deployed with Netlify. * **Page routing.** Next.js boasts a file system-based [routing structure](https://nextjs.org/docs/routing/introduction) . Organizing files and subdirectories within a `pages` directory automatically results in corresponding routes. * **Automatic API endpoints.** For simpler [API management](https://nextjs.org/docs/api-routes/introduction) , any file added to the `pages/api` directory is treated as an API endpoint with a corresponding API route. Netlify also offers [advanced API routes](/frameworks/next-js/runtime-v4/advanced-api-routes/) . * **Preview mode.** Netlify supports rendering a draft page from any data-fetching solution instead of building a statically-generated page to preview. This [preview mode](https://nextjs.org/docs/advanced-features/preview-mode) functionality eliminates waiting for a build to run before previewing new content. * **Hybrid or static.** You can use a hybrid approach to generate content, choosing between server-side rendering or static generation on a per-page basis, or you can use [`next export`](https://nextjs.org/docs/advanced-features/static-html-export) to generate a completely static site. * **Image optimization.** The `next/image` component allows you to automatically optimize images for your site on-demand, as they’re requested by users. On Netlify, `next/image` uses [ipx](https://github.com/unjs/ipx/) and [On-demand Builders](/configure-builds/on-demand-builders/) by default. For further optimization, you can route image requests through [Netlify Image CDN](#next-image-and-netlify-image-cdn) . * **Incremental Static Regeneration (ISR).** ISR on Netlify works with [On-demand Builders](/configure-builds/on-demand-builders/) to revalidate pages as needed without rebuilding your entire site. This enables faster builds, especially for very large projects. * **Internationalization.** Netlify supports Next.js [internationalized routing](https://nextjs.org/docs/advanced-features/i18n-routing) functionality for locale-specific options. [#](#next-js-runtime-v4) Next.js Runtime v4 -------------------------------------------- Netlify’s Next.js Runtime configures your site on Netlify to enable key Next.js functionality. It automatically generates serverless functions that handle server-side rendered (SSR) pages, [incremental static regeneration (ISR)](/frameworks/next-js/runtime-v4/incremental-static-regeneration/) , images, and Next.js features. ### [#](#redirects-and-rewrites) Redirects and rewrites Next.js Runtime supports Next.js [rewrites](https://nextjs.org/docs/api-reference/next.config.js/rewrites) and [redirects](https://nextjs.org/docs/api-reference/next.config.js/redirects) . These are defined in your `next.config.js` file and support some features that are not included in Netlify redirects and rewrites. We recommend using Netlify redirects when possible because they are faster to evaluate. Rewrites are a little different. Generally with Next.js Runtime, you should use Next.js rewrites instead of Netlify rewrites. Avoid root-level rewrite Do not add a rewrite from the site root (such as `from = "/"`) in `netlify.toml` or `_redirects`. Your root-level rewrite would take precedence over Next.js Runtime’s own rewrites and break routing on your site. Learn more on the [Next.js redirects and rewrites on Netlify](/frameworks/next-js/runtime-v4/redirects-and-rewrites/) page. ### [#](#middleware) Middleware Next.js Runtime supports [Middleware](https://nextjs.org/docs/middleware) , a feature in which functions run before a request has finished processing. Regular Next.js Middleware can be used to modify the request or replace the response. For example, it can change headers, rewrite the request path, or return a different response entirely. Beyond regular Middleware, Netlify’s Next.js Advanced Middleware, available in the [`@netlify/next` library](https://www.npmjs.com/package/@netlify/next) , gives improved access to requests and responses. This is similar to Netlify Edge Functions, but with some additional Next.js-specific helpers. Learn more on the [Next.js Middleware on Netlify](/frameworks/next-js/runtime-v4/middleware/) page. ### [#](#custom-headers) Custom Headers Next.js Runtime supports Next.js [custom headers](https://nextjs.org/docs/api-reference/next.config.js/headers) . Custom headers work for SSR, static site generation (SSG), ISR pages, and IPX images. There’s no need to add custom headers in the Netlify configuration. ### [#](#optimize-images-with-next-image) Optimize images with `next/image` `next/image` includes built-in performance optimization, like optimizing image size. Next.js Runtime uses an [On-demand Builder](/configure-builds/on-demand-builders/) function to handle image processing and caching. This processes an image on the first request which means it may take longer to load, but then the generated image is cached and served as a static file to future visitors for faster response times. ### [#](#next-image-and-netlify-image-cdn) `next/image` and Netlify Image CDN For further optimization, route `next/image` requests through [Netlify Image CDN](/image-cdn/overview/) by adding the following redirect: # netlify.toml [[redirects]] from = '/_next/image/*' query = { q = ':quality', url = ':url', w = ':width' } to = '/.netlify/images?url=:url&w=:width&q=:quality' status = 200 force = true Netlify Image CDN handles content negotiation to use the most efficient image format for the requesting client. We inspect the `Accept` header for content negotiation with the following logic: 1. use `avif` if accepted 2. otherwise, use `webp` if accepted 3. if neither is accepted, use the original format ### [#](#limitations) Limitations * **Large functions.** During deployment, each unzipped function bundle is limited to 250 MB in size. Some functions generated by Next.js Runtime may exceed that limit and throw an error. The [troubleshooting page](/frameworks/next-js/runtime-v4/troubleshooting/#troubleshooting-large-functions) has more information. [#](#suggested-configuration-values) Suggested configuration values -------------------------------------------------------------------- When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a Next.js project, Netlify provides a suggested build command and publish directory: `next build` and `.next`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify suggests a dev command and port: `next` and `3000`. You can override suggested values or set them in a configuration file instead, but suggested values from automatic framework detection may help simplify the process of setting up a Next.js site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#next-js) for Next.js. `serverless` target deprecated The `serverless` and `experimental-serverless-trace` targets are deprecated in Next 12, and all builds with Next.js Runtime use the default `server` target. If you previously set the target in your `next.config.js`, you should remove it. [#](#edge-functions) Edge Functions ------------------------------------ [Edge Functions](/edge-functions/overview/) connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. For different ways to use Edge Functions with Next.js, check out the [React Server Components](https://github.com/netlify/next-react-server-components) and [Edge middleware](https://github.com/netlify/next-edge-middleware) examples. You can also browse the [full library of reference examples](https://edge-functions-examples.netlify.app/) . Note that the Edge Functions feature [has limits](/edge-functions/limits/) that you should be aware of. For example, edge functions won’t work for sites with Split Testing enabled. [#](#nextauth-js-support) NextAuth.js support ---------------------------------------------- [NextAuth.js](https://next-auth.js.org/) is a complete open source authentication solution for Next.js applications. When Next.js Runtime detects the `next-auth` package in your build, it automatically sets the [`NEXTAUTH_URL` environment variable](https://next-auth.js.org/configuration/options#nextauth_url) to your site’s canonical URL. If a custom base path is specified as part of your site configuration, this is included as part of the `NEXTAUTH_URL`. To use NextAuth.js, you need to set a [`NEXTAUTH_SECRET`](https://next-auth.js.org/configuration/options#nextauth_secret) environment variable [in the Netlify UI](/environment-variables/get-started/#create-environment-variables) . This gives your site’s builds secure access to your `NEXTAUTH_SECRET` and value. Note that if you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** to be available during the build process. [#](#pnpm-support) pnpm support -------------------------------- If you’re planning to use pnpm with Next.js to manage dependencies, you must do one of the following: * Set a `PNPM_FLAGS` [environment variable](/environment-variables/get-started/#create-environment-variables) with a value of `--shamefully-hoist`. This appends a `--shamefully-hoist` argument to the `pnpm install` command that Netlify runs. * [Enable public hoisting](https://pnpm.io/npmrc#public-hoist-pattern) by adding an `.npmrc` file in the root of your project with this content: public-hoist-pattern[]=* Learn more about using [pnpm on Netlify](/configure-builds/manage-dependencies/#pnpm) . [#](#troubleshooting) Troubleshooting -------------------------------------- If you run into issues running a Next.js app on Netlify, check out our [troubleshooting page](/frameworks/next-js/runtime-v4/troubleshooting/) . You can also visit the [Netlify Support Forums](https://answers.netlify.com/categories/) to see if others have encountered similar issues. [#](#more-resources) More resources ------------------------------------ * [Typical Next.js build settings](/frameworks/#next-js) * [Video: Next.js from the Ground Up](https://www.youtube.com/playlist?list=PLzlG0L9jlhENGgDUr09a7JdRgSTybmE1P) * [Netlify Blog: Next.js posts](https://www.netlify.com/tags/nextjs/) * [Next.js framework documentation](https://nextjs.org/docs/getting-started) Last updated: October 23, 2024 ← [Frameworks overview](/frameworks/#next-js) [Next.js Middleware](/frameworks/next-js/runtime-v4/middleware/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Next.js Middleware on Netlify | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. Netlify has expanded on Next.js Middleware to give you more options during development. With `@netlify/next`, you get access to enhanced request and response features through an intuitive API. Netlify’s Next.js Advanced Middleware, available in the [`@netlify/next` library](https://www.npmjs.com/package/@netlify/next) , gives improved access to requests and responses. This is similar to Netlify Edge Functions, but with some additional Next.js-specific helpers. `@netlify/next` is separate from [Next.js Runtime](/frameworks/next-js/runtime-v4/overview/#next-js-runtime-v4) and you need to [install it](#install-netlify-next) in your project to use it. [#](#next-js-middleware) Next.js Middleware -------------------------------------------- Next.js 12 introduced Middleware and enabled changing headers, rewriting the request path, or returning a different response entirely. Netlify fully supports Next.js Middleware and runs it either in an Edge Function or at the origin. Edge Functions are highly recommended for Next.js 12.2 or later, as ISR will not work with earlier versions. ### [#](#deploy-next-js-middleware-on-netlify) Deploy Next.js Middleware on Netlify Next.js Middleware works out of the box with Netlify, and most functions will work unchanged. Visit [the Middleware docs](https://nextjs.org/docs/middleware) for details of how to create Middleware functions. ### [#](#netlify-edge-functions-and-middleware) Netlify Edge Functions and Middleware By default, Next.js Middleware on Netlify uses [Edge Functions](/frameworks/next-js/runtime-v4/overview/#edge-functions) to connect the Netlify platform and workflow with an open runtime standard at the network edge. If you don’t want to use Edge Functions for your Middleware, you can [opt out](#opt-out-of-netlify-edge-functions) . Note that the `@netlify/next` library that enables Next.js Advanced Middleware on Netlify requires Edge Functions and is subject to the [limitations](/edge-functions/limits/) of Edge Functions. #### [#](#opt-out-of-netlify-edge-functions) Opt out of Netlify Edge Functions If you opt out of using Netlify Edge Functions for Middleware, regular serverless functions will handle your requests and responses. Opting out of Edge Functions exposes you to the limitations of regular serverless functions: * You can’t use Netlify’s Next.js Advanced Middleware library `@netlify/next`. * Regular Netlify Functions don’t have access to `request.geo`. * When the Middleware runs at the origin, it is run _after_ [Netlify rewrites and redirects](/routing/redirects/) . If a static file is served by the Netlify CDN, then the Middleware is never run, as Middleware only runs when a page is served by Next.js. This means that any pages that match Middleware routes are served from the origin rather than the CDN. To opt out, [create an environment variable](/environment-variables/get-started/#create-environment-variables) named `NEXT_DISABLE_NETLIFY_EDGE` and set it to `true`. If you have the option to set specific [scopes](/environment-variables/overview/#scopes) for your environment variables, the scope must include **Builds** to be available during the build process. [#](#next-js-advanced-middleware-with-the-netlify-next-library) Next.js Advanced Middleware with the `@netlify/next` library ----------------------------------------------------------------------------------------------------------------------------- Regular Next.js Middleware doesn’t provide access to the actual response. Instead, it allows you to return a `NextResponse` object, which is used by the handler to modify the response headers when they are eventually returned. Calling `NextResponse.next()` doesn’t actually send a request to the origin. It’s a placeholder for setting response headers that are applied later. It also doesn’t let you modify the request, but instead can return a `rewrite()`. The wrapper uses the returned `rewrite()` to modify the request. To provide improved access to requests and responses, Netlify created a [library called `@netlify/next`](https://www.npmjs.com/package/@netlify/next) . This library works with requests and responses in much the same way that [Netlify Edge Functions](/edge-functions/overview/) do, but with some additional Next.js-specific helpers. `@netlify/next` requires Edge Functions `@netlify/next` requires Netlify’s [Edge Functions](/frameworks/next-js/runtime-v4/overview/#edge-functions) and is subject to the [limitations](/edge-functions/limits/) of Edge Functions. If you [opt out of Edge Functions](#opt-out-of-netlify-edge-functions) , then you can’t use `@netlify/next`. Improved access to requests and responses enables excellent features, and `@netlify/next` has several ready to go: * HTML rewrites * Page data transforms * Request headers * Access to response body ### [#](#html-rewrites) HTML rewrites This feature enables rewriting the HTML of Next.js pages. It includes a simple `replaceText` function but also support for more powerful transforms using the [HTMLRewriter](https://github.com/worker-tools/html-rewriter) stream transformer. This enables personalization of pages at the edge, with no need for SSR. It works with ISR and static pages too. ### [#](#page-data-transforms) Page data transforms Next.js passes `getStaticProps` and `getServerSideProps` data to a page component and transfers it either as a JSON data file (for internal navigation with `next/link`) or embedded in the page’s HTML in a script tag for server-rendered pages. This feature allows users to modify those props on the fly, in a similar way to the HTML rewrites. This means you can be sure that the hydrated page matches the SSR HTML, avoiding hydration errors. It works with both the data in HTML pages and JSON data requests. ### [#](#request-headers) Request headers Next.js Middleware allows response headers to be modified. This extends that ability to request headers that are sent to the origin. This is particularly helpful for rewrites to external sites. For example, it allows authentication headers to be added to proxied requests, allowing you to proxy a single page from a password-protected site without sharing credentials with the user. ### [#](#access-to-response-body) Access to response body The other features make it easier to modify responses. But if you need more powerful changes, you can also get full read and write access to the response body as a stream. [#](#install-netlify-next) Install `@netlify/next` --------------------------------------------------- `@netlify/next` is not part of the default Next.js Runtime, so you need to install this library in your project. To do so, enter the following in a terminal at the root of your project. npm install @netlify/next [#](#netlify-next-api) `@netlify/next` API ------------------------------------------- You can use `@netlify/next` in your Next.js projects through its API, which includes the `MiddlewareRequest` and `MiddlewareResponse` endpoints. [#](#middlewarerequest-object) `MiddlewareRequest` object ---------------------------------------------------------- The `MiddlewareRequest` object is a more powerful version of the standard `NextRequest` object. You create it by passing `NextRequest` to the constructor: import { MiddlewareRequest, type NextRequest } from '@netlify/next'; export async function middleware(nextRequest: NextRequest) { const request = new MiddlewareRequest(nextRequest); // ... } You can then make changes to the request, such as adding or modifying headers. Or, you can use it to get a `MiddlewareResponse` object that you can then process. `MiddlewareRequest` has several useful methods you can use to handle your requests. ### [#](#next-method) `next()` method Passes the request on to the origin and returns the response. ### [#](#rewrite-method) `rewrite()` method Rewrites the request URL and passes it on to the origin. Can be either an internal or external URL. ### [#](#headers-object) `headers` object A normal request `headers` object, except it is mutable and any changes are used when the request is sent to the origin. [#](#middlewareresponse-object) `MiddlewareResponse` object ------------------------------------------------------------ This object is returned by `middlewareRequest.next()` or `middlewareRequest.rewrite()` and gives access to the full response. This may either be a static HTML file or SSR HTML. The following object and methods in this section can help you transform the response. You can change the response headers similarly to a regular `NextResponse`. However, you can also _read_ the response headers coming from the origin. ### [#](#originresponse-object) `originResponse` object The [`Response` object](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) returned from the origin. You should not normally need to access this directly, but should instead use the helper methods below. ### [#](#setpageprop-method) `setPageProp()` method Sets the value of a single page prop. #### [#](#syntax) Syntax setPageProp(key: string, value: any); ##### [#](#parameters) Parameters * `key: string` * `value: any`. While this parameter’s type is `any`, you should follow the [guidance for `props`](https://nextjs.org/docs/pages/api-reference/functions/get-server-side-props#props) in the Next.js documentation. #### [#](#example) Example const request = new MiddlewareRequest(req); const response = await request.next(); const message = `This was static but has been transformed in ${request.geo.city}`; response.setPageProp("message", message); ### [#](#replacetext-method) `replaceText()` method Replaces the text content of an element. It can either take a string or a function that is passed the current value and returns the new value. This should be text that was generated from props, and you should use `setPageProp` to change the prop as well. #### [#](#syntax-2) Syntax replaceText(selector: string, valueOrReplacer: string | ((input: string) => string)); ##### [#](#parameters-2) Parameters * `selector: string` * `valueOrReplacer: string | ((input: string) => string))` #### [#](#example-2) Example const request = new MiddlewareRequest(req); const response = await request.next(); const message = `This was static but has been transformed in ${request.geo.city}`; response.replaceText("#message", message); ### [#](#transformdata-method) `transformData()` method Modifies the returned page data. This is like `setPageProp` except you can change the whole page data object. #### [#](#syntax-3) Syntax transformData(transform: (props: any) => any); ##### [#](#parameters-3) Parameters * `transform: (props: any) => any` #### [#](#example-3) Example const request = new MiddlewareRequest(req); const response = await request.next(); const message = `This was static but has been transformed in ${request.geo?.city}`; // Transform the response page data response.transformData((data) => { data.pageProps.message = message; data.pageProps.showAd = true; return data; }) ### [#](#rewritehtml-method) `rewriteHTML()` method Allows the returned HTML to be written using [HTMLRewriter](https://github.com/worker-tools/html-rewriter) . #### [#](#syntax-4) Syntax rewriteHTML(selector: string, handlers: ElementHandlers); ##### [#](#parameters-4) Parameters * `selector: string` * `handlers: ElementHandlers` #### [#](#example-4) Example const request = new MiddlewareRequest(req); const res = await request.next(); const message = `This was static but has been transformed in ${request.geo?.city}`; // Transform the response HTML res.rewriteHTML("p[id=message]", { text(textChunk) { if (textChunk.lastInTextNode) { textChunk.replace(message); } else { textChunk.remove(); } }, }); ### [#](#response-caveats) Response caveats Modifying the response can cause React hydration errors if the hydrated page content doesn’t match the HTML returned from the server. There are two ways around this. Ideally, you can change both the text content and the prop. That would mean the value will still match. If that’s not possible (for example, if the displayed HTML is too complex to generate), then you can use two-pass rendering for the element. This is when you don’t render the element in SSR, but instead update the state in `useEffect` and then display it at that point. The logic for this can be encapsulated in a custom hook. For example: import * as React from "react"; const useHydrated = () => { const [hydrated, setHydrated] = React.useState(false); React.useEffect(() => { setHydrated(true) }, []); return hydrated; } const Page = ({ message, showAd }) => { const hydrated = useHydrated(); return (
{hydrated && showAd ? (

This is an ad that isn't shown by default

) : (

No ads for me

)}
); } export async function getStaticProps() { return { props: { showAd: false, }, } } export default Page; [#](#modify-request-headers) Modify request headers ---------------------------------------------------- Headers on the `MiddlewareRequest` object can be added or modified, and the changed headers will then be passed along to the origin if you call `middlewareRequest.next()` or `middlewareRequest.rewrite()`. You can also modify headers on the original `NextRequest` object, and they will be passed along in the same way. This can be used for many things. For example, to add authentication headers to an externally proxied request or attach a bucket name header for A/B testing. const { pathname } = req.nextUrl; const request = new MiddlewareRequest(req); if (pathname.startsWith("/api/hello")) { // Add a header to the request request.headers.set("x-hello", "world"); return request.next(); } if (pathname.startsWith("/headers")) { // Add a header to the rewritten request request.headers.set("x-hello", "world"); return request.rewrite("/api/hello"); } Last updated: October 23, 2024 ← [Legacy Next.js on Netlify](/frameworks/next-js/runtime-v4/overview/) [Next.js redirects and rewrites](/frameworks/next-js/runtime-v4/redirects-and-rewrites/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # React Router on Netlify | Netlify Docs React Router 7+ [can be used as a framework](https://reactrouter.com/home#react-router-as-a-framework) , giving you a server and browser runtime that focuses on performance and excellent user experiences. You get a number of built-in tools to build better websites, such as nested routes, parallel data requests, and robust built-in error handling. Deploy a React Router site [Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/react-router-template) Get started with React Router on Netlify right away by clicking the button above * [Demo repo](https://github.com/netlify/react-router-template) * [Demo site](https://react-router-template.netlify.app/) [#](#key-features) Key features -------------------------------- These features provide important benefits for React Router projects, including those built by and deployed with Netlify. * **Nested routes.** By default, React Router creates routes for components that serve as boundaries for data loading and code splitting. * **Parallel data requests by default.** Instead of waiting on sequential requests, React Router processes requests in parallel and then sends a complete HTML document. * **Built-in global error handling.** React Router has built-in error handling for server and client rendering and server side data handling. Error boundaries don’t block the entire page from rendering, only the affected component. [#](#netlify-integration) Netlify integration ---------------------------------------------- To create a React Router app and deploy it on Netlify, use our Netlify starter template with the command: `npx create-react-router@latest --template netlify/react-router-template`. You'll get all you need to deploy to Netlify, including a `netlify.toml` file with common [build settings](/frameworks/#react-router) . ### [#](#create-a-new-react-router-app-to-deploy-to-netlify) Create a new React Router app to deploy to Netlify You can use the command line to scaffold a new project based on the Netlify starter template for React Router. This can streamline the process of getting your project up and running. 1. In your terminal, run `npx create-react-router@latest --template netlify/react-router-template`. 2. Follow the interactive prompts. 3. Follow the starter template README to get your project running. ### [#](#update-the-deploy-target-for-an-existing-react-router-app) Update the deploy target for an existing React Router app If you have an existing React Router 7+ project that isn’t deployed on Netlify and you want to change the deploy target to Netlify, install Netlify's React Router Vite plugin and add it to your Vite config: npm install --save-dev @netlify/vite-plugin-react-router * Loading error: Refresh the page to access this code sample import { reactRouter } from "@react-router/dev/vite"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; // ↓ add this import netlifyPlugin from "@netlify/vite-plugin-react-router"; export default defineConfig({ plugins: [\ reactRouter(),\ tsconfigPaths(),\ netlifyPlugin() // ← add this\ ] }); import { reactRouter } from "@react-router/dev/vite"; // ↓ add this import netlifyPlugin from "@netlify/vite-plugin-react-router"; export default { plugins: [\ reactRouter(),\ netlifyPlugin() // ← add this\ ] }; [#](#limitations) Limitations ------------------------------ * Running React Router as a framework on Netlify Edge Functions is not yet supported [#](#more-resources) More resources ------------------------------------ * [React Router docs](https://reactrouter.com/) * [Netlify blog: Remix posts](https://www.netlify.com/blog/tags/remix/) Last updated: December 19, 2024 ← [Frameworks overview](/frameworks/#react-router) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Nuxt on Netlify | Netlify Docs Nuxt is an open source, modular framework for building performant sites and applications using Vue.js. [#](#key-features) Key features -------------------------------- These Nuxt features provide key benefits for sites and apps, including ones built and deployed with Netlify. * **Improved SEO**. With the ability to [statically generate](https://nuxtjs.org/docs/2.x/concepts/static-site-generation) your site, Nuxt can help to boost search engine optimization for your content. * **Page routing.** Nuxt has a [file system-based routing structure](https://nuxtjs.org/docs/2.x/get-started/routing) . Organizing files and subdirectories within a pages directory automatically results in corresponding routes. * **Image optimization**. The [`nuxt/image` module](https://image.nuxtjs.org/) , backed by [Netlify Image CDN](#netlify-image-cdn) , allows you to automatically optimize images for your site. * **Git-based Headless CMS.** The [`nuxt/content` module](https://content.nuxtjs.org/) parses Markdown, JSON, YAML, XML and CSV files within your site. * **Server-side rendering.** Powered by the [Nitro](https://nuxt.com/docs/guide/concepts/server-engine) server engine, SSR is supported automatically when you use Nuxt 3. [#](#netlify-integration) Netlify integration ---------------------------------------------- Nuxt sites on Netlify can benefit from automatic framework detection and require minimal setup considerations. Nuxt 3 introduces new rendering options, such as server-side rendering (SSR). SSR is supported when you deploy Nuxt 3 to Netlify, but requires configuration when you use [Edge Functions](#edge-functions) . For more information, check out the Nuxt [Getting Started Guide](https://v3.nuxtjs.org/getting-started/introduction) and [Deploy Nuxt to Netlify](https://nitro.unjs.io/deploy/providers/netlify) doc. ### [#](#automatic-framework-detection) Automatic framework detection When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Nuxt, Netlify provides a suggested build command and publish directory: * Nuxt 3: `npm run build` (assuming your build command is set to `nuxt build`) and `dist` * Nuxt 2: `nuxt generate` and `dist` If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, the CLI should work automatically assuming you are using the dev command and port: `nuxt` and `3000`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up a site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#nuxt) for Nuxt. ### [#](#pnpm-support) pnpm support If you’re planning to use pnpm with Nuxt 3, you must set a `PNPM_FLAGS` [environment variable](/environment-variables/get-started/#create-environment-variables) with a value of `--shamefully-hoist`. This appends an argument to the `pnpm install` command that Netlify runs. Learn more about using [pnpm on Netlify](/configure-builds/manage-dependencies/#pnpm) . ### [#](#edge-functions) Edge Functions [Edge Functions](/edge-functions/overview/) connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. Nuxt supports [server-side rendering (SSR)](https://nuxtjs.org/docs/concepts/server-side-rendering/) , but the use of Edge Functions requires some configuration. When you use Edge Functions, Nitro, the server engine that powers Nuxt, will not auto-detect them and needs a different deployment preset. Learn more in the [Nitro documentation](https://nitro.unjs.io/deploy/providers/netlify#netlify-edge-functions) . You can browse a [full library of reference examples](https://edge-functions-examples.netlify.app/) for different ways to use Edge Functions. For more details, check out the [Edge Functions documentation](/edge-functions/overview/) . ### [#](#netlify-image-cdn) Netlify Image CDN When deploying your Nuxt applications to Netlify, the Nuxt image module automatically uses [Netlify Image CDN](/image-cdn/overview/) to optimize and transform images on demand without impacting build times. Netlify Image CDN also handles content negotiation to use the most efficient image format for the requesting client. To transform a source image hosted on another domain, you must first configure allowed domains in your `nuxt.config.ts` file. Visit the [Nuxt Image docs](https://image.nuxt.com/providers/netlify) to learn more. [#](#deploy-a-nuxt-site-on-netlify) Deploy a Nuxt site on Netlify ------------------------------------------------------------------ This section demonstrates how to deploy a Nuxt site on Netlify. It covers: * Starting a new project using Nuxt * Deploying your Nuxt project to Netlify with Netlify CLI ### [#](#start-a-new-project-using-nuxt) Start a new project using Nuxt Before you begin, make sure you have [Node.js](https://nodejs.org/en/download) version 18.14.0 or later installed on your machine. 1. To get started, create your project from the command line with any of the following package managers: * Loading error: Refresh the page to access this code sample npx nuxi@latest init my-project pnpm dlx nuxi@latest init my-project 2. Next, navigate to your project directory and install your dependencies: * Loading error: Refresh the page to access this code sample cd my-project npm install cd my-project pnpm install cd my-project yarn install When using [pnpm](/frameworks/nuxt/#pnpm-support) , you must set a `PNPM_FLAGS` environment variable with a value of `--shamefully-hoist`. 3. Start your development server: * Loading error: Refresh the page to access this code sample npm run dev -- -o pnpm dev -o yarn dev -o From here you can customize your site. You can also create a Git repository for your site to take advantage of [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) . Avoid 404s for SPAs If your project is a single page app (SPA) that uses the history `pushState` method to get clean URLs, you must add a [rewrite rule](/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to serve the `index.html` file no matter what URL the browser requests. ### [#](#deploy-your-nuxt-project-with-netlify-cli) Deploy your Nuxt project with Netlify CLI You can [deploy your project from the command line](/site-deploys/create-deploys/#netlify-cli) using [Netlify CLI](/cli/get-started/) . 1. To ensure you have the latest version of Netlify CLI installed, run this command from any directory in your terminal: npm install netlify-cli -g 2. In the directory for your project, run the following command to create a new Netlify site: netlify init Didn’t initialize a Git repository? When you run `netlify init` without initializing a Git repository first, the CLI prompts you to connect your local directory to GitHub. Follow the steps in your terminal to link your local directory with a remote repo in order to use continuous deployment for your site. 3. Follow the prompts to create your site, select a team if necessary, and optionally create a site name. If you already initialized a Git repository, you can authorize your Git provider and set your build command and directory. 4. If you used continuous deployment, your site is now published! To learn how to manually deploy a site, check out the [manual deploy docs](/cli/get-started/#manual-deploys) . [#](#more-resources) More resources ------------------------------------ * [Typical Nuxt build settings](/frameworks/#nuxt) * [Netlify Blog: Nuxt posts](https://www.netlify.com/tags/nuxt/) * [Video: Get started with Nuxt](https://www.youtube.com/playlist?list=PLzlG0L9jlhENcUiAQU1x95sBLLCUihwIX) * [Video: Building with Sanity and Nuxt](https://www.youtube.com/playlist?list=PLzlG0L9jlhEMMY9wJjXt-GiusqSsW6Md7) * [Video: Build a Static Blog with Nuxt and Strapi](https://www.youtube.com/playlist?list=PLzlG0L9jlhEPbibzuAQmxJg4FYwRnEyIW) * [Nuxt documentation](https://nuxt.com/docs) * [Nitro documentation](https://nitro.unjs.io/deploy/providers/netlify) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#nuxt) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # SvelteKit on Netlify | Netlify Docs SvelteKit is a versatile, open source framework for building web applications using [Svelte](https://svelte.dev/) components. Unlike React and Vue, Svelte has no virtual DOM and includes a compiler that builds projects into plain HTML, CSS, and JavaScript. SvelteKit enables features like client-side routing, server-side rendering (SSR), and hot module replacement for Svelte projects. [#](#key-features) Key features -------------------------------- These SvelteKit features are available for projects built and deployed with Netlify. * **Multiple rendering modes.** As opposed to globally setting one rendering mode for a project, you can define which rendering mode to use on a per-page basis. With SvelteKit, choose between modes such as prerendering and static site generation (SSG), client-side rendering (CSR), and server-side rendering (SSR). * **Automatic API endpoints.** API routes allow developers to create endpoints to interact with third-party services for data fetching. * **Consistent navigation experience.** With SvelteKit, you can use hybrid rendering to combine server-side rendered pages with a client-side router. This makes the navigation experience similar to a typical single-page app (SPA) that doesn’t require full page reloads. * **Developer-friendly tooling.** SvelteKit uses [Vite](https://vitejs.dev/) for a modern scaffolding and development experience. [#](#netlify-integration) Netlify integration ---------------------------------------------- SvelteKit projects on Netlify benefit from [automatic framework detection](#automatic-framework-detection) and have minor setup considerations for [deployment](#deployment) . ### [#](#automatic-framework-detection) Automatic framework detection When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your project is using. For SvelteKit projects, Netlify automatically suggests a build command and output directory of `vite build` and `build`. Projects that use SvelteKit starter templates can use `npm run build` as the build command and this will run `vite build`. If you’re using the CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `vite dev` and `5173`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up a SvelteKit site on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#sveltekit-and-svelte) for SvelteKit. ### [#](#deployment) Deployment To deploy a SvelteKit project on Netlify, use [SvelteKit’s Netlify adapter](https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify) . This adapter deploys SvelteKit endpoints as [Netlify Functions](/functions/overview/) . For example, SSR routes are deployed to a `render` function. If you enable the `split` feature, each route is deployed to its own function. Check out the [split functions](#split-functions) section below for details. Function routing limitations Paths handled by proxies or functions may not redirect from HTTP to HTTPS URLs as expected. If you’re working with proxies or functions, we recommend only publishing HTTPS URLs for your visitors to use. To deploy your project on Netlify: 1. Install the adapter into your project. * Loading error: Refresh the page to access this code sample npm install -D @sveltejs/adapter-netlify yarn add -D @sveltejs/adapter-netlify 2. Add the adapter to your project’s `svelte.config.js` file and [pass any options](https://kit.svelte.dev/docs/adapter-netlify) you need. import adapter from '@sveltejs/adapter-netlify'; export default { kit: { adapter: adapter() } }; If the config file already has an adapter import from `@sveltejs/adapter-auto`, we recommend replacing it with the more specific import from `@sveltejs/adapter-netlify`. This ensures that SvelteKit will select the correct adapter module in all development environments, including local development. Alternatively, you can use [`@sveltejs/adapter-static`](https://kit.svelte.dev/docs/adapter-static) for a fully static site, and it will also work successfully with Netlify. 3. Create a `netlify.toml` in your project’s [base directory](/configure-builds/overview/#definitions-1) and specify a build command and publish directory. [build] command = "npm run build" publish = "build" 4. [Create your new project](/welcome/add-new-site/) on Netlify with Git or the Netlify CLI. #### [#](#split-functions) Split functions By default, SvelteKit’s Netlify adapter will bundle all of your routes and SSR functionality into a single Netlify Function called `render`. This can result in a large function. If desired, you can configure the adapter to generate multiple functions instead by setting the `split` option to true. The `split` feature does not work with Edge Functions. In `svelte.config.js`, you should either set `edge` to `false` or leave that option out. // svelte.config.js export default { kit: { adapter: adapter({ edge: false, split: true }) } }; When the split option is true, the adapter generates a function for each route (pages and SvelteKit endpoints) and uses the route or endpoint name as the function name. But, generated function names for nested and random routes can be hard to predict. To confirm the name of a generated function, refer to the **Functions** page in the Netlify UI for a list of all the generated functions for your SvelteKit site. ### [#](#edge-functions) Edge Functions [Edge Functions](/edge-functions/overview/) connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools. When you enable Edge Functions in SvelteKit, SSR happens in a Deno-based edge function that’s deployed close to your site visitors. If you don’t enable Edge Functions, SSR relies on standard Node-based Netlify Functions. You can browse a [full library of reference examples](https://edge-functions-examples.netlify.app/) for different ways to use Edge Functions. For more details, check out the [Edge Functions documentation](/edge-functions/overview/) . #### [#](#enable-edge-functions-in-your-sveltekit-project) Enable Edge Functions in your SvelteKit project The `netlify-sveltekit` adapter supports Edge Functions. To enable Edge Functions for your SvelteKit project, you need to update your `svelte.config.js` file. Specifically, add the `edge: true` option to the `adapter` function. The `edge` option defaults to `false`. If you use Edge Functions, you can’t use the adapter’s `split` feature. export default { kit: { adapter: adapter({ edge: true, split: false }) } }; [#](#limitations) Limitations ------------------------------ * **Edge functions don’t work locally.** Currently, edge functions do not work as expected when running `netlify dev` with SvelteKit. * **Redirects are not supported in `netlify.toml`.** Use [`_redirects`](/routing/redirects/#syntax-for-the-redirects-file) instead. [#](#more-resources) More resources ------------------------------------ * [Typical SvelteKit build settings](/frameworks/#sveltekit-and-svelte) * [Video: Building with SvelteKit and GraphCMS](https://www.youtube.com/playlist?list=PLzlG0L9jlhEPebBqDVXtoeIPxKUCNciC9) * [Video: How to use Netlify Functions in SvelteKit Applications](https://www.youtube.com/watch?v=qHUMu7ZGQwo) * [Learn with Jason: Experimenting with SvelteKit](https://www.learnwithjason.dev/experimenting-with-sveltekit) * [SvelteKit documentation](https://kit.svelte.dev/docs) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#sveltekit-and-svelte) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Vite on Netlify | Netlify Docs Vite is a next-generation frontend build tool designed to provide a fast, lean development experience for modern web projects. It includes a dev server and a build command that bundles your code. Use the frontend library or framework of your choice when you create a project with Vite. [#](#key-features) Key features -------------------------------- The features listed below outline benefits for Vite projects, including those built and deployed with Netlify. * **Dependency resolving and pre-bundling.** Vite detects bare module imports in all served source files and pre-bundles them to improve page loading speed. It also converts CommonJS modules to ES modules and ensures the browser imports them properly. * **Hot Module Replacement (HMR)**. Frameworks with HMR capabilities can leverage Vite’s HMR API to provide instant updates without reloading the page or impacting the application state. * **Out-of-the-box support for Typescript, Vue, and JSX.** With Vite, you can import TS, JSX, and TSX files out of the box and enjoy first-class support for Vue. * **Build optimizations.** Features such as [CSS code splitting](https://vitejs.dev/guide/features.html#css-code-splitting) , [automatically generated directives](https://vitejs.dev/guide/features.html#preload-directives-generation) , and [async chunk loading optimization](https://vitejs.dev/guide/features.html#async-chunk-loading-optimization) are automatically applied as part of the build process, without the need for additional configuration. * **Easily extendable**. Vite can be extended [using plugins](https://vitejs.dev/guide/using-plugins.html) based on the mature ecosystem of Rollup plugins. Use plugins to extend the dev server and enable [SSR functionality](https://vite-plugin-ssr.com/) . [#](#netlify-integration) Netlify integration ---------------------------------------------- When you link a repository for a project, Netlify tries to detect the framework your site is using. If your site is built with Vite, Netlify provides a suggested build command and publish directory: `npm run build` or `yarn build` and `dist`. You can [override suggested values](/configure-builds/overview/#build-settings) or [set them in a configuration file](/configure-builds/file-based-configuration/) instead, but automatic framework detection may help simplify the process of setting up a project with Vite on Netlify. [#](#deploy-a-vite-site-on-netlify) Deploy a Vite site on Netlify ------------------------------------------------------------------ This section demonstrates how to deploy a Vite site on Netlify. It covers: * Starting a new project using Vite * Deploying your Vite project to Netlify with Netlify CLI ### [#](#start-a-new-project-using-vite) Start a new project using Vite Before you begin, make sure you have [Node.js](https://nodejs.org/en/download) version 18.14.0 or later installed on your machine. Then, you can start a new project using Vite. 1. Scaffold your Vite project from the command line with any of the following package managers: * Loading error: Refresh the page to access this code sample npm create vite@latest yarn create vite pnpm create vite 2. Follow the prompts to enter your project name and select the template you want to use. Check out the [`create-vite` docs](https://github.com/vitejs/vite/tree/main/packages/create-vite) for more information about the supported templates. 3. Launch your site locally by running the appropriate dev command. For example, if you built your project with npm: npm run dev From here you can customize your site. You can also create a Git repository for your site to take advantage of [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) . ### [#](#deploy-your-vite-project-with-netlify-cli) Deploy your Vite project with Netlify CLI You can [deploy your project from the command line](/site-deploys/create-deploys/#netlify-cli) using [Netlify CLI](/cli/get-started/) . 1. To ensure you have the latest version of Netlify CLI installed, run this command from any directory in your terminal: npm install netlify-cli -g 2. In the directory for your project, run the following command to create a new Netlify site: netlify init Didn’t initialize a Git repository? When you run `netlify init` without initializing a Git repository first, the CLI prompts you to connect your local directory to GitHub. Follow the steps in your terminal to link your local directory with a remote repo in order to use continuous deployment for your site. 3. Follow the prompts to create your site, select a team if necessary, and optionally create a site name. If you already initialized a Git repository, you can authorize your Git provider and set your build command and directory. 4. If you used continuous deployment, your site is now published! To learn how to manually deploy a site, check out the [manual deploy docs](/cli/get-started/#manual-deploys) . Avoid 404s for SPAs If your project is a single page app (SPA) that uses the history `pushState` method to get clean URLs, you must add a [rewrite rule](/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to serve the `index.html` file no matter what URL the browser requests. [#](#more-resources) More resources ------------------------------------ * [Typical Vite build settings](/frameworks/#vite) * [Vite documentation](https://vitejs.dev/guide/) * [Vite documentation: deploying a static site](https://vitejs.dev/guide/static-deploy.html#netlify) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#vite) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Stop or activate builds | Netlify Docs If your site is linked to a Git repository, Netlify will by default build your site according to your continuous deployment settings when you push to your Git provider. You can [stop builds](/configure-builds/stop-or-activate-builds/#stop-builds) for your site at will for more control of your workflow. When you’re ready for Netlify to build your site again, you can [activate builds](/configure-builds/stop-or-activate-builds/#activate-builds) . For example, you might: * stop builds while you use a continuous integration tool to run validations and then activate builds after all validations are successful. * stop builds while you’re sequentially pushing many small commits in response to review feedback on a pull/merge request and then activate builds before you push the last commit. * stop builds as part of implementing a content freeze and then activate builds when the freeze is over. Stop builds vs. stop auto publishing When you stop builds for a site, you prevent Netlify from building production deploys, Deploy Previews, and branch deploys. If you only want to stop new production deploys from being published, you can [stop auto publishing](/site-deploys/manage-deploys/#locked-deploys) . [#](#stop-builds) Stop builds ------------------------------ To stop builds for a site, go to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** , select **Configure**, and then toggle **Build status** to **Stopped builds**. ![](/images/configure-builds-stop-builds-stop.png) When builds are stopped, Netlify will never build your site. * If you push to your linked repository, Netlify will not build production deploys, Deploy Previews, or branch deploys. * If requests are sent to build hook URLs, Netlify will not build your site. * You will not be able to trigger a build of your site with the Netlify API. Any POST requests to `/api/v1/sites/{site_id}/builds` will return an error message. * You will not be able to build your site using the Netlify UI. On the **Deploys** page, the **Trigger deploy** button will be unavailable. On the detail page for a past deploy, the **Retry with latest branch commit** button will be unavailable. Tip You can still update your site by [running a build locally](/cli/get-started/#run-builds-locally) with the CLI and then creating a deploy manually with the [CLI](/cli/get-started/#manual-deploys) or the [API](/api/get-started/#deploy-with-the-api) . Netlify will send a notification email to let any other site members know that builds are stopped for the site. There will also be warnings in these locations in the Netlify UI: * your team’s **Sites** page. * the **Site overview** page. * the site’s **Deploys** page. * **Site configuration** under **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** . Relinking the Git repository will activate builds If you [unlink](/git/repo-permissions-linking/#unlink-a-git-repository) and then [relink](/git/repo-permissions-linking/#link-a-git-repository) your site’s repository or [link to a different repository](/git/repo-permissions-linking/#change-linked-git-repository) , builds will be activated as part of the new configuration. [#](#activate-builds) Activate builds -------------------------------------- By default, builds are active. If builds have been stopped for a site, there are multiple ways you can activate them. You can: * go to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** , select **Configure**, and then toggle **Build status** to **Active builds**. ![](/images/configure-builds-stop-builds-activate-on-settings.png) * go to the **Site overview** page and use the **Activate builds** button. ![](/images/configure-builds-stop-builds-activate-on-overview.png) * go to the site’s **Deploys** page and use the **Activate builds** button. ![](/images/configure-builds-stop-builds-activate-on-deploys.png) Activating builds does not trigger a build Netlify does not immediately build your site when you activate builds. After you activate builds, Netlify will build your site when you push to your Git repository, trigger a build hook, POST to `/api/v1/sites/{site_id}/builds`, or trigger/retry a deploy using the Netlify UI. Netlify will send a notification email to let any other site members know that builds have been activated for the site. Last updated: July 19, 2024 ← [Build hooks](/configure-builds/build-hooks/) [Troubleshooting tips](/configure-builds/troubleshooting-tips/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Remix on Netlify | Netlify Docs Remix gives you a server and browser runtime that focuses on performance and excellent user experiences. With Remix, you get a number of built-in tools to build better websites, such as nested routes, parallel data requests, and robust built-in error handling. [#](#key-features) Key features -------------------------------- These features provide important benefits for Remix projects, including those built by and deployed with Netlify. * **Nested routes.** By default, Remix creates routes for components that serve as boundaries for data loading and code splitting. * **Parallel data requests by default.** Instead of waiting on sequential requests, Remix processes requests in parallel and then sends a complete HTML document. * **Built-in global error handling.** Remix has built-in error handling for server and client rendering and server side data handling. Error boundaries don’t block the entire page from rendering, only the affected component. [#](#netlify-integration) Netlify integration ---------------------------------------------- You can create a Remix app and deploy it on Netlify using the Netlify starter template for Remix with the command `npx create-remix@latest --template netlify/remix-template`. This template automatically creates everything you need to deploy to Netlify — including a pre-configured `netlify.toml` file with [typical build settings](/frameworks/#remix) . ### [#](#create-a-new-remix-app-to-deploy-to-netlify) Create a new Remix app to deploy to Netlify You can use the command line to scaffold a new project based on the Netlify starter template for Remix. This can streamline the process of getting your project up and running. 1. In your terminal, run `npx create-remix@latest --template netlify/remix-template`. 2. Choose where you want to create your project. 3. Decide whether you want to use TypeScript or JavaScript. 4. Enter **Y** to have `create-remix` run `npm install` for your project. 5. Choose whether you want to run your app with functions or [edge functions](#edge-functions) . 6. Follow the starter template README to get your project running. ### [#](#update-the-deploy-target-for-an-existing-remix-app) Update the deploy target for an existing Remix app If you have an existing Remix project that isn’t deployed on Netlify and you want to change the deploy target to Netlify, you need to create a new Remix project. 1. Create a [new Remix project](#create-a-new-remix-app-to-deploy-to-netlify) with Netlify as the deploy target. 2. Replace the new project’s `app` directory with the `app` directory from your old project. #### [#](#manual-configuration) Manual configuration Alternatively, you can configure this manually. First, ensure you're using Remix Vite. If not, [follow this guide](https://developers.netlify.com/guides/how-to-deploy-remix-vite-to-netlify/) . Then, install Netlify's Remix adapter and add its Vite plugin to your Vite config: npm install --save-dev @netlify/remix-adapter * Loading error: Refresh the page to access this code sample import { vitePlugin as remix } from "@remix-run/dev"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; // ↓ add this import { netlifyPlugin } from "@netlify/remix-adapter/plugin"; export default defineConfig({ plugins: [\ remix(),\ tsconfigPaths(),\ netlifyPlugin() // ← add this\ ] }); import { vitePlugin as remix } from "@remix-run/dev"; // ↓ add this import { netlifyPlugin } from "@netlify/remix-adapter/plugin"; export default { plugins: [\ remix(),\ netlifyPlugin() // ← add this\ ] }; ### [#](#edge-functions) Edge Functions [Edge Functions](/edge-functions/overview/) connect the Netlify platform and workflow with an open runtime standard at the network edge. This enables you to build fast, personalized web experiences with an ecosystem of development tools, including Remix. To take advantage of Netlify Edge Functions with Remix, follow the steps above to [create a new Remix app to deploy on Netlify](#create-a-new-remix-app-to-deploy-to-netlify) . When the CLI prompts you to select the type of functions to run your Remix app with, select **Netlify Edge Functions**. To change an existing site to use Edge Functions, replace the `@netlify/remix-adapter` NPM dependency with `@netlify/remix-edge-adapter` and install this additional dependency: npm i @netlify/remix-runtime You can browse a [full library of reference examples](https://edge-functions-examples.netlify.app/) for different ways to use Edge Functions. For more details, check out the [Edge Functions documentation](/edge-functions/overview/) . [#](#more-resources) More resources ------------------------------------ * [Remix quickstart](https://remix.run/docs/en/v1/tutorials/blog) * [Netlify blog: Remix posts](https://www.netlify.com/blog/tags/remix/) * [Developer guide: build a high-performance Remix image component with Unpic and Netlify Image CDN](https://developers.netlify.com/guides/build-a-remix-image-component-with-unpic-netlify-image-cdn/) * [Remix docs about HTTP handlers and adapters](https://remix.run/docs/en/v1/pages/technical-explanation#http-handler-and-adapters) Last updated: December 19, 2024 ← [Frameworks overview](/frameworks/#remix) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Next.js advanced API routes | Netlify Docs Legacy Next.js Runtime The information on this page applies to Next.js version 10-13.4 and Netlify Next.js Runtime v4, which is currently in maintenance support. [Visit our Next.js adapter docs](/frameworks/next-js/overview/) for info on newer versions of Next.js. Next.js sites on Netlify can take advantage of advanced API route capabilities in addition to support for basic and dynamic [API routes](https://nextjs.org/docs/api-routes/introduction) . These enhancements include running a process in the background for a long-running task and scheduling a process to run at a regular interval. They are available for Next.js 12.2 and later. [#](#background-api-routes) Background API routes -------------------------------------------------- This feature is in [Beta](/platform/release-phases/#beta) and is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. With background API routes, you can invoke an API route and instead of instantly returning the data, the function can return a `HTTP 202 Accepted` response, allowing it to process the request in the background for up to 15 minutes. You can read more about this functionality in the [Netlify Background Functions](/functions/background-functions/) documentation. The background function can be called on the following endpoint for Next.js sites: `/api/function-name`. To enable a background API route in your Next.js project, add a TypeScript or JavaScript file inside the folder `pages/api` and export the following `config` object: export default async (req, res) => { // Do something slow }; export const config = { type: "experimental-background", }; Check out a more extensive [background API route code example](https://github.com/netlify/next-background-api-route) for details. [#](#scheduled-api-routes) Scheduled API routes ------------------------------------------------ This feature is in [Beta](/platform/release-phases/#beta) . Scheduled API routes are triggered on a schedule rather than in response to an HTTP request. This functionality is powered by [Netlify Scheduled Functions](/functions/scheduled-functions/) . To enable a scheduled API route in your Next.js project, add a TypeScript or JavaScript file inside the folder `pages/api` and export the following `config` object: export default (req, res) => { // Do something scheduled }; export const config = { type: "experimental-scheduled", schedule: "@hourly", }; Scheduled functions use the [“cron expression” format used by tools like crontab](https://man7.org/linux/man-pages/man5/crontab.5.html) and are executed according to the UTC timezone. For example, the cron expression `0 0 * * *` will run a scheduled function every day at midnight UTC. We also support the [extensions](https://man7.org/linux/man-pages/man5/crontab.5.html#EXTENSIONS) in the RFC, except for the `@reboot` and `@annually` specifications. With extensions, the expression `0 0 * * *` can be written as `@daily`. [#](#test-locally) Test locally -------------------------------- Follow these steps to test a background API route or scheduled API route during development. A scheduled API route will only run on a schedule once deployed to production. 1. Run your Next.js project locally in development mode with `next dev`. 2. Trigger the route by invoking the URL path. Testing with Netlify Dev isn’t supported [Netlify Dev](/cli/local-development/) doesn’t currently support serving background and schedule API routes for local testing. Instead, we recommend that you test with `next dev`. Last updated: October 23, 2024 ← [Legacy Next.js on Netlify](/frameworks/next-js/runtime-v4/overview/) [Troubleshooting Next.js](/frameworks/next-js/runtime-v4/troubleshooting/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Background Functions overview | Netlify Docs This feature is in [Beta](/platform/release-phases/#beta) and is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify’s Background Functions provide an option for serverless functions that run for up to 15 minutes and don’t need to complete before a visitor can take next steps on your site. For tasks like batch processing, scraping, and slower API workflow execution, they may be a better fit than synchronous functions. [#](#how-background-functions-work) How background functions work ------------------------------------------------------------------ Background functions are longer-running functions that are processed as background tasks using asynchronous invocation. When a function is invoked asynchronously, there is an initial `202` success response that indicates that the function was successfully invoked. The function will run separately in the background until it completes or it reaches the 15 minute execution limit. If function invocation returns an error, a retry happens after one minute. If it fails again, another retry happens two minutes later. When a background function is successfully executed, you generally pass the result to a destination other than the originating client. Like all Netlify Functions, background functions are version-controlled, built, and deployed along with the rest of your Netlify site. Background functions are deployed with the [default deployment options](/functions/overview/#default-deployment-options) , and you can [configure](/functions/optional-configuration/) and [monitor](/functions/logs/) them along with your other functions. Background functions don’t support response streaming because they don’t return responses. [#](#create-background-functions) Create background functions -------------------------------------------------------------- You can [create background functions in TypeScript](/functions/get-started/?fn-language=ts) , [JavaScript](/functions/get-started/?fn-language=js) , or [Go](/functions/lambda-compatibility/?fn-language=go) . To get started, [create a function file](/functions/get-started/#create-function-file) in your functions directory and append the name with `-background`. For example, `netlify/functions/hello-background.mts`. Based on the filename, Netlify will deploy a background function that can be called on the following endpoint, relative to the base URL of your site: `/.netlify/functions/hello-background`. [Background function syntax](/functions/get-started/#background-function) is similar to synchronous function syntax. The file has a default export with a function that receives a web platform [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and a [Netlify-specific `Context`](/functions/api/#netlify-specific-context-object) object on each invocation. But, with background functions, the client receives an empty response while the execution happens in the background, so you generally pass the invocation result to a different destination. Check out our [get started with functions](/functions/get-started/) doc to learn more about how to [name your function](/functions/get-started/#create-function-file) and the [background function format](/functions/get-started/#background-function) . Want to use background functions with Next.js? If you have a Next.js site on Netlify, you can use advanced API routes for background functions. The endpoint for background functions with Next.js differs from the endpoint described above. Read more about [background API routes for Next.js](/frameworks/next-js/runtime-v4/advanced-api-routes/#background-api-routes) . [#](#invoke-background-functions) Invoke background functions -------------------------------------------------------------- Typically, you invoke a background function with a `POST` request to your endpoint, so that you can pass parameters as needed. You can also trigger background functions on [Netlify events](/functions/trigger-on-events/) and [Identity events](/functions/functions-and-identity/) . You can then reference the [function logs](/functions/logs/) to observe and troubleshoot the background functions as they run. [#](#more-background-functions-resources) More Background Functions resources ------------------------------------------------------------------------------ * [Netlify Blog: What are Background Functions?](https://www.netlify.com/blog/2021/01/07/what-are-background-functions/) * [Netlify Blog: Background and Scheduled API Routes for Next.js](https://www.netlify.com/blog/new-background-scheduled-api-routes-nextjs/) Last updated: April 30, 2024 ← [Functions & Identity](/functions/functions-and-identity/) [Scheduled Functions](/functions/scheduled-functions/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Scheduled Functions | Netlify Docs This feature is in [Beta](/platform/release-phases/#beta) . Scheduled Functions is a feature of Netlify Functions that enables you to run functions on a regular and consistent schedule, much like a cron job. Scheduled functions can do almost anything that serverless functions do today, though some tasks are better suited to scheduled functions than others. For example, you may want to: * Invoke a set of APIs to collate data for a report at the end of every week * Backup data from one data store to another at the end of every night * Build and/or deploy all your static content every hour instead of for every authored or merged pull request * Or anything else you can imagine you might want to invoke on a regular basis! Note that scheduled functions don’t work with payloads or `POST` request data. When you need to work with payloads, you should use either a [synchronous](/functions/get-started/#synchronous-function) or [background function](/functions/get-started/#background-function) instead. [#](#getting-started) Getting started -------------------------------------- The Scheduled Functions beta is enabled by default for all accounts. To try the feature, write a scheduled function for your site. Keep the [default deployment options](/functions/overview/#default-deployment-options) , such as memory and execution time limits, in mind as you work with scheduled functions. [#](#writing-a-scheduled-function) Writing a scheduled function ---------------------------------------------------------------- Scheduled functions use the [“cron expression” format used by tools like crontab](https://man7.org/linux/man-pages/man5/crontab.5.html) and are executed according to the UTC timezone. For example, the cron expression `0 0 * * *` will run a scheduled function every day at midnight UTC. We also support the [extensions](https://man7.org/linux/man-pages/man5/crontab.5.html#EXTENSIONS) in the RFC, except for the `@reboot` and `@annually` specifications. With extensions, the expression `0 0 * * *` can be written as `@daily`. There are two ways to specify a cron expression for a scheduled function — [inline in function code](#cron-expression-inline-in-function-code) or [in `netlify.toml`](#cron-expression-in-netlify-toml) . Specifying cron expressions inline only works for TypeScript and JavaScript If you use a function language other than TypeScript or JavaScript, you must specify your cron expression in `netlify.toml`. ### [#](#cron-expression-inline-in-function-code) Cron expression inline in function code First, make sure you install the `@netlify/functions` npm module to your local project directory: npm install @netlify/functions Then, create a scheduled function in your Netlify functions directory using the general syntax of a [synchronous function](/functions/get-started/?fn-language=js#synchronous-function-2) . Netlify provides a web platform [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and a [Netlify-specific `Context`](/functions/api/#netlify-specific-context-object) object on each invocation. For scheduled functions, the request body is a JSON-encoded object containing a `next_run` property. It represents the timestamp of the next scheduled invocation, as a string in the [ISO-8601 format](https://en.wikipedia.org/wiki/ISO_8601) . To set the schedule of a function, export a `config` object with a `schedule` property containing the cron expression. * Loading error: Refresh the page to access this code sample // YOUR_BASE_DIRECTORY/netlify/functions/test-scheduled-function.mts import type { Config } from "@netlify/functions" export default async (req: Request) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } export const config: Config = { schedule: "@hourly" } // YOUR_BASE_DIRECTORY/netlify/functions/test-scheduled-function.mjs export default async (req) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } export const config = { schedule: "@hourly" } ### [#](#cron-expression-in-netlify-toml) Cron expression in `netlify.toml` If you prefer to keep your cron expressions in one file and separate from your function code, you can specify them in the `netlify.toml` configuration at the root of your repository. First, create a function in your Netlify functions directory using the general syntax of a [synchronous function](/functions/get-started/?fn-language=js#synchronous-function-2) . Netlify provides a web platform [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and a [Netlify-specific `Context`](/functions/api/#netlify-specific-context-object) object on each invocation. For scheduled functions, the request body is a JSON-encoded object containing a `next_run` property. It represents the timestamp of the next scheduled invocation, as a string in the [ISO-8601 format](https://en.wikipedia.org/wiki/ISO_8601) . * Loading error: Refresh the page to access this code sample // YOUR_BASE_DIRECTORY/netlify/functions/test-scheduled-function.mts export default async (req: Request) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } // YOUR_BASE_DIRECTORY/netlify/functions/test-scheduled-function.mjs export default async (req) => { const { next_run } = await req.json() console.log("Received event! Next invocation at:", next_run) } Then, specify the function as a scheduled function in your configuration file: # ./netlify.toml [functions."test-scheduled-function"] schedule = "@hourly" [#](#developing-and-debugging-scheduled-functions) Developing and debugging scheduled functions ------------------------------------------------------------------------------------------------ Scheduled functions only run on published deploys and, similar to [event-triggered functions](/functions/trigger-on-events/) , you can’t invoke them directly with a URL. This means that you can’t test with deploy previews, for example. Therefore, the best way to test a scheduled function is to use Netlify Dev to [serve your scheduled function locally](/cli/manage-functions/#invoke-functions-while-running-netlify-dev) and then use the [`netlify functions:invoke`](https://cli.netlify.com/commands/functions#functionsinvoke) command to invoke it. Note that Netlify Dev will not execute the scheduled function on any kind of schedule — the invoke command only allows you to debug the function code invocation. You can also invoke functions locally on the URL path but these invocations are purely for interactive debugging. Netlify Dev wraps the function response with a note that this URL invocation isn’t possible in production. Alternatively, you can create a new test site to experiment with scheduled functions as part of published deploys. Once you deploy your code, the deployed function should appear on the Functions page of the Netlify UI with a `Scheduled` badge. The function will show a next execution date and time, converted to the user’s timezone. ![Example of a function list on the Functions page of the Netlify UI](/images/functions-scheduled-functions-functions-list.png) Select the scheduled function to access the function’s schedule and logs. ![Example of a scheduled function’s details in the Netlify UI](/images/functions-scheduled-functions-function-in-app.png) [#](#supported-cron-extensions) Supported cron extensions ---------------------------------------------------------- * `@yearly`: once a year, on January 1st 00:00 (`0 0 1 1 *`) * `@monthly`: every month, on the first day of the month, at 00:00 (`0 0 1 * -`) * `@weekly`: every Sunday, 00:00 (`0 0 * * 0`) * `@daily`: once a day, at 00:00 (`0 0 * * *`) * `@hourly`: every hour, at minute 0 (`0 * * * *`) [#](#limitations) Limitations ------------------------------ * Scheduled functions have a 30 second execution limit. [Background functions](/functions/background-functions/) are more appropriate for tasks that must run longer. * Scheduled functions only run on published deploys. They don’t run on Deploy Previews or branch deploys. * You can’t invoke scheduled functions directly with a URL. Review the [developing and debugging](#developing-and-debugging-scheduled-functions) section above for how to test. * Scheduled functions don’t support response streaming because they don’t return a response body. * Scheduled functions don’t work with [Split Testing](/site-deploys/split-testing/) because Split Testing relies on branch deploys and scheduled functions only run on published deploys. * Scheduled functions don’t work with sites that have [site-wide basic password protection](/security/secure-access-to-sites/site-protection/) enabled as the protection applies to all parts of your site, including function endpoints. Netlify doesn’t have access to authentication information when executing scheduled functions. Consider using [basic authentication with custom HTTP headers](/security/secure-access-to-sites/basic-authentication-with-custom-http-headers/) instead to protect only the sections of the site that need it and exclude the functions. [#](#feedback) Feedback ------------------------ We’d love to hear your thoughts on how we can make Scheduled Functions better. Please visit our [Forums](https://answers.netlify.com/categories)  to join the conversation. Last updated: September 6, 2024 ← [Background Functions](/functions/background-functions/) [Environment variables](/functions/environment-variables) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Vue CLI on Netlify | Netlify Docs Vue CLI is a set of tools for rapid development of [Vue.js](https://vuejs.org/) applications. It includes a command line interface for prototyping and building projects and a graphical user interface for creating and managing applications. [#](#key-features) Key features -------------------------------- These features provide important benefits for Vue CLI projects, including ones built and deployed with Netlify. * **Default setup.** Vue CLI provides a standard baseline for [project setup](https://cli.vuejs.org/guide/creating-a-project.html) with common features like hot module reloading and common defaults for build tools. * **Ready for development.** Built-in support for Babel, TypeScript, ESLint, PostCSS, Progressive web apps (PWAs), unit testing, and end-to-end testing unlocks your productivity. * **Optional configuration.** Vue CLI allows for full [configuration of tooling](https://cli.vuejs.org/guide/cli-service.html#configuration-without-ejecting) without needing to eject. [#](#netlify-integration) Netlify integration ---------------------------------------------- When you [link a repository](/welcome/add-new-site/#import-from-an-existing-repository) for a project, Netlify tries to detect the framework your site is using. If your site is built with Vue CLI, Netlify provides a suggested build command and publish directory: `vue-cli-service build` and `dist`. If you’re using the Netlify CLI to run [Netlify Dev](/cli/local-development/) for a local development environment, Netlify also suggests a dev command and port: `vue-cli-service serve` and `8080`. You can override suggested values or set them in a configuration file instead, but automatic framework detection may help simplify the process of setting up a Vue CLI project on Netlify. For manual configuration, check out the [typical build settings](/frameworks/#vue-cli) for Vue CLI. Avoid 404s for SPAs If your project is a single page app (SPA) that uses the history `pushState` method to get clean URLs, you must add a [rewrite rule](/routing/redirects/rewrites-proxies/#history-pushstate-and-single-page-apps) to serve the `index.html` file no matter what URL the browser requests. [#](#vue-specific-environment-variables) Vue-specific environment variables ---------------------------------------------------------------------------- Environment variables prefixed with `VUE_APP_` are processed by the Vue CLI and made available in the browser for client-side JavaScript access. For more information on how to use environment variables in Vue, check out the [Environment variables and frameworks doc](/frameworks/environment-variables/) . [#](#more-resources) More resources ------------------------------------ * [Typical Vue CLI build settings](/frameworks/#vue-cli) * [Vue CLI documentation](https://cli.vuejs.org/) Last updated: July 19, 2024 ← [Frameworks overview](/frameworks/#vue-cli) #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Manage notifications in Netlify Connect | Netlify Docs This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. After you [create and configure a data layer](/connect/get-started/) , you can add and delete notifications for the data layer on the settings page in the Netlify UI. [Notifications](/connect/get-started/#definitions) are external webhooks that you can add to a data layer. Once added, Netlify will notify these external services whenever data changes in your data layer. For example, you may want to add a notification to notify a Slack channel when your data layer updates. Team Owners and Developers can add or delete notifications at any time. Netlify records the addition and deletion of notifications in the [team audit log](/connect/monitor-activity/#review-team-member-activity) . New to Connect? Set up a data layer first If you haven’t already created a data layer, navigate to the **Connect** page for your team and select **Add new data layer**. Follow the prompts to configure the data layer and to add data sources, connected sites, and notifications. For more information, refer to our [get started with Netlify Connect](/connect/get-started/) guide. [#](#add-a-notification) Add a notification -------------------------------------------- 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Notifications**. 4. Select **Add a notification**. 5. Enter a **Name** and **URL**. 6. Select **Create notification**. [#](#delete-a-notification) Delete a notification -------------------------------------------------- Note that when you delete a notification, Netlify will no longer notify that service when data changes. To delete a notification from your data layer: 1. Navigate to the **Connect** page for your team in the Netlify UI. 2. Select the data layer from the **Data layers** list, and then select **Data layer settings**. 3. On the data layer settings page, select **Notifications**. 4. Find the notification you want to delete and select **Delete**. 5. A confirmation prompt will appear. Review the details and then select **Delete**. Last updated: November 26, 2024 ← [Manage connected sites](/connect/manage-data-layers/manage-connected-sites/) [Manage webhooks](/connect/manage-data-layers/manage-webhooks/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Functions API reference | Netlify Docs This page provides a full reference of the Netlify Functions API. [#](#netlify-specific-context-object) Netlify-specific `Context` object ------------------------------------------------------------------------ The `Context` object exposes the following properties: * **`account`:** an object containing Netlify team account information with the following property: * **`id`:** unique ID of the team that the site and function belong to. * **`cookies`:** a simplified interface for reading and storing [cookies](https://deno.land/std@0.148.0/http/cookie.ts?s=Cookie) : * **`cookies.get(name)`:** reads a cookie with a given name from the incoming request. * **`cookies.set(options)`:** sets a cookie on the outgoing response, using the same format as the `options` value in [the `CookieStore.set` web standard](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore/set) . * **`cookies.delete(name)`** or **`cookies.delete(options)`:** adds an instruction to the outgoing response for the client to delete a cookie. Following [the `CookieStore.delete` web standard](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore/delete) , accepts a string representing the name of the cookie, or an options object. Setting cookies across subdomains only works for custom domains `netlify.app` is listed in the Mozilla Foundation’s [Public Suffix List](http://publicsuffix.org/) , which prevents setting cookies across subdomains. You can only set a cookie for all subdomains if your site uses a [custom domain](/domains-https/custom-domains/) instead of `yoursitename.netlify.app`. * **`deploy`:** an object containing Netlify deploy information with the following property: * **`context`:** the [context](/site-deploys/overview/#deploy-contexts) of the deploy that the function belongs to. * **`id`:** unique ID of the deploy that the function belongs to. * **`published`:** a boolean that indicates whether or not the function belongs to the current [published deploy](/site-deploys/overview/#definitions) . * **`geo`:** an object containing geolocation data for the client with the following properties: * **`city`:** name of the city. * **`country`:** * **`code`:** ISO 3166 code for the country. * **`name`:** name of the country. * **`latitude`:** latitude of the location. * **`longitude`:** longitude of the location. * **`subdivision`:** * **`code`:** ISO 3166 code for the country subdivision. * **`name`:** name of the country subdivision. * **`timezone`:** timezone of the location. * **`postalCode`:** postal (zip) code of the location. We support all regional formats, so the format will vary. * **`ip`:** a string containing the client IP address. * **`params`:** object containing the parameters set for the function’s `path` in the [configuration object](/functions/get-started/#route-requests) and the values they receive from the incoming request URL. For example, for a function configured to run at `/pets/:name`, the `params` value for a request to `/pets/boo` will be `{"name":"boo"}`. To access the query string, use `request.url` instead. * **`requestId`:** a string containing the Netlify request ID; for example, `01FDWR77JMF2DA1CHF5YA6H07C`. * **`server`:** an object containing server metadata with the following property: * **`region`:** the region code where the deployment is running; for example, `us-east-1`. * **`site`:** an object containing Netlify site metadata with the following properties: * **`id`:** unique ID for the site; for example, `1d01c0c0-4554-4747-93b8-34ce3448ab95`. * **`name`:** name of the site, its Netlify subdomain; for example, `petsof`. * **`url`:** URL representing the main address to your site. It can be either a Netlify subdomain or your own custom domain if you set one; for example, `https://petsof.netlify.app` or `https://www.petsofnetlify.com`. [#](#netlify-global-object) `Netlify` global object ---------------------------------------------------- The `Netlify` global object exposes the following properties: * **`context`:** the [Netlify-specific `context` object](#netlify-specific-context-object) . This property is scope-dependent The context object is only available when `Netlify.context` is accessed from within the [scope](https://developer.mozilla.org/en-US/docs/Glossary/Scope) of a function handler or one of its child scopes. If accessed from somewhere else, like the global scope, it returns `null`. * **`env`:** an object providing access to [environment variables](/functions/environment-variables/) with the following properties: * **`delete(name)`:** in the context of the invocation, deletes an environment variable with a given name. * **`get(name)`:** returns the string value of an environment variable with a given name; if the environment variable is not defined, `undefined` is returned. * **`has(name)`:** returns a boolean value containing `true` if an environment variable with a given name exists, and `false` otherwise. * **`set(name, value)`:** in the context of the invocation, sets an environment variable with a given name and value. * **`toObject()`:** returns a plain object containing all the environment variables and their values. Last updated: November 11, 2024 ← [Get started with functions](/functions/get-started/) [Lambda compatibility](/functions/lambda-compatibility/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Function logs | Netlify Docs Netlify provides logs in the Netlify UI to help you observe and troubleshoot serverless functions in your current [published deploy](/site-deploys/overview/#definitions) , branch deploys, and Deploy Previews. [#](#access-function-logs) Access function logs ------------------------------------------------ 1. In the Netlify UI, for your chosen site, go to **Logs \> Functions** . 2. Select a function from the list to open the log for that function. By default, the Functions list displays the functions in the current published deploy. To find functions on another deploy, you can use the search field at the top of the list. You can start typing to jump to a particular branch, or find a Deploy Preview by number. Team Owners and Developers can monitor the function logs for a specific deploy by going to the **Function logs** tab of the [Netlify Drawer](/site-deploys/collaborate-on-deploys/#monitor-logs) in a collaborative Deploy Preview. [#](#log-contents) Log contents -------------------------------- Netlify displays a log for each function, including: * Start of each invocation * Any `console.log()` statements you include in your function code * Log statements as each [background function](/functions/background-functions/) is executed Note that function [log retention limits](#log-retention-and-limits) apply and may impact what the Netlify UI displays. ### [#](#date-filter) Date filter By default, the function log displays a live tail of the latest activity in **Real-time**. You can also filter to review data from a specific time period, including the **Last hour**, **Last day**, **Last 7 days**, or select **Custom** to input a specific date and time range. ### [#](#text-filter) Text filter You can filter the contents of the log with simple text matches on request ID, message, or log level. Some common log levels include: * `INFO` * `ERROR` * `WARN` * `FATAL` * `DEBUG` * `TRACE` [#](#log-retention-and-limits) Log retention and limits -------------------------------------------------------- Logs are retained for at least 24 hours of function activity, even after a new function deployment. This log retention period increases to 7 days for certain pricing plans. Historical function log output is limited to 4 KB total per invocation. If a log’s output exceeds 4 KB, only the last 4 KB of the log is retained and the log message will be truncated. [#](#log-drains) Log Drains ---------------------------- This feature is available on [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. You can connect your function logs to third-party monitoring services for analysis using Netlify’s Log Drains feature. Check out our [Log Drains](/monitor-sites/log-drains/) doc for more information. [#](#function-metrics) Function Metrics ---------------------------------------- With [Function Metrics](/monitor-sites/function-metrics/) , you can get insights into the performance, reliability, and usage patterns of functions on your site. By analyzing success and error rates alongside other metrics, such as invocation count and function duration, you can optimize performance, troubleshoot issues, and make data-driven decisions to enhance the overall quality and user experience of your projects. Last updated: October 2, 2024 ← [Deploy](/functions/deploy/) [Optional configuration](/functions/optional-configuration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Functions overview | Netlify Docs Serverless functions open a world of possibilities for running on-demand, server-side code without having to run a dedicated server. However, managing service discovery, configuring API gateways, and coordinating deployments between your app and your functions can quickly become overwhelming. With Netlify Functions, your serverless functions are version-controlled, built, and deployed along with the rest of your Netlify site, and we will automatically handle service discovery through our built-in API gateway. This eliminates overhead and brings the power of Deploy Previews and rollbacks to your functions. To provide faster customer experiences, synchronous functions can use [response streaming](/functions/get-started/?fn-language=ts#synchronous-function) to get content in front of people as quickly as possible. For longer-running function tasks, [Background Functions](/functions/background-functions/) allow for extended execution time using asynchronous invocation. Currently, you can deploy functions built with TypeScript, JavaScript, and Go. [#](#manage-your-functions) Manage your functions -------------------------------------------------- Functions deployed from Netlify are immutable. This means that an update to a function on your production branch won’t change the version that was deployed in a branch deploy, or in a Deploy Preview. You can access all versions of your functions in the Netlify web interface, under the **Functions** tab. By default, the list displays all of the functions, including background functions, in the current [published deploy](/site-deploys/overview/#definitions) . To find functions on another deploy, you can use the search field at the top of the list. You can start typing to jump to a particular branch, or find a Deploy Preview by number. [#](#default-deployment-options) Default deployment options ------------------------------------------------------------ By default, all functions are deployed with: * us-east-2 AWS Lambda region (for sites created after October 4, 2023) Private Connectivity If your team has [Private Connectivity](/security/private-connectivity/) enabled, note that this region selection makes your functions use the private network. * 1024 MB of memory * 30 second execution limit for synchronous functions, including [scheduled functions](/functions/scheduled-functions/) * 15 minute execution limit for [background functions](/functions/background-functions/) * 6 MB request and response payload size limit for buffered synchronous functions Lower effective limit for binary request payloads We Base64-encode requests with binary payloads such as image uploads. This encoding comes with approximately 30% overhead relative to the size of the original binary data, effectively reducing the binary request payload size limit to 4.5 MB. * 20 MB response payload size limit for streamed synchronous functions * 256 KB request and response payload size limit for [background functions](/functions/background-functions/) [#](#custom-deployment-options) Custom deployment options ---------------------------------------------------------- Depending on your [plan](https://www.netlify.com/pricing/?category=developer#features-custom-deployment-options-for-functions) , you can change the deployment options for synchronous functions. * [Region](/functions/optional-configuration/#region) can be customized through the Netlify UI. * [Private Connectivity](/security/private-connectivity/) can be enabled by [contacting your account manager](https://www.netlify.com/support/) . Limits other than the ones mentioned above cannot be changed. If you wish to deploy functions onto your own AWS account (in order to integrate with other AWS services on your account), please [contact sales](https://www.netlify.com/contact/) . [#](#more-functions-resources) More Functions resources -------------------------------------------------------- * [Get started with functions](/functions/get-started/) * [API](/functions/api/) * [Lambda compatibility](/functions/lambda-compatibility/) * [Trigger functions on events](/functions/trigger-on-events/) * [Functions and Identity](/functions/functions-and-identity/) * [Background Functions overview](/functions/background-functions/) * [Scheduled Functions overview](/functions/scheduled-functions/) * [On-demand Builders](/configure-builds/on-demand-builders/) * [Environment variables and functions](/functions/environment-variables/) * [Deploy functions](/functions/deploy/) * [Function logs](/functions/logs/) * [Optional configuration for functions](/functions/optional-configuration/) * [Functions usage and billing](/functions/usage-and-billing/) * [Function Metrics](/monitor-sites/function-metrics/) * [Use the Netlify Blobs API in a function](/blobs/overview/) * Go to our [Trust Center](https://trust-center.netlify-corp.com) to download our reference architecture for HIPAA-compliant composable sites on Netlify * Visit our [Forums](https://answers.netlify.com/categories) to join the conversation about Functions [Optional configuration for functions: Directory](/functions/optional-configuration/#directory) [Deploy functions](/functions/deploy/) [Deploy functions](/functions/deploy/?fn-language=js) Last updated: September 6, 2024 [Get started with functions](/functions/get-started/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Functions and Identity | Netlify Docs If you have [Identity](/security/secure-access-to-sites/identity/) enabled on your site, your serverless functions get access to the Identity instance and to Identity user claims in the `context` object. You can also trigger functions from Identity events. [#](#access-identity-info-with-clientcontext) Access Identity info with clientContext -------------------------------------------------------------------------------------- If an Identity service is active for a site, functions running on that site have access to an `identity` and a `user` object in Netlify’s base64-encoded custom `clientContext`. You can access the client context with TypeScript or JavaScript like this: * Loading error: Refresh the page to access this code sample import type { Handler, HandlerEvent, HandlerContext } from "@netlify/functions"; const handler: Handler = async function ( event: HandlerEvent, context: HandlerContext ) { const rawNetlifyContext = context.clientContext.custom.netlify; const netlifyContext = Buffer.from(rawNetlifyContext, 'base64').toString('utf-8'); const { identity, user } = JSON.parse(netlifyContext); // Do stuff and return a response... }; export { handler }; exports.handler = async function (event, context) { const rawNetlifyContext = context.clientContext.custom.netlify; const netlifyContext = Buffer.from(rawNetlifyContext, 'base64').toString('utf-8'); const { identity, user } = JSON.parse(netlifyContext); // Do stuff and return a response... }; Visit our docs on [Go functions](/functions/lambda-compatibility/?fn-language=go#access-the-clientcontext) to learn how to access the `clientContext` with Go. The `user` object is present if the function request has an `Authorization: Bearer ` header with a valid JWT from the Identity instance. In this case the object will contain the decoded claims. The `identity` object has `url` and `token` attributes. The URL is the endpoint for the underlying [GoTrue](https://github.com/netlify/gotrue) API powering the Identity service. The `token` attribute is a short-lived admin token that can be used to make requests as an admin to the GoTrue API. [#](#trigger-functions-on-identity-events) Trigger functions on Identity events -------------------------------------------------------------------------------- You can [trigger function calls](/functions/trigger-on-events/) when certain Identity events happen, like when a user signs up. The following events are currently available: * `identity-validate`: Triggered when an Identity user tries to sign up with Identity. * `identity-signup`: Triggered when an Identity user signs up with Netlify Identity and confirms their email address. Note that this fires for email+password signups only, not for signups using external providers such as Google or GitHub. * `identity-login`: Triggered when an Identity user logs in with Netlify Identity To set a synchronous function to trigger on one of these events, match the name of the function file to the name of the event. For example, to trigger a function on `identity-login` events, name the function file `identity-login.ts`. To trigger a [background function](/functions/background-functions/) on one of the Identity events, include the event name in the function file name. For example, to trigger a background function on `identity-login` events, name the function file `identity-login-background.ts`. If you return a status other than `200`, `202`, or `204` from one of these event functions, the signup or login will be blocked. The payload in the body of an Identity event function is formatted like: { "event": "login|signup|validate", "user": { # an Identity user object } } If your function returns a `200`, you can also return a JSON object with new `user_metadata` or `app_metadata` for the Identity user. For example: * Loading error: Refresh the page to access this code sample import type { Handler, HandlerEvent } from "@netlify/functions"; export async function handler(event: HandlerEvent): Handler { const user = JSON.parse(event.body).user; return { body: JSON.stringify({ ...user, app_metadata: { ...user.app_metadata, roles: ["admin"], }, }), statusCode: 200, }; } export async function handler(event) { const user = JSON.parse(event.body).user; return { body: JSON.stringify({ ...user, app_metadata: { ...user.app_metadata, roles: ["admin"], }, }), statusCode: 200, }; } This function replaces the value of the Identity user’s `app_metadata` to give them the `admin` role. Last updated: December 19, 2023 ← [Trigger on events](/functions/trigger-on-events/) [Background Functions](/functions/background-functions/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Deploy functions | Netlify Docs This page describes workflows for deploying your functions. Choose your programming language: * TypeScript * JavaScript * Go TypeScript JavaScript Go The deployment preparation process includes both compiling and bundling your TypeScript function files into executable artifacts. You can use [continuous deployment](#continuous-deployment-with-git) , the [Netlify CLI](#manual-deploys-with-cli) , or the [Netlify API](#file-digest-deploys-with-api) to deploy functions. [#](#continuous-deployment-with-git) Continuous deployment with Git -------------------------------------------------------------------- With [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) , your functions are built if needed and deployed each time you push changes to your Git provider. You can rely on [Netlify’s default automatic build process](#automatic-build) , use [your own custom build process on Netlify](#custom-build) , or [build outside of Netlify](#external-build) . ### [#](#automatic-build) Automatic build Netlify can automatically detect and build your functions from their source files. This is the most common workflow. To use this option, follow the TypeScript file naming instructions on the [get started with functions](/functions/get-started/?fn-language=ts) page. TypeScript and JavaScript together If you include TypeScript and JavaScript functions with the same name, for example, `my-function.ts` and `my-function.js`, the TypeScript function is ignored while the JavaScript function is deployed. This allows you to handle TypeScript compilation in a [custom build command](/functions/deploy/?fn-language=ts#custom-build) , if preferred. Netlify then bundles and deploys the resulting JavaScript function. ### [#](#custom-build) Custom build If you want more control over the handling of your function source files, you can use your site’s build command to customize the build process. Netlify runs your build command before accessing your functions directory to prepare and deploy your functions. This means you can use your build command to override any part of the default preparation process up until the point Netlify deploys executable artifacts. Here are some examples of customizations you could make to the process: * Bundle your functions with tools not available through Netlify such as Webpack or Rollup. * Run unit tests to validate your functions before they’re deployed. If you want your custom build to bypass Netlify’s automated function and dependency preparation entirely, your build process needs to result in Node.js ZIP archives in your functions directory. Netlify will deploy these without modification. To customize the build process, do one of the following: * Include customizations directly in your build command. For example: tsc hello/function.ts --outfile netlify/functions/hello.js This example customizes the TypeScript compilation stage. * Invoke scripts through a file called by your build command. For example: npm run test:functions && npm run build Where `test:functions` is a unit testing script configured in `package.json`. For more information, visit our Forums for a verified Support Guide on [testing your Netlify builds](https://answers.netlify.com/t/support-guide-testing-your-netlify-builds/1456) . ### [#](#external-build) External build For even more control over the handling of your function source files and dependencies, you can bundle ZIP archives outside of Netlify. If you put your bundled ZIP archives in your functions directory before you push changes to your Git provider, Netlify will deploy these executable artifacts without modification. Consider CLI deploys instead It’s not a best practice to track bundling results in Git. So, if you want to bundle your own ZIP archives, we recommend you use [CLI deploys](#manual-deploys-with-cli) instead of continuous deployment with Git. [#](#manual-deploys-with-cli) Manual deploys with CLI ------------------------------------------------------ Netlify CLI can upload files directly from your local project directory to your site on Netlify. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * deploying to Netlify at the end of external CI tool tasks Prepare your function dependencies before you deploy with the CLI. 1. Install your dependencies. This enables Netlify CLI to automatically zip dependencies with your functions for deployment. 2. Follow the [instructions on the CLI page](/cli/get-started/#manual-deploys) to deploy your site including your functions. TypeScript and JavaScript together If you include TypeScript and JavaScript functions with the same name, for example, `my-function.ts` and `my-function.js`, the TypeScript function is ignored while the JavaScript function is deployed. This allows you to handle TypeScript compilation locally, if preferred. Netlify then bundles and deploys the resulting JavaScript function. [#](#file-digest-deploys-with-api) File digest deploys with API ---------------------------------------------------------------- Netlify API can upload functions when you use the file digest method for manual deploys. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * automating workflows that connect with other systems Prepare your functions before you deploy with the API. 1. Zip each function with its dependencies. 2. Follow the [instructions on the API page](/api/get-started/#deploy-with-the-api) to deploy your site including executable artifacts for Netlify Functions. The deployment preparation process includes bundling your JavaScript function files into executable artifacts. You can use [continuous deployment](#continuous-deployment-with-git-2) , the [Netlify CLI](#manual-deploys-with-cli-2) , or the [Netlify API](#file-digest-deploys-with-api-2) to deploy functions. [#](#continuous-deployment-with-git-2) Continuous deployment with Git ---------------------------------------------------------------------- With [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) , your functions are built if needed and deployed each time you push changes to your Git provider. You can rely on [Netlify’s default automatic build process](#automatic-build-2) , use [your own custom build process on Netlify](#custom-build-2) , or [build outside of Netlify](#external-build-2) . ### [#](#automatic-build-2) Automatic build Netlify can automatically detect and build your functions from their source files. This is the most common workflow. To use this option, follow the JavaScript file naming instructions on the [get started with functions](/functions/get-started/?fn-language=js) page. TypeScript and JavaScript together If you include TypeScript and JavaScript functions with the same name, for example, `my-function.ts` and `my-function.js`, the TypeScript function is ignored while the JavaScript function is deployed. This allows you to handle TypeScript compilation in a [custom build command](/functions/deploy/?fn-language=ts#custom-build) , if preferred. Netlify then bundles and deploys the resulting JavaScript function. ### [#](#custom-build-2) Custom build If you want more control over the handling of your function source files, you can use your site’s build command to customize the build process. Netlify runs your build command before accessing your functions directory to prepare and deploy your functions. This means you can use your build command to override any part of the default preparation process up until the point Netlify deploys executable artifacts. Here are some examples of customizations you could make to the process: * Bundle your functions with tools not available through Netlify such as Webpack or Rollup. * Run unit tests to validate your functions before they’re deployed. If you want your custom build to bypass Netlify’s automated function and dependency preparation entirely, your build process needs to result in Node.js ZIP archives in your functions directory. Netlify will deploy these without modification. To customize the build process, do one of the following: * Include customizations directly in your build command. For example: rollup hello/function.js --file netlify/functions/hello.js --format cjs This example uses Rollup to bundle a specific function. * Invoke scripts through a file called by your build command. For example: npm run test:functions && npm run build Where `test:functions` is a unit testing script configured in `package.json`. For more information, visit our Forums for a verified Support Guide on [testing your Netlify builds](https://answers.netlify.com/t/support-guide-testing-your-netlify-builds/1456) . ### [#](#external-build-2) External build For even more control over the handling of your function source files and dependencies, you can bundle ZIP archives outside of Netlify. If you put your bundled ZIP archives in your functions directory before you push changes to your Git provider, Netlify will deploy these executable artifacts without modification. Consider CLI deploys instead It’s not a best practice to track bundling results in Git. So, if you want to bundle your own ZIP archives, we recommend you use [CLI deploys](#manual-deploys-with-cli-2) instead of continuous deployment with Git. [#](#manual-deploys-with-cli-2) Manual deploys with CLI -------------------------------------------------------- Netlify CLI can upload files directly from your local project directory to your site on Netlify. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * deploying to Netlify at the end of external CI tool tasks Prepare your function dependencies before you deploy with the CLI. 1. Install your dependencies. This enables Netlify CLI to automatically zip dependencies with your functions for deployment. 2. Follow the [instructions on the CLI page](/cli/get-started/#manual-deploys) to deploy your site including your functions. TypeScript and JavaScript together If you include TypeScript and JavaScript functions with the same name, for example, `my-function.ts` and `my-function.js`, the TypeScript function is ignored while the JavaScript function is deployed. This allows you to handle TypeScript compilation locally, if preferred. Netlify then bundles and deploys the resulting JavaScript function. [#](#file-digest-deploys-with-api-2) File digest deploys with API ------------------------------------------------------------------ Netlify API can upload functions when you use the file digest method for manual deploys. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * automating workflows that connect with other systems Prepare your functions before you deploy with the API. 1. Zip each function with its dependencies. 2. Follow the [instructions on the API page](/api/get-started/#deploy-with-the-api) to deploy your site including executable artifacts for Netlify Functions. The deployment preparation process includes compiling your Go function files into executable artifacts. You can use [continuous deployment](#continuous-deployment-with-git-3) , the [Netlify CLI](#manual-deploys-with-cli-3) , or the [Netlify API](#file-digest-deploys-with-api-3) to deploy functions. [#](#continuous-deployment-with-git-3) Continuous deployment with Git ---------------------------------------------------------------------- With [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) , your functions are built if needed and deployed each time you push changes to your Git provider. You can rely on [Netlify’s default automatic build process](#automatic-build-3) , use [your own custom build process on Netlify](#custom-build-3) , or [build outside of Netlify](#external-build-3) . ### [#](#automatic-build-3) Automatic build Netlify can automatically detect and build your functions from their source files. This is the most common workflow. To use this option, follow the Go file naming instructions on the [Lambda compatibility for Functions](/functions/lambda-compatibility/?fn-language=go) page. ### [#](#custom-build-3) Custom build If you want more control over the handling of your function source files, you can use your site’s build command to customize the build process. Netlify runs your build command before accessing your functions directory to prepare and deploy your functions. This means you can use your build command to override any part of the default preparation process up until the point Netlify deploys executable artifacts. Here are some examples of customizations you could make to the process: * Detect source files from several different directories. * Run unit tests to validate your functions before they’re deployed. If you want your custom build to bypass Netlify’s automated function preparation entirely, your build process needs to result in binaries compiled for the `linux` operating system and `amd64` architecture in your functions directory. Netlify will deploy these without modification. You can customize `go build` in one of the following ways. * Include `go build` directly in your build command. For example: GOOS=linux GOARCH=amd64 go build -o netlify/functions/hello ./hello/function.go && GOOS=linux GOARCH=amd64 go build -o netlify/functions/goodbye ./goodbye/function.go This example builds source files saved in multiple different directories into compiled binaries in the functions directory for deployment. * Invoke `go build` through a file called by the build command. For example: npm run build && npm run build:function This example invokes a script stored in `package.json`. Visit the [example repository](https://github.com/futuregerald/next-function) to explore the full example. ### [#](#external-build-3) External build For even more control over the handling of your function source files, you can compile binaries outside of Netlify. The binaries must be compiled for the `linux` operating system and `amd64` architecture. Use the Go compilation environment variables `GOOS` and `GOARCH` to set the compiler targets: GOOS=linux GOARCH=amd64 go build If you put your compiled binaries in your functions directory before you push changes to your Git provider, Netlify will deploy these executable artifacts without modification. Consider CLI deploys instead It’s not a best practice to track compilation results in Git. So, if you want to compile your own binaries, we recommend you use [CLI deploys](#manual-deploys-with-cli-3) instead of continuous deployment with Git. [#](#manual-deploys-with-cli-3) Manual deploys with CLI -------------------------------------------------------- Netlify CLI can upload files directly from your local project directory to your site on Netlify. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * deploying to Netlify at the end of external CI tool tasks Prepare your functions before you deploy with the CLI. 1. Compile your Go functions to binaries for the `linux` operating system and `amd64` architecture in your functions directory. GOOS=linux GOARCH=amd64 go build 2. Follow the [instructions on the CLI page](/cli/get-started/#manual-deploys) to deploy your site including executable artifacts for Netlify Functions. [#](#file-digest-deploys-with-api-3) File digest deploys with API ------------------------------------------------------------------ Netlify API can upload functions when you use the file digest method for manual deploys. Common use cases for this workflow: * updating a site while [builds are stopped](/configure-builds/stop-or-activate-builds/) * automating workflows that connect with other systems Prepare your functions before you deploy with the API. 1. Compile your Go functions to binaries for the `linux` operating system and `amd64` architecture in your functions directory. GOOS=linux GOARCH=amd64 go build 2. Follow the [instructions on the API page](/api/get-started/#deploy-with-the-api) to deploy your site including executable artifacts for Netlify Functions. Last updated: November 1, 2023 ← [Environment variables](/functions/environment-variables) [Logs](/functions/logs/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Optional configuration for functions | Netlify Docs This document describes optional configuration settings you can use for more control over how your functions are built, deployed, and executed. Choose your programming language: * TypeScript * JavaScript * Go TypeScript JavaScript Go [#](#directory) Directory -------------------------- Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function. The default directory is `YOUR_BASE_DIRECTORY/netlify/functions`. You can customize the directory using the Netlify UI or file-based configuration. * In the Netlify UI, go to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** and select **Configure**. In the **Functions directory** field, enter a path to the directory in your repository where you want to store your functions. ![](/images/functions-folder-setting.png) * Alternatively, add the following to `netlify.toml` for [file-based configuration](/configure-builds/file-based-configuration/) . [functions] directory = "my_functions" Settings in `netlify.toml` override settings in the Netlify UI. For both methods, the path is an absolute path relative to the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. To help keep your site secure, make sure your functions directory is outside of your [publish directory](/configure-builds/overview/#definitions-1) so that your source files aren’t deployed as part of your site. [#](#region) Region -------------------- This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify offers several [AWS regions](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) for deploying your serverless functions. You may want to customize the region for the following reasons: * **Optimize performance.** Deploying serverless functions close to their data sources, such as a database or another backend service, can greatly reduce roundtrip time for data retrieval resulting in faster response times for your users. * **Ensure compliance.** In some cases, data protection laws and industry-specific regulations may require that sensitive data processing happens within specific regions. * **Use Private Connectivity.** Static IP addresses for [Private Connectivity](/security/private-connectivity/) are available in only some regions. By default, Netlify deploys functions for new sites to `us-east-2` (Ohio). This is a common choice for many database providers, so this optimizes performance for most cases. You can change the region through the Netlify UI to one of the following regions. * ap-northeast-1 - Asia Pacific (Tokyo) * ap-southeast-1 - Asia Pacific (Singapore) * ap-southeast-2 - Asia Pacific (Sydney) * ca-central-1 - Canada (Central) * eu-central-1 - EU (Frankfurt) * eu-west-1 - EU (Ireland) * eu-west-2 - EU (London) * sa-east-1 - South America (São Paulo) * us-east-1 - US East (N. Virginia) * us-east-2 - US East (Ohio) * us-west-1 - US West (N. California) * us-west-2 - US West (Oregon) In addition to the above self-serve regions, the following regions are available through support-assisted configuration. * eu-north-1 - EU (Stockholm) * eu-west-3 - EU (Paris) * eu-south-1 - EU (Milan) If you want your site to use one of the above regions, please [contact support](https://www.netlify.com/support/) . To configure your functions region through the Netlify UI: 1. Go to **Site configuration \> Build & deploy \> Continuous deployment \> Functions region** . 2. Select **Configure**. 3. Use the menu to select a new region. 4. Confirm with **Save**. 5. Redeploy your site to apply the new region configuration. Old deploys will continue to use the region configuration from when they were deployed. [#](#bundle) Bundle -------------------- For granular control over which files are bundled in your executable function artifacts, use the `netlify.toml` properties `external_node_modules` and `included_files`. Visit the [file-based configuration](/configure-builds/file-based-configuration/#functions) doc for details. [functions] # Flags "package-1" as an external node module for all functions. external_node_modules = ["package-1"] # Includes all Markdown files inside the "files/" directory. included_files = ["files/*.md"] [#](#node-js-version-for-runtime) Node.js version for runtime -------------------------------------------------------------- For all Node.js functions deployed on or after May 15, 2023, the default functions runtime is based on the [Node.js version used for the build](/configure-builds/manage-dependencies/#node-js-and-javascript) . The Node.js version used for the build must be a valid [AWS Lambda runtime for Node.js](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) that isn’t set to be deprecated in the next two months. If the build uses a version of Node.js that does not meet these conditions, then the functions runtime uses a fallback default version of Node.js 18. You can override the default to any valid [AWS Lambda runtime for Node.js](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) that isn’t set to be deprecated in the next two months. Do so by completing the following steps. 1. In the Netlify UI, [set the environment variable](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) `AWS_LAMBDA_JS_RUNTIME` to the desired version. For example, to use Node.js 20 for all future functions deployed, set the variable value to `nodejs20.x`. 2. Redeploy your site to apply the new runtime version. Note that this environment variable must be set using the Netlify UI, CLI, or API, and not with a Netlify configuration file (`netlify.toml`). [#](#directory-2) Directory ---------------------------- Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function. The default directory is `YOUR_BASE_DIRECTORY/netlify/functions`. You can customize the directory using the Netlify UI or file-based configuration. * In the Netlify UI, go to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** and select **Configure**. In the **Functions directory** field, enter a path to the directory in your repository where you want to store your functions. ![](/images/functions-folder-setting.png) * Alternatively, add the following to `netlify.toml` for [file-based configuration](/configure-builds/file-based-configuration/) . [functions] directory = "my_functions" Settings in `netlify.toml` override settings in the Netlify UI. For both methods, the path is an absolute path relative to the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. To help keep your site secure, make sure your functions directory is outside of your [publish directory](/configure-builds/overview/#definitions-1) so that your source files aren’t deployed as part of your site. [#](#region-2) Region ---------------------- This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify offers several [AWS regions](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) for deploying your serverless functions. You may want to customize the region for the following reasons: * **Optimize performance.** Deploying serverless functions close to their data sources, such as a database or another backend service, can greatly reduce roundtrip time for data retrieval resulting in faster response times for your users. * **Ensure compliance.** In some cases, data protection laws and industry-specific regulations may require that sensitive data processing happens within specific regions. * **Use Private Connectivity.** Static IP addresses for [Private Connectivity](/security/private-connectivity/) are available in only some regions. By default, Netlify deploys functions for new sites to `us-east-2` (Ohio). This is a common choice for many database providers, so this optimizes performance for most cases. You can change the region through the Netlify UI to one of the following regions. * ap-northeast-1 - Asia Pacific (Tokyo) * ap-southeast-1 - Asia Pacific (Singapore) * ap-southeast-2 - Asia Pacific (Sydney) * ca-central-1 - Canada (Central) * eu-central-1 - EU (Frankfurt) * eu-west-1 - EU (Ireland) * eu-west-2 - EU (London) * sa-east-1 - South America (São Paulo) * us-east-1 - US East (N. Virginia) * us-east-2 - US East (Ohio) * us-west-1 - US West (N. California) * us-west-2 - US West (Oregon) In addition to the above self-serve regions, the following regions are available through support-assisted configuration. * eu-north-1 - EU (Stockholm) * eu-west-3 - EU (Paris) * eu-south-1 - EU (Milan) If you want your site to use one of the above regions, please [contact support](https://www.netlify.com/support/) . To configure your functions region through the Netlify UI: 1. Go to **Site configuration \> Build & deploy \> Continuous deployment \> Functions region** . 2. Select **Configure**. 3. Use the menu to select a new region. 4. Confirm with **Save**. 5. Redeploy your site to apply the new region configuration. Old deploys will continue to use the region configuration from when they were deployed. [#](#bundle-2) Bundle ---------------------- To optimize bundling time and artifact size, you can have Netlify use [esbuild](https://esbuild.github.io/) for bundling your JavaScript functions. Enable this opt-in beta feature in [`netlify.toml`](/configure-builds/file-based-configuration/) . [functions] node_bundler = "esbuild" For granular control over which files are bundled in your executable function artifacts, use the `netlify.toml` properties `external_node_modules` and `included_files`. Visit the [file-based configuration](/configure-builds/file-based-configuration/#functions) doc for details. [functions] # Flags "package-1" as an external node module for all functions. external_node_modules = ["package-1"] # Includes all Markdown files inside the "files/" directory. included_files = ["files/*.md"] [#](#node-js-version-for-runtime-2) Node.js version for runtime ---------------------------------------------------------------- For all Node.js functions deployed on or after May 15, 2023, the default functions runtime is based on the [Node.js version used for the build](/configure-builds/manage-dependencies/#node-js-and-javascript) . The Node.js version used for the build must be a valid [AWS Lambda runtime for Node.js](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) that isn’t set to be deprecated in the next two months. If the build uses a version of Node.js that does not meet these conditions, then the functions runtime uses a fallback default version of Node.js 18. You can override the default to any valid [AWS Lambda runtime for Node.js](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) that isn’t set to be deprecated in the next two months. Do so by completing the following steps. 1. In the Netlify UI, [set the environment variable](/environment-variables/get-started/#create-variables-with-the-netlify-ui-cli-or-api) `AWS_LAMBDA_JS_RUNTIME` to the desired version. For example, to use Node.js 20 for all future functions deployed, set the variable value to `nodejs20.x`. 2. Redeploy your site to apply the new runtime version. Note that this environment variable must be set using the Netlify UI, CLI, or API, and not with a Netlify configuration file (`netlify.toml`). [#](#directory-3) Directory ---------------------------- Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function. The default directory is `YOUR_BASE_DIRECTORY/netlify/functions`. You can customize the directory using the Netlify UI or file-based configuration. * In the Netlify UI, go to **Site configuration \> Build & deploy \> Continuous deployment \> Build settings** and select **Configure**. In the **Functions directory** field, enter a path to the directory in your repository where you want to store your functions. ![](/images/functions-folder-setting.png) * Alternatively, add the following to `netlify.toml` for [file-based configuration](/configure-builds/file-based-configuration/) . [functions] directory = "my_functions" Settings in `netlify.toml` override settings in the Netlify UI. For both methods, the path is an absolute path relative to the site’s [base directory](/configure-builds/overview/#definitions-1) in your repository. To help keep your site secure, make sure your functions directory is outside of your [publish directory](/configure-builds/overview/#definitions-1) so that your source files aren’t deployed as part of your site. [#](#region-3) Region ---------------------- This feature is available on [Pro](https://www.netlify.com/pricing/?category=developer) and [Enterprise](https://www.netlify.com/pricing/?category=enterprise) plans. Netlify offers several [AWS regions](https://docs.aws.amazon.com/general/latest/gr/lambda-service.html) for deploying your serverless functions. You may want to customize the region for the following reasons: * **Optimize performance.** Deploying serverless functions close to their data sources, such as a database or another backend service, can greatly reduce roundtrip time for data retrieval resulting in faster response times for your users. * **Ensure compliance.** In some cases, data protection laws and industry-specific regulations may require that sensitive data processing happens within specific regions. * **Use Private Connectivity.** Static IP addresses for [Private Connectivity](/security/private-connectivity/) are available in only some regions. By default, Netlify deploys functions for new sites to `us-east-2` (Ohio). This is a common choice for many database providers, so this optimizes performance for most cases. You can change the region through the Netlify UI to one of the following regions. * ap-northeast-1 - Asia Pacific (Tokyo) * ap-southeast-1 - Asia Pacific (Singapore) * ap-southeast-2 - Asia Pacific (Sydney) * ca-central-1 - Canada (Central) * eu-central-1 - EU (Frankfurt) * eu-west-1 - EU (Ireland) * eu-west-2 - EU (London) * sa-east-1 - South America (São Paulo) * us-east-1 - US East (N. Virginia) * us-east-2 - US East (Ohio) * us-west-1 - US West (N. California) * us-west-2 - US West (Oregon) In addition to the above self-serve regions, the following regions are available through support-assisted configuration. * eu-north-1 - EU (Stockholm) * eu-west-3 - EU (Paris) * eu-south-1 - EU (Milan) If you want your site to use one of the above regions, please [contact support](https://www.netlify.com/support/) . To configure your functions region through the Netlify UI: 1. Go to **Site configuration \> Build & deploy \> Continuous deployment \> Functions region** . 2. Select **Configure**. 3. Use the menu to select a new region. 4. Confirm with **Save**. 5. Redeploy your site to apply the new region configuration. Old deploys will continue to use the region configuration from when they were deployed. [#](#go-version-for-builds) Go version for builds -------------------------------------------------- The Go version used in the deployment pipeline is determined by your site’s [build image](/configure-builds/overview/#build-image-selection) . To modify the Go version used for your builds, change the build image for your site at **Site configuration \> Build & deploy \> Continuous Deployment \> Build image selection** . Last updated: October 11, 2023 ← [Logs](/functions/logs/) [Usage & billing](/functions/usage-and-billing/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Large Media overview | Netlify Docs This feature is deprecated Netlify’s Large Media service is [deprecated](/platform/release-phases/#deprecated) . While Large Media continues to function for sites that currently have it enabled, new Large Media configuration is not recommended. Refer to the [deprecation notice](https://answers.netlify.com/t/large-media-feature-deprecated-but-not-removed/100804) in our Support Forums for alternative services and more information. To avoid the risk of file loss, read our [Uninstalling Large Media](https://answers.netlify.com/t/support-guide-uninstalling-large-media/17662) Support Guide and [contact support](https://www.netlify.com/support/) for assistance turning off Large Media for an existing site. Storing your site content in a Git repository is great until you start adding large files that aren’t made up of text — files like images, ZIP files, and PDFs. Git’s system of tracking diffs doesn’t work with these files, so it saves full copies of every version in your Git repository. Netlify Large Media uses [Git LFS](https://git-lfs.github.com/) to take advantage of the benefits of Git version tracking without bloating your repository. Your designated Large Media files are uploaded directly to our media servers while Git tracks their versions with text pointer files in the repository. This saves local development time and speeds up builds in the following ways: * **Smaller repositories.** Whether you’re cloning for local development, or our build system is cloning to run your build, smaller repositories mean faster clones. * **Separate uploads.** Uploads to our Large Media service run in parallel with the build, so both processes can run as efficiently as possible. * **Transformations when you need them.** With our [image transformation](/git/large-media/transform-images/) service, you can serve the exact image size you need for each context, from thumbnail to retina, without having to save multiple versions or run repetitive resizing operations in your build. [#](#large-media-docs) Large Media docs ---------------------------------------- Find the information you need about Netlify Large Media. **Requirements and limitations** – Large Media changes how your Git repository works, so it’s important to review the [requirements and limitations](/git/large-media/requirements-and-limitations/) before getting started. **Setup** – Once you’re clear on the requirements and limitations, head to [setup](/git/large-media/setup/) to learn how to connect your site and repository with Large Media. **Repository collaboration** – Learn about [options for collaboration](/git/large-media/repository-collaboration/) in repositories enabled for Large Media, including workflows using Git and a CMS. **Transform images** – With Large Media enabled on your site, you can use query parameters to have our servers [transform images](/git/large-media/transform-images/) to the exact dimensions you need. **Usage and billing** – Find out how Large Media service usage is metered on the [usage and billing](/git/large-media/usage-and-billing/) page. Last updated: September 21, 2023 [Requirements & limitations](/git/large-media/requirements-and-limitations/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Get started with Netlify | Netlify Docs This tutorial will help you learn how to deploy a demo project on Netlify to make it available on the web. It will also introduce some of Netlify’s key features to manage sites, stores, or apps, and set up visual editing. Start exploring a demo site [Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-feature-tour) Want to explore a demo site first? You can return to this guide to help you get to know some key features including Deploy Previews, rollbacks, Netlify Functions, visual editing, environment variables, redirects, and Netlify Forms. * [Demo repo](https://github.com/netlify/netlify-feature-tour) * [Demo site](https://feature-tour.netlify.app/) * [Feature tour](https://feature-tour.netlify.app/) [#](#introduction) Introduction -------------------------------- To get started with your first project on Netlify, we’ll deploy a demo website. Here’s a [live example](https://feature-tour.netlify.app/) . By the end of this tutorial, you will have completed these steps to help familiarize yourself with Netlify workflows: * clone project code from an example repository in GitHub and create a new site in the Netlify UI * leverage continuous deployment in Netlify to kick off an automated build process that generates site assets * visit your demo project’s URL after Netlify uploads site assets to a content delivery network (CDN) and makes your demo site available * make changes to the example code and explore some key Netlify features This tutorial’s example project uses the [Astro](https://astro.build/) frontend framework. If you’re not familiar with it, that’s totally fine. Understanding the framework isn’t necessary to complete this tutorial. ### [#](#development-environment-prerequisites) Development environment prerequisites Here’s what you’ll need to have set up to follow along with the steps in each section: * A code editor like [Visual Studio Code](https://code.visualstudio.com/) . * [Git](https://git-scm.com/) installed on your system. * An account with a Git provider: [GitHub](https://github.com/) , [GitLab](https://about.gitlab.com/) , or [Azure DevOps](https://azure.microsoft.com/en-us/products/devops/?nav=min#Overview-2) . This tutorial includes instructions for GitHub only, but you can use one of the other supported Git providers instead. * [Node.js](https://nodejs.org/en/) 14.15.0 or later installed on your system. Installing Node.js will also install [npm](https://www.npmjs.com/) . * [Netlify CLI](/cli/get-started/) installed on your system, for testing out Netlify Functions in a local development environment. [#](#deploy-a-project-to-netlify) Deploy a project to Netlify -------------------------------------------------------------- One way to get started deploying on Netlify is to use a Deploy to Netlify button to add a site. 1. Select the Deploy to Netlify button. [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-feature-tour) You will get directed to the Netlify app to create a new site. You should find the following page, asking you to connect to GitHub. ![Welcome to Netlify.](/images/get-started-connect-github.png) 2. Select **Connect to GitHub** to authenticate. If you don’t already have a Netlify user account, you will get one as part of this process. 3. Select **Save & Deploy**. As well as creating a new site on Netlify, this process clones the [demo project repository](https://github.com/netlify/netlify-feature-tour) to your GitHub account so you can make your own changes later on. You will be redirected to the **Deploy details** page in the Netlify UI. You can check that the repository was successfully created by selecting **HEAD** to navigate to your new repository on GitHub. Once the deploy is complete, the cloned project will be available in this new repository. ![Deploy details page with GitHub link.](/images/get-started-deploys-from-github.png) 4. When the site deploy succeeds, you should get a production URL where you can access the website. Select **Open production deploy** to check it out. ![Open production deploy from Deploy details page.](/images/get-started-prod-url.png) Here’s what you can expect for the example site homepage: ![Netlify Feature Tour.](/images/get-started-demo-site-homepage.png) 5. You can choose to customize the URL by changing the site’s name in the Netlify UI at **Site configuration \> Site details \> Site information** . Now that we’ve deployed a site on Netlify and generated a public URL, let’s make some changes to the code to customize the site and learn about some helpful features. ### [#](#generate-deploy-previews) Generate Deploy Previews One of the most useful aspects of Netlify is the ability to generate unique [Deploy Previews](/site-deploys/deploy-previews/) for each pull/merge request. Every push to the pull/merge request updates the Deploy Preview and generates a unique [atomic deploy](https://www.netlify.com/blog/2021/02/23/terminology-explained-atomic-and-immutable-deploys/) with a permalink that you can share and refer back to. To understand how this works in practice, we’ll make some changes to the code. 1. Start by cloning the repository that was created on your GitHub account to create a copy on your local machine. Check out the GitHub docs for instructions on how to [clone a repo](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) . 2. In your terminal, use the `cd` command to change your working directory to the location that contains your local copy of the repository. 3. Run the following command to install dependencies: npm install 4. Create and check out a new branch off of `main` by running the following command: git checkout -b myChanges 5. Open the local project directory in your favorite code editor, and open the `deploy-previews.astro` file in `/src/pages`. Let’s make a very small copy change to update the `

` to say `This is a Deploy Preview`.

This is a Deploy Preview.

6. Save the `deploy-previews.astro` file. Then from your terminal, commit and push this change to GitHub: git commit -am "update the h2" git push -u origin myChanges 7. Create a pull request as if you were going to merge this change into your `main` branch. Check out the [GitHub docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request#creating-the-pull-request) for details on how to do this. A few things are kicked off on GitHub automatically once you’ve created the pull request. A [comment is added](/site-deploys/notifications/#github-pull-request-comments) with information about your Deploy Preview, including a link to the Netlify [deploy log](/site-deploys/overview/#deploy-log) . ![Comment from netlify bot.](/images/get-started-github-netlify-bot-comment.png) Some [checks are triggered](/site-deploys/notifications/#github-commit-checks) that provide insights on the deploy. ![Commit checks for header rules, pages changed, redirect rules, deploy preview.](/images/get-started-github-successful-commit-checks.png) 8. When Netlify is done building and deploying the site, check the GitHub pull request comment. Find **Deploy Preview** and select the generated Deploy Preview URL. 9. Navigate to the Deploy Previews page on the demo site (`YOUR_DEPLOY_PREVIEW_URL/deploy-previews`), and note that the `

` has changed. Examine the URL and note that your site’s name is prepended with `deploy-preview-` and a number that represents the pull/merge request number. For each pull or merge request, you get a unique URL that serves a version of your site containing the changes specific to that pull/merge request. 10. In the GitHub pull request comment, find **Latest deploy log** and select the associated link. You should be directed to the Netlify UI. If you hover over **Permalink** in the header section, you might notice that, instead of `deploy-preview`, the site name is prepended with a deploy ID such as `61c36a332214be000842be44`. A unique permalink is generated for each atomic deploy. ![](/images/get-started-deploy-with-permalink.png) Set up automatic deploy subdomains to ensure deploys are accessible If you use Netlify DNS to manage a custom domain for your site, we recommend that you consider [setting an automatic deploy subdomain](/domains-https/custom-domains/automatic-deploy-subdomains/) for your Deploy Previews. This ensures that the deploys are not blocked by any third-party scripts or services that require this, such as local internet service providers. ### [#](#collaborate-with-deploy-previews) Collaborate with Deploy Previews Deploy Previews streamline your workflows by giving you the ability to collect reviewer feedback through the preview and have everything synced with the related pull/merge request. 1. If you’re using GitHub, install the [Netlify GitHub App](https://github.com/apps/netlify) to enable the Deploy Preview collaboration tools. As we’ve already created a Netlify site, you will need to [update the existing site to use the app](/git/repo-permissions-linking/#install-on-an-existing-site) . 2. Open the Deploy Preview URL, and locate the [Netlify Drawer](/site-deploys/deploy-previews/#collaborative-deploy-previews) at the bottom of the window. ![Netlify Drawer, closed](/images/site-deploys-netlify-drawer-on-deploy-preview-logged-in.png) 3. Select the left side of the Netlify Drawer to open it. From there, you can add comments including screenshots and videos captured right from the Deploy Preview, add team members to solicit their thoughts, and integrate with other tools you may use to manage feedback such as Jira and Trello. You can also access deploy logs right from the Deploy Preview to troubleshoot issues you find while reviewing. Any comment added using the Netlify Drawer on a Deploy Preview is automatically posted in the corresponding pull/merge request and vice versa so everyone can work in context. ### [#](#publish-changes) Publish changes After making some changes locally, pushing commits to GitHub, and checking that everything is fine on a Deploy Preview, the next step is to publish the changes to production by merging your branch to `main`. 1. In GitHub, merge your pull request. Check out the [GitHub docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/merging-a-pull-request#merging-a-pull-request) for details. 2. In the Netlify UI, locate the new production build in the **Deploys** list. ![](/images/get-started-new-prod-deploy.png) 3. When the production build’s status badge changes to `Published`, visit the production URL. The `

` change on the `YOUR_URL/deploy-previews/` page should be live. ### [#](#roll-back-instantly) Roll back instantly Oh no, we’ve made a mistake! The page now says `This is a Deploy Preview` but it’s in production. Don’t worry; we can use Netlify’s [one-click rollback](https://www.netlify.com/blog/2021/07/12/how-to-rollback-a-deploy-in-2-seconds-on-netlify/) . 1. On the **Deploys** page, select the very first deploy for the site. 2. Select **Publish deploy**. ![](/images/get-started-publish-deploy-for-rollback.png) Netlify replaces whatever is in production with the version of the code attached to the selected deploy. 3. Visit the production URL again, where the text on the `YOUR_URL/deploy-previews/` page should be back to `Try out Deploy Previews`. [#](#test-out-netlify-functions) Test out Netlify Functions ------------------------------------------------------------ You could use Netlify only for the ease of continuous deployment, but that would be missing out on a lot of other features that can simplify your workflows such as [Netlify Functions](/functions/overview/) . Netlify Functions are serverless functions that are version-controlled, built, and deployed along with the rest of your Netlify site. This allows you to add backend functionality to your projects without having to set up and configure a server or coordinate deployments between your app and your functions. We’ll walk through the steps to set up a function. 1. Go back to the example site repository in your code editor, and note the `netlify` folder with a `functions` folder inside. If you add function files or subfolders with function files here, Netlify will automatically detect that your project uses functions. 2. Before creating a new file, make sure you switch back to the `main` branch of the project and pull the latest changes. Here are the commands to run in your terminal: git checkout main git pull origin main 3. Create a new `hello-world.js` file in the `netlify/functions` folder. Normally, we recommend doing this in a separate branch instead of `main` to uphold branching best practices, but we’ve shortened the versioning workflow for this tutorial. 4. Copy and paste the following code with the minimum structure required for Netlify Functions, then save the file. exports.handler = async () => { return { statusCode: 200, body: "hello world!" }; }; 5. To run our function while developing locally, we’ll use the [Netlify Dev](/cli/local-development/) functionality of the [Netlify CLI](/cli/get-started/) . Run the following command in your terminal (or the shortcut `ntl dev`): netlify dev 6. Visit `http://localhost:8888/.netlify/functions/hello-world`, and you should find `hello world!` on the page. Having trouble with your function? Make sure the `hello-world.js` file is nested inside the `functions` folder, not directly under `netlify`. ### [#](#use-environment-variables) Use environment variables One of the advantages of using Netlify Functions relates to writing code that uses [environment variables](/environment-variables/overview/) . Instead of having to add an `.env` file in your project, you can create environment variables on Netlify and refer to them in your function with `process.env` syntax. This allows you to use external APIs that require secret tokens, such as Stripe, Slack, and Airbase, while keeping everything secret. What happens in a serverless function is not visible in the frontend when making requests. Let’s try this out by adding an environment variable in the Netlify UI. 1. Navigate to **Site configuration \> Environment variables** . Then select **Add a variable**. 2. Add an environment variable with a **Key** of `MY_SECRET`. Select **Same value for all deploy contexts** and enter a value to use here. Leave the [scope](/environment-variables/overview/#scopes) as the default value to include all **All scopes**. Then, select **Create variable**. ![The environment variable creation form showing an example variable with a scope set to functions](/images/get-started-environment-variable.png) 3. Return to your code editor and the `hello-world.js` file, add a reference to the new environment variable using `process.env.MY_SECRET`, and save the file. exports.handler = async () => { const mySecret = process.env.MY_SECRET; return { statusCode: 200, body: `hello world! I have a ${mySecret}` }; }; 4. To verify that this works correctly, we’ll need to take a couple of steps to allow Netlify CLI to get access to the environment variables for the site we want to serve. First, exit out of the Netlify Dev environment. (On macOS, that’s control + C). Then run this command in your terminal (or the shortcut `ntl link`): netlify link When prompted by Netlify CLI, follow the instructions to link the Netlify site. This gives the local environment access to data stored in Netlify servers. 5. Restart the local development environment by running this command in your terminal (or the shortcut `ntl dev`): netlify dev 6. Visit `http://localhost:8888/.netlify/functions/hello-world`, and you should find your environment variable’s value referenced on the page. ### [#](#redirect-a-path) Redirect a path If you think that entering `/.netlify/functions/hello-world` is a bit cumbersome, you might want to set up a [redirect](/routing/redirects/) to invoke the function. 1. In your code editor, find a file called `_redirects` in the `public` folder. 2. Copy and paste this redirect rule: /api/* /.netlify/functions/:splat Adding this rule means that, when there’s a request to `YOUR_URL/api/hello-world`, Netlify redirects it to `YOUR_URL/.netlify/functions/hello-world`. 3. To try it out, commit and push the changes to GitHub. Make sure to commit and push the `hello-world.js` functions file as well. git add . git commit -am "add a redirect and function" git push -u origin main 4. Wait for your production build to finish, then visit your site at `YOUR_URL/api/hello-world`. You should find the `hello world!` body returned by your function. [#](#set-up-netlify-forms) Set up Netlify Forms ------------------------------------------------ One last feature we’ll introduce in this tutorial is [Netlify Forms](/forms/setup/) . If you’re building a project that collects users’ input through a form, Netlify can handle submissions, data, and basic spam filtering with a single line of code. 1. In the Netlify UI, [enable automatic form detection](/forms/setup/#enable-form-detection) . Navigate to **Forms** , and select **Enable form detection**. 2. In your code editor, open the `netlify-forms.astro` file in `/src/pages` and locate the `
` HTML element. So far, this is a standard form. 3. Add the attribute `data-netlify="true"` to the form element, like this: 4. Commit and push these changes to GitHub. git commit -am "add a form" git push -u origin main 5. Once the production build finishes, visit your site and navigate to the page about Netlify Forms, `YOUR_URL/netlify-forms/`. 6. Fill in some details and select **Send**. You should find the following success message. ![submission received!](/images/get-started-form-success.png) This means our form entry submitted successfully, but where can we find it? 7. In the Netlify UI, select the **Forms** tab for your site. 8. Select the active **contact** form from the **Active forms** list, and you should find the submission listed. ![Verified submissions with user name and message.](/images/get-started-forms-submission.png) [#](#try-visual-editing) Try visual editing -------------------------------------------- To try out visual editing quickly, we recommend you create a new site using a site template that is already configured for visual editing. Starter site templates with visual editing include: * **[TypeScript + MUI Starter](https://github.com/netlify-templates/ts-mui-nextjs-starter) **: good for a tutorial-like experience and learning about visual editor capabilities, doesn’t require content source setup * **[ContentOps Starter](https://github.com/netlify-templates/content-ops-starter) **: Contains over 35 content types, good to try more complex scenarios, doesn’t require content source setup * **[Auto-annotated portfolio](https://github.com/netlify-templates/auto-annotated-portfolio) **: contains auto annotated components, good to learn about auto annotating your own site, doesn’t require content source setup * **[Next.js & Contentful Starter](https://github.com/netlify-templates/nextjs-contentful-starter) **: good for getting started with Contentful * **[Astro & Sanity Starter](https://github.com/netlify-templates/astro-sanity-starter) **: good for getting started with Sanity Learn more about creating a site with visual editing in our [setup pathways docs](/visual-editor/get-started/get-started-overview/#setup-pathways) or learn more about the [setup requirements](/visual-editor/get-started/get-started-overview/#visual-editor-support-requirements) . [#](#conclusion) Conclusion ---------------------------- In this tutorial, we’ve deployed an example site and introduced a few key features to get you started building sites, stores, and apps with Netlify. To explore more, consider setting up a [custom domain](/domains-https/custom-domains/) for your site, check out our get started docs for [Visual Editor](/visual-editor/get-started/get-started-overview/) and [Netlify Connect](/connect/get-started/) , work through our [production launch checklist](/platform/launch-checklist/) , or explore [our Support Forums](https://answers.netlify.com/) . Last updated: January 29, 2025 [Add new site](/welcome/add-new-site/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Large Media requirements and limitations | Netlify Docs This feature is deprecated Netlify’s Large Media service is [deprecated](/platform/release-phases/#deprecated) . While Large Media continues to function for sites that currently have it enabled, new Large Media configuration is not recommended. Refer to the [deprecation notice](https://answers.netlify.com/t/large-media-feature-deprecated-but-not-removed/100804) in our Support Forums for alternative services and more information. To avoid the risk of file loss, read our [Uninstalling Large Media](https://answers.netlify.com/t/support-guide-uninstalling-large-media/17662) Support Guide and [contact support](https://www.netlify.com/support/) for assistance turning off Large Media for an existing site. Netlify Large Media can be a powerful tool for your sites and apps, but because it’s built on Git LFS, it fundamentally changes how your Git repository works, and how your files are handled on Netlify. Make sure to review the following requirements and limitations before enabling Large Media on a site and repository. [#](#requirements) Requirements -------------------------------- To enable Large Media on a site repository, or to connect to an existing Large-Media-enabled site for local development, you need the following: * A Netlify site connected with a Git repository for [continuous deployment](/site-deploys/create-deploys/#deploy-with-git) . The site must have at least one successful deploy before using Large Media. If the repository already has Git LFS set up with another provider, visit our Forums for a verified Support Guide on [migrating your files from other LFS providers](https://answers.netlify.com/t/support-guide-are-there-extra-steps-required-when-moving-from-another-git-lfs-provider-to-netlify-large-media/852) . * A Netlify user login with access to the site configuration. (This is true for every Developer committing large media files to the site, unless they are using a CMS.) * Git LFS 2.5.1 or later, installed on your local machine. You can run `git lfs version` in your terminal to check if you have a valid version installed. If not, follow the installation instructions on the [Git LFS website](https://git-lfs.github.com/) . * Netlify CLI 3.8.0 or later. Refer to the [CLI docs](/cli/get-started) for information on installation, authentication, and linking your local repository clone to your Netlify site. [#](#limitations) Limitations ------------------------------ Different sites have different needs, and Netlify Large Media may not be the best solution for all situations. Make sure to review the following before enabling Large Media on a site and repository: * Files tracked with Netlify Large Media are tied to a specific site. This means that [Deploy to Netlify buttons](/site-deploys/create-deploys/#deploy-to-netlify-button) and repositories with multiple connected sites (such as monorepos) are not supported. Similarly, you cannot create a new site from a fork of a repository, though you can fork a Large-Media-enabled repository for the purpose of [making contributions](/git/large-media/repository-collaboration/#repository-forks) to be merged into the original repository. * Files tracked with Large Media are uploaded directly to the Netlify Large Media storage service on push, completely bypassing the site build. This saves build time, but also means that the files are not available to tools that process asset files during the build, such as Hugo’s image processing or the `gatsby-image` plugin. Depending on your needs, you may be able to replace this functionality with Netlify’s [image transformation service](/git/large-media/transform-images) . * Uploading tracked files to the Netlify Large Media storage service requires Git to have access to the `/.netlify/large-media` path on the connected site. This will not work with [Site Protection](/security/secure-access-to-sites/site-protection/) , but will work with other forms of [visitor access control](/security/secure-access-to-sites/role-based-access-control/) , as long as you leave access open to the `/.netlify/large-media` path. * Netlify Large Media is not suitable for _streaming_ audio or video files. However, storing these assets for download should work well. * Netlify Large Media is intended for files up to 100 MB in size. [#](#to-stop-service) To stop service -------------------------------------- Netlify Large Media’s connection with Git LFS requires extra care when disabling the service or deleting a site with the service enabled. ### [#](#disable-large-media) Disable Large Media Because Netlify Large Media and Git LFS change the way your files are saved, disabling Large Media requires assistance from Netlify Support. To request this assistance, please make a new topic in our [Support Forums](https://answers.netlify.com/c/netlify-support/48) . ### [#](#delete-a-site-with-large-media-enabled) Delete a site with Large Media enabled When you configure a repository to use Git LFS and Large Media, your designated LFS-tracked files will no longer be stored in your repository on your Git provider. Instead, they will be stored in the Large Media store for your connected Netlify site. This means that if you delete that site, you will not be able to recover the files at your Git provider. Don’t forget to make a copy! To avoid permanent file loss, always clone your entire repository locally before deleting a site with Large Media enabled. To clone your entire repository with all branches and history, run the following command: git clone --mirror YOUR_REPOSITORY_URL Make sure your files have downloaded properly before deleting the connected site on Netlify. Last updated: March 27, 2024 ← [Overview](/git/large-media/overview/) [Setup](/git/large-media/setup/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Large Media setup | Netlify Docs This feature is deprecated Netlify’s Large Media service is [deprecated](/platform/release-phases/#deprecated) . While Large Media continues to function for sites that currently have it enabled, new Large Media configuration is not recommended. Refer to the [deprecation notice](https://answers.netlify.com/t/large-media-feature-deprecated-but-not-removed/100804) in our Support Forums for alternative services and more information. To avoid the risk of file loss, read our [Uninstalling Large Media](https://answers.netlify.com/t/support-guide-uninstalling-large-media/17662) Support Guide and [contact support](https://www.netlify.com/support/) for assistance turning off Large Media for an existing site. To get started using Netlify Large Media on your site, you need to enable the Large Media add-on and configure Git LFS on a connected local repository. You can do this by completing the following steps: 1. Make sure you have reviewed the limitations and fulfilled all of the requirements stated in the [requirements and limitations](/git/large-media/requirements-and-limitations/) doc, then open your terminal into the local repository connected with your Netlify site. Avoid conflicts with GitLab If your repository is stored on GitLab, you will need to disable GitLab’s Large File Service (LFS) in the [project permissions settings](https://docs.gitlab.com/ee/user/project/settings/project_features_permissions.html#configure-project-features-and-permissions) . 2. If you haven’t already, [log in](/cli/get-started/#authentication) to Netlify CLI and [link](/cli/get-started/#link-and-unlink-sites) your local repository to your site on Netlify: netlify link 3. Run the following command for Large Media: netlify lm:setup This command will do the following: * Enable the Large Media add-on for your Netlify site. * Configure Git LFS to use the Netlify Large Media service. 4. Check your `git status`, and commit the `.lfsconfig` file. This file stores your Large Media settings. Your repository and site are now ready to start tracking files. Continue to the next section to configure file tracking. [#](#configure-file-tracking) Configure file tracking ------------------------------------------------------ After you enable Netlify Large Media on your site and local repository, you need to specify which files to track with Git LFS. When you push a tracked file to your remote repository, Git will store a text pointer file in its place, and upload the file itself to the Netlify Large Media storage service. You can change which files are tracked at any time. You can follow the steps below to set up a new configuration, or to make changes to an existing configuration. 1. **Specify which files you would like to track** with Large Media by using the `git lfs track` command. You can name individual files, one at a time, or in the same command, containing the files in quotation marks and separating them with a space: git lfs track "dog.jpg" "cat.gif" You can also track groups of files using [gitignore pattern rules](https://git-scm.com/docs/gitignore#_pattern_format) . For example, you could run the following to track all files in the `static/pdfs` directory: git lfs track "static/pdfs/**" You can also track all files with certain extensions, like so: git lfs track "*.jpg" "*.png" You can combine different types of patterns in a single command, or run the command multiple times. 2. **Commit your changes.** When you run the `git lfs track` command, Git saves your tracking configuration in a `.gitattributes` file. For example, running all three of the sample commands in step 1 would add the following lines to the `.gitattributes` file: dog.jpg filter=lfs diff=lfs merge=lfs -text cat.gif filter=lfs diff=lfs merge=lfs -text static/pdfs/** filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text The `git lfs track` command also applies Git LFS tracking to any files which match the rules specified. You can note newly tracked files listed as modified when you run `git status`. Commit all of these changes to Git. 3. **Push the changes to your remote.** For example, if you are working on your `production` branch and pushing to origin, run: git push origin production Newly tracked files you committed in the previous step will upload to the Netlify Large Media storage service. If you started tracking a large number of files, this initial push may take a long time as all of the files are uploaded. When the tracked files are uploaded to Large Media, Git replaces them with pointer files in your remote repository. If you navigate to one of the files on your Git provider, you will find plain text information about the original file. ![GitHub UI for a sample pointer file which includes LFS version, file SHA, and size.](/images/large-media-pointer-file.png) This pointer file is usually much smaller than the file it tracks, saving space in your repository and reducing cloning time. In your local repository and in your built site on Netlify, all tracked files can still be accessed as normal. 4. **Continue working in your repository as normal.** Any files you add or change which match your tracking rules will automatically be handled by Git LFS and Netlify Large Media on every pushed commit. ### [#](#check-file-tracking) Check file tracking Git LFS stores your tracking rules in a `.gitattributes` file in your repository. You can read the rules in this file directly, or list them with the following command: git lfs track To list all of the _files_ being tracked based on these rules, run: git lfs ls-files [#](#migrate-files-from-git-history) Migrate files from Git history -------------------------------------------------------------------- When you start tracking files for Netlify Large Media, all subsequent pushed commits of tracked files will be handled by Git LFS. However, this does not change the previous versions of the files, stored full-size in your repository as part of your Git history. Moving from another service? If you are moving from another Git LFS provider, visit our Forums for a verified Support Guide on [migrating your files from other LFS providers](https://answers.netlify.com/t/support-guide-are-there-extra-steps-required-when-moving-from-another-git-lfs-provider-to-netlify-large-media/852) . You can determine how much space these files are taking in your history with the following command: git lfs migrate info The command also accepts [options flags](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc#options) to filter your search by file type, location, or size. Be prepared to wait! If you have many large files in your Git history, it may take a very, very long time for all of them to migrate and upload to the Netlify Large Media storage service. To migrate asset files from your Git history to Large Media, complete the following steps. 1. In your local repository, use the `git lfs migrate import` command to convert files in your Git history. The command accepts several [options flags](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc#options) , including: `--everything` – migrates all matching files in all commits in all branches in your Git history. If you don’t want the migration to apply to your entire history, you can use a different flag as described in the [command documentation](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc#include-and-exclude-references) . `--include` – accepts rules for which files to migrate. These rules follow the same format as the `git lfs track` command used to set up your [initial file tracking configuration](/git/large-media/setup/#configure-file-tracking) . In this case, rules are separated by commas, and the entire list is wrapped in quotation marks. Here is an example to convert all files in the `images` directory, along with any other gif files, throughout the entire repository history: git lfs migrate import --everything --include="images/**,*.gif" You can find more examples in the [Git LFS `migrate` command documentation](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc) . 2. Push the newly migrated files to your remote repository. Unless you [specify otherwise](https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-migrate.adoc#import-without-rewriting-history) , the `git lfs migrate import` command will rewrite your commit history, converting all previous file version to Git LFS pointers. Pushing this rewritten history to the remote on your Git provider may require a force-push, as follows: git push --force-with-lease This will upload the previous file versions to Netlify Large Media, and replace the files in the remote repository with pointer files. [#](#troubleshooting) Troubleshooting -------------------------------------- If Large Media isn’t working as expected, you can visit our Forums for a verified Support Guide on [troubleshooting your Netlify Large Media configuration](https://answers.netlify.com/t/support-guide-troubleshooting-your-netlify-large-media-configuration/188) . Last updated: January 9, 2024 ← [Requirements & limitations](/git/large-media/requirements-and-limitations/) [Repository collaboration](/git/large-media/repository-collaboration/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send --- # Repository collaboration with Large Media | Netlify Docs This feature is deprecated Netlify’s Large Media service is [deprecated](/platform/release-phases/#deprecated) . While Large Media continues to function for sites that currently have it enabled, new Large Media configuration is not recommended. Refer to the [deprecation notice](https://answers.netlify.com/t/large-media-feature-deprecated-but-not-removed/100804) in our Support Forums for alternative services and more information. To avoid the risk of file loss, read our [Uninstalling Large Media](https://answers.netlify.com/t/support-guide-uninstalling-large-media/17662) Support Guide and [contact support](https://www.netlify.com/support/) for assistance turning off Large Media for an existing site. When a repository is configured to use Large Media and Git LFS, contributors cloning and working with the repository locally must also have these services installed, and must have access to the site on Netlify. To start working locally with a repository configured for Large Media, complete all of the stated [requirements](/git/large-media/requirements-and-limitations/) , then clone and push as normal. Tip No local setup is required for contributing to a repository using [Decap CMS](/git/large-media/repository-collaboration/#decap-cms) . [#](#repository-forks) Repository forks ---------------------------------------- You can fork a repository connected to a site enabled for Large Media, with the following limitations: * In order to access the Large Media files, you must fulfill all of the Large Media [requirements](/git/large-media/requirements-and-limitations/) , including access to the Netlify site connected to the _main_ (upstream) repository. * You cannot create a new Netlify site from the fork, because the Large Media files are accessible on the original site only. [#](#clone-without-large-media-files) Clone without Large Media files ---------------------------------------------------------------------- For contributions that don’t require access to a repository’s Large Media files, you can use `GIT_LFS_SKIP_SMUDGE=1` with your `clone` command to ignore LFS settings and download the text pointer files only: GIT_LFS_SKIP_SMUDGE=1 git clone YOUR_REPOSITORY_URL Windows users PowerShell and the Windows command line (cmd.exe) do not support the above syntax. For Windows users, we recommend running the command above using [Git Bash for Windows](https://git-scm.com/) . [#](#decap-cms) Decap CMS -------------------------- When you have Large Media enabled on your site, you can use [Decap CMS](https://decapcms.org/) with Netlify Identity to allow your site editors to work seamlessly with Large Media files in the Decap CMS UI — with no local setup required on their end. To get started, refer to the [Large Media setup instructions](/git/large-media/setup/) to enable Large Media on your site, then visit the [Decap CMS docs](https://decapcms.org/docs/netlify-large-media/) for more information on CMS setup and configuration options. Last updated: September 21, 2023 ← [Setup](/git/large-media/setup/) [Transform images](/git/large-media/transform-images/) → #### Did you find this doc useful? Your feedback helps us improve our docs. Do not fill in this field What else would you like to tell us about this doc? Send ---