<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Netlify</title>
    <description>The latest articles on Forem by Netlify (@netlify).</description>
    <link>https://forem.com/netlify</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F141%2F786e7a76-3019-4b70-9d33-663ffdbb1d8e.png</url>
      <title>Forem: Netlify</title>
      <link>https://forem.com/netlify</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/netlify"/>
    <language>en</language>
    <item>
      <title>How to keep your secrets secret on Netlify</title>
      <dc:creator>Sean Roberts</dc:creator>
      <pubDate>Mon, 09 Dec 2024 21:45:41 +0000</pubDate>
      <link>https://forem.com/netlify/how-to-keep-your-secrets-secret-on-netlify-4b4p</link>
      <guid>https://forem.com/netlify/how-to-keep-your-secrets-secret-on-netlify-4b4p</guid>
      <description>&lt;p&gt;Managing secrets is a critical part of building secure applications. But let’s face it—mistakes happen. Secrets can accidentally find their way into your codebase, your logs, or even your published files. That’s where Netlify’s Secrets Controller steps in, offering a quick way to protect sensitive data for everyone using Netlify.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Watch it in action&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Want to see how it works? Check out this quick demo:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZaBXMvPy4nQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Here’s how the Secrets Controller helps you sleep better at night:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Environment variables, done right&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Secrets are stored securely as environment variables, either synced from a vault or added directly in your site settings. They’re delivered in-memory and never exposed in your codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mark secrets for extra security&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Any environment variable can be flagged as a secret. Once flagged, these values are locked down—hidden from the UI, API, or CLI—ensuring they’re only accessible to your app during runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic secret leak detection&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Mistakes happen, but Netlify has your back. During every build, Secrets Controller scans your repo code and bundled files for any instance where a secret might have been exposed. If it finds one, the build is blocked, and you’re alerted to fix the issue before it goes live.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Even the most careful developers can accidentally expose secrets. Misconfigured build tools, copy-pasting errors, or overlooked logs can lead to serious data breaches. Netlify’s Secrets Controller not only prevents these mistakes but also simplifies your workflow, so you can focus on building, not worrying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let’s talk secrets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever experienced a close call with leaked secrets? How do you handle secrets in your workflows today? Share your thoughts in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Debugging failed builds with Netlify</title>
      <dc:creator>Taylor Barnett-Torabi</dc:creator>
      <pubDate>Thu, 05 Dec 2024 19:57:30 +0000</pubDate>
      <link>https://forem.com/netlify/debugging-failed-builds-with-netlify-554p</link>
      <guid>https://forem.com/netlify/debugging-failed-builds-with-netlify-554p</guid>
      <description>&lt;p&gt;We all get failed builds. Sometimes it works on your machine and then as soon as you push it to your hosting platform, something breaks in the build. Then, you have to sort through the build logs trying to spot what went wrong and figure it out. &lt;/p&gt;

&lt;p&gt;But what if you could get some help?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Meet Netlify’s AI-powered 'Why Did It Fail?' feature—designed to help you troubleshoot build errors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ixUTpQ-Nx4w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this video, we’ll walk you through how to use this powerful debugging tool to identify and fix the issues behind a failed deploy. With a single click, Netlify identifies the cause of deploy failures and provides actionable solutions, helping you fix errors in record time.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>astro</category>
      <category>ai</category>
    </item>
    <item>
      <title>Deploy your bolt.new app to Netlify</title>
      <dc:creator>Karin</dc:creator>
      <pubDate>Tue, 03 Dec 2024 08:54:33 +0000</pubDate>
      <link>https://forem.com/netlify/deploy-your-boltnew-app-to-netlify-1k54</link>
      <guid>https://forem.com/netlify/deploy-your-boltnew-app-to-netlify-1k54</guid>
      <description>&lt;p&gt;&lt;strong&gt;Have you tried Bolt.new? This AI-powered tool transforms your ideas into fully functional websites in minutes. Simply provide a short prompt, and Bolt takes care of the rest—generating the code for your site and making it effortless to create unique projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/L1Ic2oodk2w"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this video, we explore how to create and deploy a fully functional website in just a few steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate your site&lt;/strong&gt;: Provide a simple prompt—like creating a website celebrating cats! Bolt generates a beautiful application, complete with features like comments powered by Turo and Netlify Functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View your live site&lt;/strong&gt;: Bolt automatically deploys your site to Netlify, giving you a live URL to share instantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claim ownership&lt;/strong&gt;: Transfer the site to your Netlify team and make it yours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link to GitHub&lt;/strong&gt;: Open your project in StackBlitz, create a repository, and link it to your Netlify site for streamlined version control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With Bolt and Netlify, turning ideas into live, production-ready sites has never been faster. What kind of website would you create? Share your ideas (and URLs) in the comments—we’d love to see them!&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>automation</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Netlify Dynamic Site Challenge - Help Thread!</title>
      <dc:creator>Sean C Davis</dc:creator>
      <pubDate>Thu, 02 May 2024 21:01:44 +0000</pubDate>
      <link>https://forem.com/netlify/netlify-dynamic-site-challenge-help-thread-2081</link>
      <guid>https://forem.com/netlify/netlify-dynamic-site-challenge-help-thread-2081</guid>
      <description>&lt;p&gt;Looking for help with your &lt;a href="https://dev.to/challenges/netlify"&gt;Netlify DEV Challenge Submission&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;We're here to assist anyone who encounters issues or has questions about Netlify!&lt;/p&gt;

&lt;p&gt;Feel free to post your questions or concerns in the comments below, and we'll do our best to provide timely and helpful responses.&lt;/p&gt;

&lt;p&gt;Just hearing about this challenge? Read the announcement post here:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/devteam" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1%2Fd908a186-5651-4a5a-9f76-15200bc6801f.jpg" alt="The DEV Team"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3%2F13d3b32a-d381-4549-b95e-ec665768ce8f.png" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/devteam/join-us-for-the-netlify-dynamic-site-challenge-3000-in-prizes-3mfn" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Join us for the Netlify Dynamic Site Challenge: $3,000 in Prizes!&lt;/h2&gt;
      &lt;h3&gt;dev.to staff for The DEV Team ・ May 1&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#netlifychallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devchallenge&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>netlifychallenge</category>
      <category>netlify</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building AI experiences on Netlify</title>
      <dc:creator>Sean Roberts</dc:creator>
      <pubDate>Tue, 23 Apr 2024 15:24:34 +0000</pubDate>
      <link>https://forem.com/netlify/building-ai-experiences-on-netlify-5bj5</link>
      <guid>https://forem.com/netlify/building-ai-experiences-on-netlify-5bj5</guid>
      <description>&lt;p&gt;The rise and acceleration of AI experiences across the web is seeing an adoption curve unlike any technology we’ve seen in years. AI driven experiences have raised the bar in UX expectations and is offering new frontiers for serving customers. Traditional static design and rigid input experiences are going to become a sign of outdated experiences on the web. As we’re helping our millions of developers embrace these new capabilities, this guide will start your journey of building AI experiences on Netlify.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We’re going to discuss the high-level approaches to building AI experiences on Netlify. You’ll walk away knowing how to start your AI journey, what parts of AI workloads Netlify can support, and considerations to keeping things fast and secure. Along the way, we'll step through some examples that you can code along with to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  I got 99 problems and AI should solve some
&lt;/h2&gt;

&lt;p&gt;The first consideration in this space is to ensure you have a problem that’s right for AI to solve. Of course, those that are just exploring the tech and APIs this isn’t necessary. But if you’re building for your business/community, it’s important to start with the problem. AI is part of the solution (to a lot of problems) but it can be a challenge to start with the solution vs starting with the right problems. Starting with the right problem allows you to narrow in on which tools to use, provides clearer ways of evaluate the solutions, and reduces the risk of forcing a solution onto the wrong problem.&lt;/p&gt;

&lt;p&gt;Here are some usecases/problems our customers solve with AI on Netlify today.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-driven chat agents to help their customer workloads&lt;/li&gt;
&lt;li&gt;Generative UI to provide more personalized experiences&lt;/li&gt;
&lt;li&gt;AI Agents/Assistants trained to solve key tasks on behalf of users&lt;/li&gt;
&lt;li&gt;Publishing/hosting websites/artifacts generated by AI tools&lt;/li&gt;
&lt;li&gt;Semantic search of knowledgebases to make it easier to get insights and solve issues&lt;/li&gt;
&lt;li&gt;Storing and processing the data needed to create embeddings and push to vector databases&lt;/li&gt;
&lt;li&gt;Generating or modifying images, content, etc. to personalize their customer experiences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Did you know?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lJEzh7GA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/250/guides/2024-04-16-building-ai-experiences-on-netlify/cognition-logo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lJEzh7GA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/250/guides/2024-04-16-building-ai-experiences-on-netlify/cognition-logo.webp" alt="Cognition" width="250" height="91"&gt;&lt;/a&gt;&lt;br&gt;
Cognition Labs, creators of the AI Software Engineer, &lt;a href="https://www.cognition-labs.com/introducing-devin"&gt;Devin&lt;/a&gt;, faced challenges with needing to be able to run, host, and validate web experiences created by their AI engineer.&lt;/p&gt;

&lt;p&gt;The team chose Netlify to manage all of the web infrastructure that Devin produces during its development.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Composable AI stacks
&lt;/h2&gt;

&lt;p&gt;With a usecase and concept in mind, you’ll want to get to building on your stack as quickly as possible. Netlify’s composable platform let’s your team decide the right combination of tools to use to achieve your goals.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI / Framework stack
&lt;/h3&gt;

&lt;p&gt;You probably already have a framework of choice and a website you’re building on. If you don’t, here are some templates to get you started with a site on Netlify.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/netlify-templates/kpop-stack"&gt;Remix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/netlify-templates/next-platform-starter?tab=readme-ov-file#deploying-to-netlify"&gt;Next.js (with App Router)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;… check out our &lt;a href="https://docs.netlify.com/frameworks/"&gt;docs for your UI framework of choice&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For most usecases, AI solutions tend to be a server/backend concern. It’s often treated as an API layer separate from your frontend stack or integrated into it. That is to say, like your site’s other server concerns, your AI layer will usually look the same and sit next to the rest.&lt;/p&gt;

&lt;p&gt;For example, if you’re building Generative UI via React Server Components, you are already integrating your server logic next to your components. Most websites today utilize a more trigger oriented flow - user interacts with UI, an API call happens, and UI is updated to reflect the information. Both approaches are supported on Netlify so you can use the approach that fits with your current site.&lt;/p&gt;

&lt;h3&gt;
  
  
  Any Model. Any AI Pattern. Any AI Framework.
&lt;/h3&gt;

&lt;p&gt;Within your website architecture, you can decide which model and provider you would like to use. Netlify’s serverless runtime allows you to start working with AI without worrying about the infrastructure that powers it.&lt;/p&gt;

&lt;p&gt;Access any AI model from a provider of your choosing. Here’s some that you might be interested in for your usecases.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://openai.com/"&gt;OpenAI&lt;/a&gt; - powerful proprietary models&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://groq.com/"&gt;Groq&lt;/a&gt; - extremely fast LLM inference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/"&gt;HuggingFace&lt;/a&gt; - extensive library of open models&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/"&gt;Anthropic&lt;/a&gt; - exceptional proprietary models&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://octo.ai/"&gt;OctoAI&lt;/a&gt; - containerized access to models and inference stack&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/vertex-ai?hl=en"&gt;Google’s Vertex AI&lt;/a&gt; - powerful proprietary and open model access&lt;/li&gt;
&lt;li&gt;countless more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on your usecases, you’ll employ various AI patterns. Whether you’re just using basic direct inference, RAG (Retrieval Augmented Generation), or supporting something more complex such as knowledge graphs. These patterns combine compute, data, and inference to achieve results and Netlify is the glue and runtime to make this happen.&lt;/p&gt;

&lt;p&gt;As your usecases get more complex, it’s a good idea to start reaching for a purpose-built AI framework to simplify what you need to understand.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://js.langchain.com/docs/get_started/introduction"&gt;LangChain&lt;/a&gt; - A complete framework for orchestrating different patterns, normalizing provider differences, and making it easy to build and maintain AI systems without needing to know the nuances.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sdk.vercel.ai/docs"&gt;AI SDK&lt;/a&gt; - Normalizing the responses from AI tools, common utilities, and prebuilt usecase methods.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ts.llamaindex.ai/"&gt;LlammaIndex&lt;/a&gt; - A data framework for orchestrating the data workloads used in your AI systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re needing a vector database to do some advanced patterns, Netlify supports connecting to all of the major providers such as Pinecone, PlanetScale, Supabase, MongoDB, Neo4J, etc. Just select the tools that fits your needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w5J00JYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/guides/2024-04-16-building-ai-experiences-on-netlify/ai-service-layers.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w5J00JYw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/guides/2024-04-16-building-ai-experiences-on-netlify/ai-service-layers.png" alt="Tools in the AI ecosystem working with Netlify" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Anthropic for product descriptions
&lt;/h2&gt;

&lt;p&gt;Let’s apply some of this approach to see how simple it is to build AI experiences on Netlify. If we needed an API that generates descriptions of products, how would we build that? In this example, we will create an AI endpoint that runs on the edge and uses Anthropic’s Claude model to generate product descriptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Set up an &lt;a href="https://docs.anthropic.com/claude/docs/getting-access-to-claude#step-1-sign-up-for-a-console-account"&gt;Anthropic account&lt;/a&gt; and &lt;a href="https://docs.anthropic.com/claude/docs/getting-access-to-claude#step-3-generate-an-api-key"&gt;create an API key&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;In your site settings create an environment variable for &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;In your codebase, create a Netlify Edge Function, that will your endpoint. In our case the api path will be &lt;code&gt;/product-description&lt;/code&gt; and we can send a &lt;code&gt;productSummary&lt;/code&gt; query parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Anthropic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/@anthropic-ai/sdk@0.20.4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productSummary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;productSummary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;productSummary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Netlify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatCompletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;claude-3-opus-20240229&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You're an ecommerce store. I need you to make the best description possible with the information I provide.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productSummary&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chatCompletion&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/product-description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Your API is ready, now we need to call it. Here’s some basic HTML/JS to see this working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Info about the product"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"summary"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"generate-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate Product Description&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"desc-target"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;summary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;generate-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;desc-target&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;generateBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;generating description...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;descResp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/product-description?productSummary=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;desc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;descResp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;desc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! The more information/specs about the product that’s provided the better the results.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🛹 Prompt: “Eric Koston Girl Basic Logo Skatebord”&lt;/p&gt;

&lt;p&gt;Generated: “Ride in style with the Eric Koston Girl Basic Logo Skateboard. This high-quality skateboard features a sleek and minimalist design, perfect for showcasing your love for the iconic Girl Skateboards brand. The deck is made from durable 7-ply maple wood, providing a smooth and responsive ride for skaters of all skill levels.&lt;/p&gt;

&lt;p&gt;The top of the deck features Girl's classic logo in bold, black text against a clean white background. The understated design is a testament to Eric Koston's timeless style and the brand's commitment to simplicity and functionality.&lt;/p&gt;

&lt;p&gt;The skateboard measures 8.25 inches wide and 31.85 inches long, making it suitable for a wide range of skating styles and techniques. The medium concave shape offers excellent control and stability, while the slightly tapered tail and nose provide ample pop for ollies and other tricks.&lt;/p&gt;

&lt;p&gt;The Eric Koston Girl Basic Logo Skateboard comes fully assembled and ready to ride, with high-quality trucks, wheels, and bearings that ensure a smooth and responsive experience. Whether you're cruising the streets or hitting the skate park, this board is built to perform.&lt;/p&gt;

&lt;p&gt;As a signature model from one of the most influential skaters of all time, the Eric Koston Girl Basic Logo Skateboard is a must-have for any serious skateboarder or collector. Don't miss your chance to own a piece of skateboarding history and elevate your riding style with this iconic deck.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Using OpenAI with tool/function calling
&lt;/h2&gt;

&lt;p&gt;Let’s try something a little more advanced using a different tool. In this example, we want to provide an experience to help our customers who are traveling. One way to help is suggesting what clothes to pack for a given travel location and expected weather. Inference models do not have up-to-date information so they need a way to get this information to continue the request.&lt;/p&gt;

&lt;p&gt;To achieve this, we will create an endpoint that defines a “tool” that must be called to determine what to do next. With this feature, OpenAI’s model is informed that, when certain questions are asked, it should consult the list of tools for what to do next. In this case, it will call this function when it needs to dynamically look up the weather.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Set up an &lt;a href="https://platform.openai.com/signup"&gt;OpenAI account&lt;/a&gt; and &lt;a href="https://platform.openai.com/docs/quickstart/account-setup"&gt;create an API key&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;In your site settings create an environment variable for &lt;code&gt;OPENAI_API_KEY&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Create your function. Below we use OpenAI’s &lt;code&gt;runTools&lt;/code&gt; function that will process the prompt, select the right tool, and use the result to complete the prompting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://esm.sh/openai@4.33.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locationInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;locationInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Where are you traveling to?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Netlify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolRunner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;beta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;runTools&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You're a helpful travel agent informing the user what clothes they should pack. When deciding what clothes to offer, you will be informed of the travel destination. Ensure that the clothes are appropriate for the weather.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`I'm traveling to "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locationInput&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gpt-4-turbo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;suggestion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;toolRunner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;finalContent&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// called automatically when the model believes it needs to get the weather&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// call weather API&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;98F&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;precipitation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;humid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// it's hot everywhere :)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/packing-suggestions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Let’s start using the API from the website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Location of travel"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"location"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"generate-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Suggest clothes for travel&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"suggestion-target"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locationInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generateBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;generate-button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;suggestionTarget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;suggestion-target&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;generateBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;suggestionTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;generating packing suggestions...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/packing-suggestions?location=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locationInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;suggestion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;suggestionTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;suggestion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a simple endpoint for helping your users decide how to prepare for their trip.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;☀️ “For your trip to Atlanta, Georgia, where the current temperature is 98°F and it's quite humid, it would be best to pack lightweight and breathable clothing. Here are some suggestions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Light Cotton Shirts/Tops: Help you stay cool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shorts or Loose Pants: Opt for breathable materials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Wide-Brimmed Hat: To protect from the sun.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sunglasses and Sunscreen: Essential for sun protection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Comfortable Sandals or Breathable Shoes: Keep your feet cool.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Lightweight Jacket or Sweater: For cooler indoor environments due to air conditioning.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Make sure you stay hydrated and take breaks in the shade or indoors as it seems quite hot and humid out there!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Advanced workflows
&lt;/h3&gt;

&lt;p&gt;These examples are just the beginning of what can be achieved on Netlify. Customers are building out very complex background data processing workflows on Netlify with the ease thanks to the automatic scaling and managed infrastructure. Retrieval augmented generation (RAG) is as easy as selecting a retrieval data store (e.g. Pinecone), using async functions to populate the database, and make the retrieval and inference calls within your endpoints. Combine this with framework techniques like generative UI and you have some amazing opportunities!&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing AI endpoints
&lt;/h2&gt;

&lt;p&gt;As you build out your web experiences, you need to ensure bad actors are not able to abuse your endpoints causing outages or increased provider billing.&lt;/p&gt;

&lt;p&gt;Here are some basic initial steps to ensure you’re building in a secure manner&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Store API keys as environment variables.&lt;/strong&gt; Marking them as secrets will add more protections. Use the Netlify UI, API, or CLI to add these environment variables and avoid committing them to your source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create different API keys for your different deploy contexts.&lt;/strong&gt; Production should have a different API key than development or pre-production. This reduces the chance of those API keys be exposed through development environments on your local machines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat data sent to your endpoints and generated data as unsafe input.&lt;/strong&gt; Ensure the expected data is being provided to your endpoints and enforce nothing else is being sent. Generated content from model inference can be erroneous or produce unsafe content. If you’re using generated content elsewhere in your system (such as putting it in a DB, using it in queries, presenting it on the UI) you should treat this content similarly as user content and protect your system from dangerous values.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Controlling Access to your endpoints
&lt;/h3&gt;

&lt;p&gt;Netlify has DDoS protections in place for all customers that constantly protects against global attacks. All sites are different and you know your users and usecases better than Netlify, so you can leverage Netlify’s capabilities to add &lt;em&gt;more&lt;/em&gt; protections for who can access the site itself and to what degree they should be using it. Here are some ways of achieving that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ensure the expected clients are calling your endpoints.&lt;/strong&gt; This is the basics around ensuring the client is who you expect them to be. For example, ensuring that the &lt;code&gt;Origin&lt;/code&gt; header matches your site. If you only expect authenticated users, you should check the session information as well.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable access control protection for your site.&lt;/strong&gt; When you create PRs and code branches, you’re usually creating preview environments to verify changes. This creates a URL for your team to access and test changes. These are extremely useful but it’s not very often that these are required to be publicly accessible for anyone to use. If you want to &lt;a href="https://docs.netlify.com/security/secure-access-to-sites/site-protection/"&gt;lock down&lt;/a&gt; who has access to these environments, you can enable &lt;a href="https://docs.netlify.com/security/secure-access-to-sites/site-protection/#protect-your-sites-with-a-basic-password"&gt;password protections&lt;/a&gt;, &lt;a href="https://docs.netlify.com/security/secure-access-to-sites/traffic-rules/"&gt;IP requirements&lt;/a&gt;, or even &lt;a href="https://docs.netlify.com/security/secure-access-to-sites/site-protection/#protect-your-sites-with-netlify-team-login"&gt;require the end user to be someone on your Netlify team account&lt;/a&gt; to access the site.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add rate limits that match your expected traffic patterns.&lt;/strong&gt; Netlify has very powerful &lt;a href="https://docs.netlify.com/security/secure-access-to-sites/rate-limiting/"&gt;rate limiting capabilities&lt;/a&gt; that can target broad sets of users or very granular areas of your site. With these capabilities, you can assess your AI endpoints and enforce rules based on your expectations of usage. For example, our endpoint to generate suggestions for clothes to pack, we do not expect this to be called many times by the same user within a short period of time. I would create a rate limiting rule that enforces a limit that no one device should call that endpoint more than 5 times a minute. Whether it’s abuse or a bug on the site’s code, you’ll be protected from these endpoints being called too many times.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance optimization
&lt;/h2&gt;

&lt;p&gt;A key challenge in building with AI tools is performance. If you’re expecting a model inference call to be as fast as a traditional database read, you’ll have a harsh awakening. Over time, we expect that inference providers are going to get faster but until then here are some opportunities to consider when creating more performant AI experiences.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caching results.&lt;/strong&gt; The de facto initial perf consideration is deciding if a given response from your endpoint can be cached on the CDN or the browser for some period of time. Netlify has industry leading &lt;a href="https://docs.netlify.com/platform/caching"&gt;controls for explicit caching/purging rules&lt;/a&gt; for the CDN.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blob storage of results.&lt;/strong&gt; This is another form of caching but, unlike browser/CDN cache, this storage would be global. Let’s say you built an AI experience that processes many large documents to compute a summary. If your end users are teams that could ask to process the same large documents, you would want to reuse the results of the initial processing. This is where &lt;a href="https://docs.netlify.com/blobs/overview/"&gt;Netlify Blobs&lt;/a&gt; is very powerful. They can be easily used to store/fetch data saving time and money for intensive AI calculations. In addition to performance, this approach is also useful for consistency of results. AI tools tend to generate slightly or significantly different results each time they are called with the same information - that can cause confusion when your users expect the same information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick the right model, then pick the right provider.&lt;/strong&gt; As mentioned, Netlify’s platform allows teams to pick the right tool for the job. As you evaluate models, you might decide on a model that’s well supported across many platforms. If that’s the case, it’s a good opportunity to assess if you’ll have a faster experience with a different provider. For example, if you decide to use the open &lt;code&gt;Llama 2 7B&lt;/code&gt; model from Meta, then you’d find it’s supported across many providers. Choosing a provider like Groq might provide substantial performance benefits because they are focused on high performance inference that includes that model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The key takeaways for building AI on Netlify&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with a problem that AI should solve.&lt;/li&gt;
&lt;li&gt;Decide your composable AI stack. With Netlify, you can evolve this stack over time.&lt;/li&gt;
&lt;li&gt;Start building by leveraging Netlify’s infrastructure - you focus on the feature, we will handle the infra.&lt;/li&gt;
&lt;li&gt;As you advance in complexity, Netlify will be there to let you choose the right tools and support the intensive workloads and patterns you’re building.&lt;/li&gt;
&lt;li&gt;Secure your endpoints using protections in your code and granular access controls.&lt;/li&gt;
&lt;li&gt;Improve the performance and consistency of AI experiences leveraging the caching, data stores, and the right providers.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>netlify</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Avoiding lock-in for your image pipeline with Nuxt Image and Netlify Image CDN</title>
      <dc:creator>Phil Hawksworth</dc:creator>
      <pubDate>Fri, 19 Apr 2024 09:53:12 +0000</pubDate>
      <link>https://forem.com/netlify/avoiding-lock-in-for-your-image-pipeline-with-nuxt-image-and-netlify-image-cdn-3anc</link>
      <guid>https://forem.com/netlify/avoiding-lock-in-for-your-image-pipeline-with-nuxt-image-and-netlify-image-cdn-3anc</guid>
      <description>&lt;p&gt;Resizing and optimizing image assets in our web projects has become both an important part of the efforts to safeguard performance, and also a common developer experience or code efficiency wrinkle. Many frameworks seek to streamline this for users and developers alike, and often leverage image services such as Netlify Image CDN, Cloudinary, or Imgix. Nuxt Image does this in a way that does not lock you in to any one provider, and is incredibly simple to set up with Netlify.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Here, we'll look at the steps to adding Nuxt Image to a Nuxt project, and see how it is automatically powered by Netlify Image CDN when deployed to Netlify. We'll also see how this can be used and tested in a local development context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To code along as we go, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.netlify.com/cli/" rel="noopener noreferrer"&gt;Netlify CLI&lt;/a&gt; for local development with Netlify Image&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://app.netlify.com/singup" rel="noopener noreferrer"&gt;A Netlify account&lt;/a&gt; for deploying a version to test in production&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  JFDI (just deploy it)
&lt;/h2&gt;

&lt;p&gt;If you'd prefer to just clone and deploy an example to explore, click the button below and you'll very quickly have an example Nuxt site using Netlify Image to power Nuxt Image deployed and ready to tinker with.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.netlify.com/start/deploy?repository=https://github.com/netlify/example-nuxt-image" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.netlify.com%2Fimg%2Fdeploy%2Fbutton.svg%3Fv%3D2" alt="Deploy to Netlify"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Nuxt Image to a Nuxt project
&lt;/h2&gt;

&lt;p&gt;Nuxt Image is a module dedicated to providing image asset optimization, resizing, and associated markup generation for your Nuxt sites. If you have a project already, you can add it that, or if you'd prefer a totally clean start, use the &lt;a href="https://www.npmjs.com/package/nuxi" rel="noopener noreferrer"&gt;Nuxt CLI&lt;/a&gt; (nuxi) to quickly create a new starter Nuxt project to experiment with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nuxi@latest init my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the Nuxt Image module as a dependency to your project
&lt;/h3&gt;

&lt;p&gt;The Nuxt CLI can help us with this too, which for convenience, we can use via &lt;code&gt;npx&lt;/code&gt; like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nuxi@latest module add image
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tell your Nuxt project that you're using the module
&lt;/h3&gt;

&lt;p&gt;Adding the module to your Nuxt configuration file, &lt;code&gt;nuxt.config.js&lt;/code&gt;, will make &lt;code&gt;&amp;lt;NuxtImg&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;NuxtPicture&amp;gt;&lt;/code&gt; components available to use in your application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxt/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add an image to your application using &lt;code&gt;&amp;lt;NuxtImg&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Nuxt Image and Netlify Image CDN can serve images assets which are part of the site repo or sourced from an external resource. To start, let's add a local image and display it in a page template.&lt;/p&gt;

&lt;p&gt;Various &lt;a href="https://image.nuxt.com/providers/netlify#modifiers" rel="noopener noreferrer"&gt;attributes and modifiers&lt;/a&gt; can be set and passed along to the underlying image service provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;NuxtImg&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"owl.jpg"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt; &lt;span class="na"&gt;fit=&lt;/span&gt;&lt;span class="s"&gt;"cover"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing Nuxt Image in your local environment
&lt;/h2&gt;

&lt;p&gt;During development, you'll want to get a realistic picture (Yes, I saw this pun coming, and did nothing to avoid it. You're welcome) of how everything is working using the underlying image provider, in our case Netlify Image CDN. Luckily, we can gain access to this by simply running our local build with &lt;a href="https://docs.netlify.com/cli/local-development/#get-started-with-netlify-dev" rel="noopener noreferrer"&gt;Netlify Dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Netlify Dev is bundled into &lt;a href="https://dev.to/cli/"&gt;Netlify CLI&lt;/a&gt; and will &lt;a href="https://docs.netlify.com/cli/local-development/#project-detection" rel="noopener noreferrer"&gt;detect your local site&lt;/a&gt; characteristics and run your build for you when you run the command &lt;code&gt;netlify dev&lt;/code&gt; in your project directory (or &lt;code&gt;ntl dev&lt;/code&gt; if you want to &lt;a href="https://developers.netlify.com/guides/netlify-cli-alias-ntl" rel="noopener noreferrer"&gt;save a few keystrokes&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;By running your project with &lt;code&gt;netlify dev&lt;/code&gt; you'll gain local access to a number of the facilities of the Netlify platform such as redirects, serverless and edge functions, blob storage, and Image CDN (which is what we care about here)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;More specific local dev command control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If for some reason your project is not correctly detected and run by &lt;code&gt;netlify dev&lt;/code&gt;, or if you have some exotic local dev commands that you run, you can &lt;a href="https://docs.netlify.com/cli/local-development/#project-detection" rel="noopener noreferrer"&gt;configure this with a &lt;code&gt;netlify.toml&lt;/code&gt;file&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Explicitly specifying Netlify Image CDN as a provider
&lt;/h3&gt;

&lt;p&gt;Although Netlify will default to using Netlify CDN automatically, you can explicitly specify this by adding an &lt;code&gt;image&lt;/code&gt; object to your &lt;code&gt;nuxt.config.ts&lt;/code&gt; file and declaring your provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxt/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;netlify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Allowing external image sources
&lt;/h4&gt;

&lt;p&gt;To use images from external sources in Nuxt Image, with the same optimizations, CDN caching, and manipulation as with your local images, you need to declare the allowed domains by adding a &lt;code&gt;domains&lt;/code&gt; array to your &lt;code&gt;nuxt.config.ts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxt/image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;netlify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;domains&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;images.example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ummm... that's it
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;tl;dr&lt;/em&gt; could perhaps have been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add the dependency&lt;/li&gt;
&lt;li&gt;Add it to the config&lt;/li&gt;
&lt;li&gt;Use the component&lt;/li&gt;
&lt;li&gt;Ship it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to the thoughtful abstractions provided by Nuxt Image, this is all you need to do to use &lt;code&gt;&amp;lt;NuxtImg&amp;gt;&lt;/code&gt; with Netlify powering the image optimizations and manipulations. You might have noticed that we've not even added any mention of Netlify Image CDN to the codebase at this stage.&lt;/p&gt;

&lt;p&gt;Nuxt Image will automatically detect when it's being deployed to Netlify and use Netlify Image under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  The power of primitives
&lt;/h2&gt;

&lt;p&gt;One of the principles we value at Netlify is providing developers and framework authors access to powerful primitives to power their applications (or the frameworks that power the applications of others).&lt;/p&gt;

&lt;p&gt;Nuxt Image makes use of one such primitive perfectly here, offering convenience to Nuxt users without the need to learn about the underlying primitives (although &lt;a href="https://developers.netlify.com/guides/how-to-serve-optimized-images-using-netlify-image-cdn" rel="noopener noreferrer"&gt;you could use the Image CDN directly&lt;/a&gt; if you wished, or if your site didn't justify the use of a framework).&lt;/p&gt;

&lt;h2&gt;
  
  
  More information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://image.nuxt.com/" rel="noopener noreferrer"&gt;Nuxt Image module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://image.nuxt.com/providers/netlify" rel="noopener noreferrer"&gt;Netlify as a Nuxt Image provider&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/image-cdn/overview/#app" rel="noopener noreferrer"&gt;Netlify Image CDN docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/guides/how-to-serve-optimized-images-using-netlify-image-cdn"&gt;Using Netlify Image CDN directly&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Netlify integrations can now inject serverless functions to enhance any site. Here’s how</title>
      <dc:creator>Karin</dc:creator>
      <pubDate>Thu, 11 Apr 2024 12:01:24 +0000</pubDate>
      <link>https://forem.com/netlify/netlify-integrations-can-now-inject-serverless-functions-to-enhance-any-site-heres-how-2hnk</link>
      <guid>https://forem.com/netlify/netlify-integrations-can-now-inject-serverless-functions-to-enhance-any-site-heres-how-2hnk</guid>
      <description>&lt;p&gt;It’s long been possible to use Netlify Functions in your site. But with the Netlify SDK we’re bringing the power of function injection to integration builders as well. This allows you to build one integration that can power any of your Netlify sites using Netlify Functions with the click of a button! This guide will show you three different types of functions you can inject into a site.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;This guide explains the three different types of functions that you can inject into a site using a Netlify integration: &lt;a href="https://docs.netlify.com/functions/overview/"&gt;serverless functions&lt;/a&gt;, &lt;a href="https://docs.netlify.com/functions/scheduled-functions/"&gt;scheduled functions&lt;/a&gt; and &lt;a href="https://docs.netlify.com/functions/background-functions/"&gt;background functions&lt;/a&gt; (only available for sites that are on &lt;a href="https://www.netlify.com/pricing/?category=developer"&gt;Core Pro&lt;/a&gt; and &lt;a href="https://www.netlify.com/pricing/?category=enterprise"&gt;Core Enterprise&lt;/a&gt; plans). We'll make an integration by using the functions boilerplate from the Netlify CLI, and deploy it for use in an example site.&lt;/p&gt;

&lt;p&gt;You can explore the full source code with examples to see how to inject each of these three types of functions. Or you can add this integration to your Netlify account by clicking the button below.&lt;/p&gt;

&lt;p&gt;You can explore the &lt;a href="https://github.com/netlify/sdk-sf-injection-integration"&gt;full source code of this integration&lt;/a&gt; to see how we built this integration. Or add the integration to your Netlify account by clicking the button below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.netlify.com/integration/start/deploy?repository=https://github.com/netlify/sdk-sf-injection-integration&amp;amp;integrationName=sdk-sf-injection-integration&amp;amp;integrationSlug=sdk-sf-injection-integration&amp;amp;integrationDescription=Inject%20functions%20into%20your%20site%20with%20the%20netlify%20sdk&amp;amp;integrationLevel=site&amp;amp;scopes=site:read,site:write" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5a03ubW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.netlify.com/img/deploy/button.svg%3Fv%3D2" alt="Deploy to Netlify" width="179" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/"&gt;Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.netlify.com/signup"&gt;A Netlify account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s get started
&lt;/h2&gt;

&lt;p&gt;First, run &lt;code&gt;npm create @netlify/sdk@latest&lt;/code&gt; to create a new integration. Answer the prompts following the steps below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? Where do you want to create the integration? sdk-sf-injection-integration
? What is the slug of the integration? (e.g. my-integration) sdk-sf-injection-integration
? Summarize what your integration does. This will be shown on the integration's card on the Integrations page. It has some examples for
injecting functions
? Which boilerplate should be included? Functions Injection (beta)
? What level will this integration be installed on? site (recommended for Build Event Handlers, Edge Functions and Functions)
? Which package manager do you want to use? pnpm
? Do you want to create or link a Netlify site to your integration? This will help you test your integration and will be used to host
your integration. skip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create your integration in the folder with the name you provided! It will have a scaffold that the SDK created for you. There is a basic structure there that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── integration.yaml
├── netlify.toml
├── node_modules
├── package-lock.json
├── package.json
├── src
│ ├── index.ts
│ └── functions
│   └── hello-world.mts
└── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;integration.yaml&lt;/code&gt; - The integration configuration file. This is where you configure the integration name, description, and other metadata.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netlify.toml&lt;/code&gt; - The Netlify configuration file. This is where you configure the settings for your integration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/index.ts&lt;/code&gt; - The entry point for developing the integration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/functions/&lt;/code&gt; - The folder to store your functions in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/functions/hello-world.mts&lt;/code&gt; - An example function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deploy the integration
&lt;/h2&gt;

&lt;p&gt;You have a working integration now! Follow &lt;a href="https://developers.netlify.com/sdk/publish/private-integrations/"&gt;this guide&lt;/a&gt; to deploy your integration to your Netlify account so we can try it out on a Netlify site.&lt;/p&gt;

&lt;p&gt;After following that guide, let’s try it out on one of your Netlify sites! You can test it out by finding a site in your Netlify account (make a simple test site if necessary). When you’re in the dashboard of that site, select ‘integrations’ in the site’s sidebar. Then, find your integration in the list of private integrations. The last step is to click ‘enable’ on the integration card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs4o9pmme3phdxiuwkon.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs4o9pmme3phdxiuwkon.png" alt="Enable your integration by selecting 'enable' on the integration card in the Netlify UI" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test it out by redeploying your test site and visiting your site on the &lt;code&gt;/.netlify/functions/sf_prefix_hello-world&lt;/code&gt; path. It should say &lt;code&gt;Hello, world!&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check out the integration code
&lt;/h2&gt;

&lt;p&gt;Open up the &lt;code&gt;src/index.ts&lt;/code&gt; file in your editor to see how the integration is set up. In that file you’ll see the following:&lt;/p&gt;

&lt;p&gt;Test it out by redeploying your test site and visiting your site on the &lt;code&gt;/.netlify/functions/sf_prefix_hello-world&lt;/code&gt; path. It should say &lt;code&gt;Hello, world!&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check out the integration code
&lt;/h2&gt;

&lt;p&gt;Open up the &lt;code&gt;src/index.ts&lt;/code&gt; file in your editor to see how the integration is set up. In that file you’ll see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NetlifyIntegration&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;integration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NetlifyIntegration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;integration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my_unique_prefix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;integration&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;addFunctions&lt;/code&gt; method defines where the SDK can find your function. In this case it’s &lt;code&gt;./src/functions&lt;/code&gt;. It also provides a prefix for your functions. This is important because it helps avoid naming conflicts with functions that might be injected by other integrations or frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different function options
&lt;/h2&gt;

&lt;p&gt;Let’s dive into the different types of functions you can inject through the SDK: serverless functions, background functions and scheduled functions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless function
&lt;/h2&gt;

&lt;p&gt;The first type is the one that is already part of the scaffold that the SDK created for you, a default serverless function.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can you use a serverless function for?
&lt;/h3&gt;

&lt;p&gt;These types of functions can be used for a lot of different usecases, some examples are fetching live data from an API, returning dynamic images, sending automated emails or validating user input.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you create a serverless function?
&lt;/h3&gt;

&lt;p&gt;If we open the file &lt;code&gt;src/functions/hello-world.mts&lt;/code&gt; in the integration’s repository we’ll see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documentation: https://sdk.netlify.com&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’re looking at the most basic version of a function. As mentioned before, this function can be found on the &lt;code&gt;/.netlify/functions/my_unique_prefix_hello-world&lt;/code&gt; endpoint on sites where it is installed. You can change this path by adding a config to the file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Documentation: https://sdk.netlify.com&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, world!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do you use a serverless function?
&lt;/h3&gt;

&lt;p&gt;If you were to commit this change to your integration and push it with &lt;a href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git"&gt;continuous deployment&lt;/a&gt; set up, it will automatically deploy the changes to your integration. When you try it out on your test site by redeploying your site, this function should be accessible through the &lt;code&gt;/test&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background function
&lt;/h2&gt;

&lt;p&gt;Background functions can only be used on sites in teams that are on &lt;a href="https://www.netlify.com/pricing/?category=developer"&gt;Core Pro&lt;/a&gt; or &lt;a href="https://www.netlify.com/pricing/?category=enterprise"&gt;Core Enterprise&lt;/a&gt; plans, so keep this in mind if you’re planning on building that kind of integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  What can you use a background function for?
&lt;/h3&gt;

&lt;p&gt;A background function is useful if your integration needs to inject a function that has to run for longer than the 10 second maximum execution time permitted for regular serverless functions. A background function can run for up to 15 minutes and doesn’t need to complete before a visitor can take next steps on the site it is injected in. It can be used for tasks such as batch processing, scraping or for slower API workflow execution.&lt;/p&gt;

&lt;p&gt;As mentioned in the &lt;a href="https://docs.netlify.com/functions/background-functions/"&gt;background functions documentation&lt;/a&gt;, background functions are invoked asynchronously. They return an initial &lt;code&gt;202&lt;/code&gt; success response and will then run in the background until it completes.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you create a background function?
&lt;/h3&gt;

&lt;p&gt;Creating a background function works similar to normal functions, the only difference is that you append the name of the file with &lt;code&gt;-background&lt;/code&gt;. Let’s create one!&lt;/p&gt;

&lt;p&gt;First, let’s install a useful dependency with &lt;code&gt;npm install @netlify/functions&lt;/code&gt;. Then, in your &lt;code&gt;src/functions&lt;/code&gt; directory create a file called &lt;code&gt;count-background.mts&lt;/code&gt;, add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BackgroundHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HandlerEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HandlerContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BackgroundHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HandlerEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HandlerContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLocaleString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/count&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do you use a background function?
&lt;/h3&gt;

&lt;p&gt;This deploys to an endpoint at &lt;code&gt;/count&lt;/code&gt; relative to the base URL of the site your integration is used on. When this function is invoked, the function returns an initial &lt;code&gt;202&lt;/code&gt; success response. It will then &lt;a href="https://docs.netlify.com/functions/logs/#access-function-logs"&gt;log&lt;/a&gt; numbers 1 through 60. Try it out by committing it to your integration’s repository and pushing your changes. Your integration will redeploy, after this make sure to also redeploy your test site and call this new function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduled function
&lt;/h2&gt;

&lt;p&gt;Scheduled functions are an exciting feature that makes it possible to run functions on a regular and consistent schedule, kind of like a cron job!&lt;/p&gt;

&lt;h3&gt;
  
  
  What can you use a scheduled function for?
&lt;/h3&gt;

&lt;p&gt;Scheduled functions provide so many different possibilities! From invoke a set of APIs to collate data for a report at the end of every week to backing up data from one data store to another at the end of every night or building and/or deploying all your static content every hour instead of for every authored or merged pull request.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you create a scheduled function?
&lt;/h3&gt;

&lt;p&gt;Creating a scheduled function works similar to normal functions, the only difference is that you export a config object from the file that defines when the function should run with something called a “&lt;a href="https://man7.org/linux/man-pages/man5/crontab.5.html"&gt;cron expression&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;Create a new file in your &lt;code&gt;src/functions&lt;/code&gt; directory called &lt;code&gt;hourly-run.mts&lt;/code&gt; and add the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;next_run&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Received event! Next invocation at:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next_run&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;* * * * *&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do you use the scheduled function?
&lt;/h3&gt;

&lt;p&gt;Commit it to your integration’s repository and push your changes. Your integration will redeploy, after this make sure to also redeploy your test site and call this new function. By going to your &lt;a href="https://docs.netlify.com/functions/logs/#access-function-logs"&gt;function logs&lt;/a&gt; you should be able to see an hourly message.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;Go ahead and use all of these new possibilities to build something that your team can really use with a private integration! Create one integration and apply it to your different Netlify sites to automate your workflows. Happy coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  More information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.netlify.com/sdk/functions/overview/"&gt;Full documentation on injecting functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.netlify.com/sdk/get-started/introduction/"&gt;Netlify SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>automation</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Create an integration that injects edge functions into any site</title>
      <dc:creator>Karin</dc:creator>
      <pubDate>Wed, 03 Apr 2024 11:51:36 +0000</pubDate>
      <link>https://forem.com/netlify/create-an-integration-that-injects-edge-functions-into-any-site-2a0i</link>
      <guid>https://forem.com/netlify/create-an-integration-that-injects-edge-functions-into-any-site-2a0i</guid>
      <description>&lt;p&gt;Netlify's edge functions have been a useful tool for developers wanting to add logic like transforming responses, setting custom request headers, localizing content based on the user's location, and more. But we also wanted to make it easy for integration developers to inject edge functions into the user's site. This expands the possibilities for what you can do with Netlify integrations and allow the creation of integrations that can modify the user's site at the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;In this guide you're going to use the Netlify SDK to create an integration that can block content based on the location of your site visitor. You'll create an integration that injects an edge function into the user's site that checks the user's location and blocks the content if they are in a specific country. You’ll then be able to use this integration on any of your Netlify sites by enabling and configuring them.&lt;/p&gt;

&lt;p&gt;You can explore the &lt;a href="https://github.com/netlify/block-content-with-sdk-ef-integration"&gt;full source code of this integration&lt;/a&gt; to see how we built this integration. Or add the integration to your Netlify account by clicking the button below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.netlify.com/integration/start/deploy?repository=https://github.com/netlify/block-content-with-sdk-ef-integration&amp;amp;integrationName=block-content-with-efs-integration&amp;amp;integrationSlug=block-content-with-efs-integration&amp;amp;integrationDescription=Block%20content%20with%20edge%20functions&amp;amp;integrationLevel=site&amp;amp;scopes=site:read,site:write" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5a03ubW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.netlify.com/img/deploy/button.svg%3Fv%3D2" alt="Deploy to Netlify" width="179" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Need full control on who gets to access your sites?&lt;/p&gt;

&lt;p&gt;While this integration might provide some control already, if you’re looking for a full-fledged solution to control who can access your Netlify site, then take a look at Netlify Firewall Traffic Rules. This feature empowers Enterprise customers with &lt;a href="https://www.netlify.com/platform/core/high-performance-edge/"&gt;Netlify High-Performance Edge&lt;/a&gt; to proactively control who can access their Netlify web properties based on the geographic location and IP address of the requestor, in real-time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org"&gt;Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.netlify.com/signup"&gt;A Netlify account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let's get started
&lt;/h2&gt;

&lt;p&gt;First, run &lt;code&gt;npm create @netlify/sdk@latest&lt;/code&gt; to create a new integration. Answer the prompts following the steps below. If you're using Visual Studio Code, you can configure it to use Edge Functions. This will install the Deno extension and create a new settings file for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
? Where &lt;span class="k"&gt;do &lt;/span&gt;you want to create the integration? NAME-OF-YOUR-INTEGRATION
? What is the slug of the integration? &lt;span class="o"&gt;(&lt;/span&gt;e.g. my-integration&lt;span class="o"&gt;)&lt;/span&gt; SLUG-OF-YOUR-INTEGRATION
? Summarize what your integration does. This will be shown on the integration&lt;span class="s1"&gt;'s card on the Integrations page. DESCRIPTION-OF-YOUR-INTEGRATION
? Which boilerplate should be included? [more than one]
? Which boilerplate should be included? Integration UI, Edge Function Injection (beta)
? What level will this integration be installed on? site (recommended for Build Event Handlers and Edge Functions)
? Would you like to configure VS Code to use Edge Functions? yes
? Which package manager do you want to use? pnpm
? Do you want to create or link a Netlify site to your integration? This will help you test your integration and will be used to host your
integration. skip
? A new VS Code settings file will be created at /path/.vscode/settings.json yes
? The Deno VS Code extension is recommended. Would you like to install it now? yes
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create your integration in the folder with the name you provided. The Netlify SDK will scaffold the basic structure needed for your integration and output the required files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── integration.yaml
├── netlify.toml
├── node_modules
├── package-lock.json
├── package.json
├── src
│ ├── index.ts
│ └── edge-functions
│   └── hello-world.ts
└── tsconfig.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;integration.yaml&lt;/code&gt; - The integration configuration file. This is where you configure the integration name, description, and other metadata.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netlify.toml&lt;/code&gt; - The Netlify configuration file. This is where you configure the settings for your integration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/index.ts&lt;/code&gt; - The entry point for developing the integration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/edge-functions/&lt;/code&gt; - The folder to store your edge functions in.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/edge-functions/hello-world.ts&lt;/code&gt; - An example edge function.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deploy the integration
&lt;/h2&gt;

&lt;p&gt;You have a working integration now! Let's try it out by &lt;a href="https://developers.netlify.com/sdk/publish/private-integrations/"&gt;deploying your integration as a private integration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now that you've created your private integration, let’s try it out on one of your Netlify sites! You can test it out by finding a site in your Netlify account (make a simple test site if necessary). When you’re in the dashboard of that site, select ‘integrations’ in the site’s sidebar. Then, find your integration in the list of private integrations. The last step is to click 'enable' on the integration card.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0rp8vvo4xdggyyc8k9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0rp8vvo4xdggyyc8k9n.png" alt="Enable your integration by selecting 'enable' on the integration card in the Netlify UI" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can test it out by redeploying your site and then visiting your site on the &lt;code&gt;/test&lt;/code&gt; path. You should see the message "Hello, world!".&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing
&lt;/h2&gt;

&lt;p&gt;Now that you've seen your integration in action, let's look at the code and customize it so it can block content based on the location of your site visitor.&lt;/p&gt;

&lt;p&gt;First let's look at the &lt;code&gt;src/index.ts&lt;/code&gt; file. In there you can see that it creates a new &lt;code&gt;NetlifyIntegration&lt;/code&gt; instance and calls the &lt;code&gt;addEdgeFunctions&lt;/code&gt; method to define where the edge functions are located in the codebase. In this case it's &lt;code&gt;./src/edge-functions&lt;/code&gt;. It also provides a prefix for the edge functions. This is important because it helps avoid naming conflicts with edge functions that might be injected by other integrations or frameworks. Let's change that prefix from &lt;code&gt;ef_prefix&lt;/code&gt; to &lt;code&gt;block_content&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NetlifyIntegration&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;integration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NetlifyIntegration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;integration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEdgeFunctions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/edge-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block_content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;integration&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is step 1 in getting edge functions injected into the user's site. The next step is to define your edge function. In this case the boilerplate has already created an example edge function for you in the &lt;code&gt;src/edge-functions/hello-world.ts&lt;/code&gt; file. Let's change this edge function's filename to &lt;code&gt;block-content.ts&lt;/code&gt; and update the code to block content based on the user's location.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/edge-functions/block-content.ts&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get the BLOCKED_COUNTRY_CODE from the site's environment variables.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BLOCKED_COUNTRY_CODE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Netlify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BLOCKED_COUNTRY_CODE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Use context.geo to find the country code and name.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countryCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countryName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;;

  // Use the countryCode to check if we should block it.

  if (countryCode === BLOCKED_COUNTRY_CODE) {
    return new Response(
      `We&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;re&lt;/span&gt; &lt;span class="nx"&gt;sorry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="nx"&gt;can&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t access our content from ${countryName}!`,
      {
        headers: { &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; },
        status: 451,
      }
    );
  }

  // Get the response of the original content that this path pointed to.
  // Learn more: https://docs.netlify.com/edge-functions/api/#use-conditional-request
  const response = await context.next();

  // Return the original response
  return new Response(response);
};

// This defines the path that this edge function will run on
// In this case, it runs on every path of the site.
export const config = {
  path: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="cm"&gt;/*',
};
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we are using the &lt;code&gt;context.geo.country.code&lt;/code&gt; to get the country code of the user's location. We then compare this to the &lt;code&gt;BLOCKED_COUNTRY_CODE&lt;/code&gt; environment variable. If the user is in the blocked country, we return a 451 status code with a message that they can't access the content. Otherwise, we return a 200 status code with a message that they can access the content.&lt;/p&gt;

&lt;p&gt;Let's commit these changes to your integration and push it. If you've set up &lt;a href="https://docs.netlify.com/site-deploys/create-deploys/#deploy-with-git"&gt;continuous deployment&lt;/a&gt; for your integration, it will automatically deploy the changes to your integration if you push the commit to your main branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Now on your test site, add the &lt;code&gt;BLOCKED_COUNTRY_CODE&lt;/code&gt; environment variable with the country code you want to block. It might be interesting to try it with your own &lt;a href="https://countrycode.org/"&gt;country code&lt;/a&gt; to see if it works. After you've added the environment variable, redeploy your site and visit it. You should see the message that you can't access the content from your country.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add an integration UI
&lt;/h2&gt;

&lt;p&gt;Do you want to go one level further with developer user experience? Try building your own &lt;a href="https://developers.netlify.com/sdk/integration-ui/overview/"&gt;integration UI&lt;/a&gt; that allows the developer to set the &lt;code&gt;BLOCKED_COUNTRY_CODE&lt;/code&gt; environment variable. If you want to see an example of how this code could look, check out the &lt;a href="https://github.com/netlify/block-content-with-sdk-ef-integration"&gt;readme of the repository&lt;/a&gt; to see how we built it in this example integration!&lt;/p&gt;

&lt;h2&gt;
  
  
  Other things to try and more information
&lt;/h2&gt;

&lt;p&gt;If you want to know more about edge function injection through integrations, make sure to read &lt;a href="https://developers.netlify.com/sdk/edge-functions/overview/"&gt;the documentation&lt;/a&gt;! It walks you through the steps to create an integration that injects edge functions, but also explains more complex things like the &lt;a href="https://docs.netlify.com/edge-functions/declarations/#declaration-processing-order"&gt;order of execution for edge functions&lt;/a&gt; when injected into a user’s site through an integration, and how they interact with any user-defined edge functions.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developers.netlify.com/sdk/edge-functions/overview/"&gt;Full documentation on injecting edge functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.netlify.com/sdk/get-started/introduction/"&gt;Netlify SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>automation</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Trigger a site update from anything that speaks HTTP with build hooks</title>
      <dc:creator>Phil Hawksworth</dc:creator>
      <pubDate>Tue, 02 Apr 2024 09:40:00 +0000</pubDate>
      <link>https://forem.com/netlify/trigger-a-site-update-from-anything-that-speaks-http-with-build-hooks-5h5n</link>
      <guid>https://forem.com/netlify/trigger-a-site-update-from-anything-that-speaks-http-with-build-hooks-5h5n</guid>
      <description>&lt;p&gt;Many might remember (or still be subjected to) long, drawn-out deployment processes. Complex, monolithic products often needed a time-consuming deployment process, taking many days and many people. CI/CD tooling transformed this aspect of web development and also unlocked the potential for highly performant and robust static assets to power sites that frequently update to stay fresh. Triggering a site build and deployment at the right moment is key to this, and build hooks give us that ability.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We can manage and monitor the events that trigger updates to our sites with build hooks. In this guide, we'll see how simple it is to create build hooks from &lt;a href="https://app.netlify.com"&gt;the Netlify UI&lt;/a&gt; or using &lt;a href="https://developers.netlify.com/cli/"&gt;the CLI&lt;/a&gt;, and show how to conveniently test them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating build hooks in the Netlify UI
&lt;/h2&gt;

&lt;p&gt;By creating different build hooks, we can initiate new builds from all sorts of different events and see which event triggered our builds. To create a new build hook visit your &lt;strong&gt;Site configuration&lt;/strong&gt; in &lt;a href="https://app.netlify.com"&gt;the Netlify UI&lt;/a&gt; and go to &lt;strong&gt;Build &amp;amp; deploy&lt;/strong&gt; to find the &lt;strong&gt;Build hooks&lt;/strong&gt; panel.&lt;/p&gt;

&lt;p&gt;You can select the branch that you'd like to deploy and give your new build hook a meaningful name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h2Epr_vH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/blog-build-hook-settings.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2Epr_vH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/blog-build-hook-settings.webp" alt="Build hook settings" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's not possible to edit existing build hooks, but the list of your site's build hooks gives easy access to copy their URLs, and to copy a cURL command to test them out. You can also delete build hooks from here too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5zli2dJC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/blog-build-hook-list.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5zli2dJC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/full/blog-build-hook-list.webp" alt="A list of build hooks" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating build hooks with the Netlify CLI
&lt;/h2&gt;

&lt;p&gt;The Netlify CLI doesn't include commands to manage build hooks, but the Netlify API does. Since the CLI also gives access to any API command, you can use that facility to do this from your command line or programmatically should you wish.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  Bonus Netlify CLI tip
&lt;/h3&gt;

&lt;p&gt;In addition to the built-in utilities in the Netlify CLI, you can also access API commands like so:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;netlify api {API—METHOD}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Try running &lt;code&gt;netlify api --list&lt;/code&gt; to show the available API methods and get quick access to their documentation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use the following command to list any build hooks on your site. (You'll need your Site ID, which you can get from the Netlify UI or from the CLI by running &lt;code&gt;netlify status&lt;/code&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlify api listSiteBuildHooks &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{"site_id": "YOUR—SITE—ID"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a new build hook using the CLI, use the &lt;code&gt;createSiteBuildHook&lt;/code&gt; API method, passing it the required data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlify api createSiteBuildHook &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'
  {
    "site_id": "YOUR—SITE—ID",
    "body": {"title":"My build hook", "branch":"main"}
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command will return information about your new build hook including its URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My build hook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"branch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.netlify.com/build_hooks/66058fe91febf5273753e516"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"draft"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-03-28T15:42:33.674Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"66058fe91febf5273753e516"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"site_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"41d9d252-cc2d-4600-bf60-XXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"msg"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST https://api.netlify.com/build_hooks/66058fe91febf5273753e516 to trigger a build"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing a Build Hook
&lt;/h2&gt;

&lt;p&gt;Invoking a build hook is as simple as making an HTTP POST request to its URL. These URLs contain a unique, non-guessable path but no other form of authentication. It's recommended that you don't advertise your build hook URLs publicly, although it is trivial to delete a build hook and you can create as many as you need. (The ones in this post are all deleted, before you try to have some fun with me!)&lt;/p&gt;

&lt;p&gt;You can make an HTTP POST from your command line using cURL. There is no payload to pass, just an HTTP POST to the correct URL. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; https://api.netlify.com/build_hooks/&lt;span class="o"&gt;{&lt;/span&gt;YOUR-BUILD-HOOK-ID&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After making the request, you'll see a new build identified with the label you gave to your build hook in your site's deploys in the &lt;a href="https://app.netlify.com"&gt;Netlify UI&lt;/a&gt;. Or you could look for the newly requested build by inspecting your deploys with the &lt;a href="https://developers.netlify.com/guides/streamline-your-workflow-with-the-official-netlify-raycast-extension/"&gt;Netlify Raycast extension&lt;/a&gt; if you prefer not to leave your desktop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safeguards against build thrashing
&lt;/h2&gt;

&lt;p&gt;Triggering builds programmatically from a variety of different sources and events has the potential to swamp Netlify with requests to build and deploy your site, so we have some safeguards against that, and some recommendations to further protect your build minutes.&lt;/p&gt;

&lt;p&gt;The Netlify Build Bots (as they are affectionately known internally at Netlify) have the intelligence to protect our systems and avoid wasting your build minutes. While a build is in progress, any additional build requests are queued behind it until the active build completes, at which time all subsequent build requests are skipped except for the most recent one. This avoids wasted builds that would have been quickly superseded and also gets the most recent request processed in a more timely way.&lt;/p&gt;

&lt;p&gt;You can also avoid making excessive build requests by being thoughtful about what events you choose to trigger a build.&lt;/p&gt;

&lt;p&gt;For instance, most headless content management systems (CMS) can post to a webhook for different types of events in their systems. Choose wisely here. For convenience, many save your content automatically as you type. This has saved my bacon (that is to say, my content) many times over the years, but also resulted in a lot of build requests to my sites as each keystroke created another request to build. Using the configuration of your chosen CMS to request a build based on &lt;em&gt;publishing&lt;/em&gt; events rather than &lt;em&gt;save&lt;/em&gt; events can be a good choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uses for build hooks
&lt;/h2&gt;

&lt;p&gt;Combining build hooks, with access to data and content from a variety of tools and services, and the ability to trigger calls to your build hooks from different events makes for a huge array of possibilities.&lt;/p&gt;

&lt;p&gt;By making APIs the interfaces between services, and by making the incredibly ubiquitous HTTP the means to communicate between services and trigger actions, we can compose many tools and services together with excellent hygiene and defined roles and responsibilities.&lt;/p&gt;

&lt;p&gt;Unifying content sources, digital asset management systems, version control systems, and so much more, all becomes viable and manageable.&lt;/p&gt;

&lt;p&gt;In addition to the more conventional uses we might imagine, I've seen many creative uses of build hooks too, with people calling on them to trigger site builds from Alexa, Apple Shortcuts on an iWatch, hardware buttons, and even motion sensors!&lt;/p&gt;

&lt;p&gt;Whether we're having fun or solving big, serious infrastructure and tooling challenges, the days of high friction and painful deployment processes are well and truly over.&lt;/p&gt;

&lt;h2&gt;
  
  
  More information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/configure-builds/build-hooks/#app"&gt;Full documentation on build hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cli.netlify.com/"&gt;Netlify CLI command reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://open-api.netlify.com/"&gt;Netlify API documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>automation</category>
    </item>
    <item>
      <title>Using custom error handling if a serverless function has crashed</title>
      <dc:creator>Phil Hawksworth</dc:creator>
      <pubDate>Mon, 25 Mar 2024 10:36:00 +0000</pubDate>
      <link>https://forem.com/netlify/using-custom-error-handling-if-a-serverless-function-has-crashed-1929</link>
      <guid>https://forem.com/netlify/using-custom-error-handling-if-a-serverless-function-has-crashed-1929</guid>
      <description>&lt;p&gt;When code is executed at request-time rather than at build time, and if it influences what visitors to your site see, then it is vitally important that you can control what happens should that code encounter an error. Displaying a message like "a serverless function has crashed" or a cryptic HTTP error code makes for a rough user experience. That's why Netlify edge functions give you some helpful options to gracefully handle errors, and fully control the experience passed on to the users.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We'll look at how to configure the custom error handling available in Netlify edge functions, and try them out with some simplified examples which you can also clone and explore in your own local and deployed sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  The default error page
&lt;/h2&gt;

&lt;p&gt;If an error ever causes an edge function to crash, that error is written to the function logs and by default it will also be displayed as a response from the Edge Handler. This default function error page is helpful for the developer, but not so much for the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9afy8cvb2g3i8gwui54.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft9afy8cvb2g3i8gwui54.png" alt="The default edge function error page" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom error handling in edge functions
&lt;/h2&gt;

&lt;p&gt;You can configure this error handling behavior to customize the experience. You have three options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Show the default failure page&lt;/li&gt;
&lt;li&gt;Silently bypass the error&lt;/li&gt;
&lt;li&gt;Display your own custom error page&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Show the default failure page
&lt;/h3&gt;

&lt;p&gt;The custom error handling is configured directly in your edge function by adding an &lt;code&gt;onError&lt;/code&gt; property to the config. If you don't specify an &lt;code&gt;onError&lt;/code&gt; behavior, the default of &lt;code&gt;fail&lt;/code&gt; will be used, &lt;a href="https://example-edge-function-error-handling.netlify.app/unhandled-error"&gt;as you can see here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/edge-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Display the failure message&lt;/span&gt;
  &lt;span class="c1"&gt;// (This is the default behavior if not configured)&lt;/span&gt;
  &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fail&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Silently bypass the error
&lt;/h3&gt;

&lt;p&gt;By setting the &lt;code&gt;onError&lt;/code&gt; option to &lt;code&gt;bypass&lt;/code&gt;, an erroring edge function still throws an error which is entered into the error logs, but it does not halt the progress of the request chain. If an asset was to be returned from this request, that will still happen even though the function encountered an error.&lt;/p&gt;

&lt;p&gt;You can see that in this example, where an edge function is invoked on requests made to the &lt;a href="https://example-edge-function-error-handling.netlify.app/intended-page"&gt;intended page&lt;/a&gt;. Even though the function errors, you'll still reach the intended page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/edge-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Silently bypass the error&lt;/span&gt;
  &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bypass&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Display your own custom error page
&lt;/h3&gt;

&lt;p&gt;By setting the &lt;code&gt;onError&lt;/code&gt; option to hold any path on your site, starting with &lt;code&gt;/&lt;/code&gt;, the Edge function still throws an error which is entered into the error logs, but the user sees the result of am HTTP rewrite to the path of our choosing within the site. This allows us to let them down gently with whatever nicely designed experience we chose, while logging the error behind the scenes.&lt;/p&gt;

&lt;p&gt;You can see that in this example where an edge function is invoked on requests made to the &lt;a href="https://example-edge-function-error-handling.netlify.app/custom-error"&gt;this erroring route&lt;/a&gt; which results in you seeing the custom &lt;a href="https://github.com/philhawksworth/example-edge-function-error-handling/blob/main/www/error-page.html"&gt;error page&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@netlify/edge-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Redirect the user to any URL in your site&lt;/span&gt;
  &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/your-far-prettier-error-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try for yourself
&lt;/h2&gt;

&lt;p&gt;Visiting these example links only showed you the view intended for the user. To see the error logging behind the scenes, and to experiment more, you can clone and deploy your own version of these simple examples by clicking the button below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.netlify.com/start/deploy?repository=https://github.com/philhawksworth/example-edge-function-error-handling"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5a03ubW8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.netlify.com/img/deploy/button.svg%3Fv%3D2" alt="Deploy to Netlify" width="179" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;More examples of using and configuring edge functions in this &lt;a href="https://edge-functions-examples.netlify.app/"&gt;edge functions examples site&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/edge-functions/optional-configuration/"&gt;Configuring edge functions documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/philhawksworth/example-edge-function-error-handling"&gt;Example repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>serverless</category>
      <category>webdev</category>
      <category>edge</category>
    </item>
    <item>
      <title>Build faster with the official Netlify Raycast extension</title>
      <dc:creator>Phil Hawksworth</dc:creator>
      <pubDate>Fri, 15 Mar 2024 10:25:00 +0000</pubDate>
      <link>https://forem.com/netlify/build-faster-with-the-official-netlify-raycast-extension-45e5</link>
      <guid>https://forem.com/netlify/build-faster-with-the-official-netlify-raycast-extension-45e5</guid>
      <description>&lt;p&gt;Raycast is an outstanding productivity tool for Mac OS offering all sorts of utilities, helpers, and deep integrations. It also has a thriving extension ecosystem. &lt;a href="https://www.raycast.com/netlify/netlify"&gt;Netlify's official Raycast extension&lt;/a&gt; utilizes Netlify's own APIs and offers a number of helpful tools and conveniences for developers building for the web with Netlify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl457qu38ekgjz90bsy4l.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl457qu38ekgjz90bsy4l.jpeg" alt="Netlify Raycast commands" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;This post shows how to install the free Netlify Raycast extension, and explores some of the useful features it provides. Don't fancy reading? There is a quick video summary too.&lt;/p&gt;

&lt;h1&gt;
  
  
  Install the free extension
&lt;/h1&gt;

&lt;p&gt;Existing Raycast users can just click the button below, or you can head over to the &lt;a href="https://www.raycast.com/netlify/netlify"&gt;Raycast site&lt;/a&gt; for more information and the latest release details for the Netlify extension.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.toraycast://extensions/netlify/netlify?source=netlify-developers-site"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wIx8cI6w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.raycast.com/netlify/netlify/install_button%402x.png%3Fv%3D1.1" alt="Install the Netlify Raycast extension" width="512" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/EVLUsV2XaQg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Direct docs access
&lt;/h1&gt;

&lt;p&gt;Quick access to the Netlify docs with less context switching is really nice. You can search the docs from within the Raycast UI and also add shortcuts to pages and locations &lt;a href="https://docs.netlify.com/"&gt;in the docs&lt;/a&gt; that you might visit regularly. Assign a hotkey or custom trigger for this and the friction reduces even further.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoh1rwaf9c55m72ctfq9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgoh1rwaf9c55m72ctfq9.jpeg" alt="Netlify Raycast - search docs" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Explore sites and deploy resources
&lt;/h1&gt;

&lt;p&gt;Raycast lets you swiftly find and access management of your sites hosted on Netlify. It's a speedy way to browse, filter, and access your sites, so you can see what is happening in your Netlify projects without leaving your desktop, and then jump directly into the site, admin, or repo you're interested in. The convenience of accessing site details, scoping by team, and navigating to GitHub repositories is a real bonus. I use this a lot, especially as a stepping stone to exploring site deploys or site repos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl9mq86b3w9dpqn1alk1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhl9mq86b3w9dpqn1alk1.jpeg" alt="Netlify Raycast - search sites" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also monitor your deploys this way. Access to the active and previous deploys is made more convenient thanks to the ability to filter by deploy context (such as branch, preview, or production), and by team. I love being able to see the status of a recent build quickly, and then quickly access the underlying pull request or code change that triggered the build. This is all available via the &lt;a href="https://app.netlify.com/"&gt;Netlify admin&lt;/a&gt;, but having it accessible quickly from the Raycast UI brings it closer to where I am working and speeds me up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ashk51kw4ihxtbdegaw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ashk51kw4ihxtbdegaw.jpeg" alt="Netlify Raycast - deploys" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Find local Netlify projects
&lt;/h1&gt;

&lt;p&gt;You can also use this to locate your Netlify projects on your local machine. Raycast makes them available for you to filter by name to quickly find projects and get into your code fast. After finding your local project, you can jump into it, open the underlying version control repo, open the Netlify admin for this project and more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsvgwpaomshgu8y4qez6.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsvgwpaomshgu8y4qez6.jpeg" alt="Netlify Raycast - local projects" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Review team actions
&lt;/h1&gt;

&lt;p&gt;Working in a team? There's extra help for you here too. The extension gives quick access to the &lt;a href="https://docs.netlify.com/accounts-and-billing/team-management/team-audit-log/#app"&gt;team audit log&lt;/a&gt;. This functionality can be really useful for teams collaborating on projects and accounts, allowing you to filter and review actions taken on the account by colleagues and collaborators. With the ability to filter by team and access the details of audit logs, team actions across projects become more transparent. Very handy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhrop4qrulv0v4ojpuye.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvhrop4qrulv0v4ojpuye.jpeg" alt="Netlify Raycast - audit logs" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's more to explore in this extension, and you can also submit feature requests vis the Raycast code repo. Why not install it and give it a try?&lt;/p&gt;

&lt;h1&gt;
  
  
  Install the free extension
&lt;/h1&gt;

&lt;p&gt;You can visit &lt;a href="https://www.raycast.com/netlify/netlify"&gt;the Netlify Raycast extension page&lt;/a&gt; for more information about the extension and to install it from there, or if you're already a Raycast user, you can click the link below to install it directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.toraycast://extensions/netlify/netlify?source=netlify-developers-site"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wIx8cI6w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.raycast.com/netlify/netlify/install_button%402x.png%3Fv%3D1.1" alt="Install the Netlify Raycast extension" width="512" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>raycast</category>
    </item>
    <item>
      <title>How to serve optimized images using Netlify's Image CDN</title>
      <dc:creator>Phil Hawksworth</dc:creator>
      <pubDate>Mon, 04 Mar 2024 13:11:00 +0000</pubDate>
      <link>https://forem.com/netlify/how-to-serve-optimized-images-using-52hj</link>
      <guid>https://forem.com/netlify/how-to-serve-optimized-images-using-52hj</guid>
      <description>&lt;p&gt;Not only can Netlify's Image CDN optimize image assets to improve site performance, but it can also handle common asset manipulation tasks on the fly. This cuts your site build times and powers valuable techniques such as responsive images and lazy loading.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Use a URL like this to serve your image through Netlify's Image CDN:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/.netlify/images/?url=/images/your-image.jpeg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This post explains how you can quickly start using the Netlify Image CDN, and demonstrates some helpful techniques to make using this service fit conveniently into your development workflow. Learn how to use a single image to provide all of the required asset sizes for responsive images.&lt;/p&gt;

&lt;h2&gt;
  
  
  No setup required, just a URL
&lt;/h2&gt;

&lt;p&gt;To begin using Netlify's Image CDN, you don't need to install or enable anything in your Netlify Admin. You simply need to make requests for your assets via a special URL pattern that Netlify recognizes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# An image served from your site's files&lt;/span&gt;
/images/some-image.jpeg

&lt;span class="c"&gt;# The same image, but served from Netlify's optimized Image CDN&lt;/span&gt;
/.netlify/images/?url&lt;span class="o"&gt;=&lt;/span&gt;/images/some-image.jpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might recognize this special URL pattern from other tools you can use in your sites on Netlify, such as &lt;a href="https://www.netlify.com/platform/core/functions/"&gt;Netlify Functions&lt;/a&gt;. That &lt;code&gt;/.netlify/&lt;/code&gt; path is reserved on Netlify to access these sorts of helpers and utilities, so for those already using Netlify Functions this will already feel a little familiar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convenience and future-proofing
&lt;/h2&gt;

&lt;p&gt;When using a service like this, I like to make it as unobtrusive in my code as possible. That way, should I ever wish to swap it out for an alternative, I can do so without a major refactor. Since the API is the URL, a small amount of abstraction using &lt;a href="https://docs.netlify.com/routing/redirects/"&gt;Netlify Redirects&lt;/a&gt; can help us achieve that.&lt;/p&gt;

&lt;p&gt;Let's create a convenient URL pattern we can use to serve the full-sized original image, but serve it from the Netlify Image CDN rather from our own site assets. A few lines in our &lt;code&gt;netlify.toml&lt;/code&gt; file will do that for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[[redirects]]&lt;/span&gt;
  &lt;span class="c"&gt;# Requests to URLs matching this pattern...&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/images/full/:file"&lt;/span&gt;
  &lt;span class="c"&gt;# ...will resolve to this URL pattern&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"/.netlify/images/?url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;/images/:file&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="c"&gt;# ... and the status code of 200 will make this behave as a rewrite&lt;/span&gt;
  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other excellent Image CDN and optimization services out there like Cloudinary or Imgix also let you control their APIs through URLs. This means that should you need to upgrade to another service, perhaps to gain access to their more detailed asset manipulation features, you can do so by modifying the URL redirect rules here in your &lt;code&gt;netlify.toml&lt;/code&gt; (after creating accounts with them, for example), and leave all of the image URLs across your site untouched.&lt;/p&gt;

&lt;p&gt;With our redirect rule in place, a small change to the path used to source our images will let us choose to serve that image from the Image CDN.&lt;/p&gt;

&lt;p&gt;From this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- an image served from my assets folder --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/seedlings.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A photo of some green seedlings"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- an image served from my Netlify's Image CDN, originally sourced from my assets folder --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/full/seedlings.jpg"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"A photo of some green seedlings"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tip: Assets can be on your sites or third party domains
&lt;/h3&gt;

&lt;p&gt;Netlify's Image CDN needs to source and ingest your image asset before it can optimize, cache, and serve it, which is done by specifying the URL where this can be found. This might be within your site or an external domain. For security reasons, requests for assets on external domains require a little config, which we'll get to later.&lt;/p&gt;

&lt;h2&gt;
  
  
  On-demand image resizing and manipulation
&lt;/h2&gt;

&lt;p&gt;The Netlify Image CDN can also perform a number of image manipulation tasks for us. It's very common to need differently sized versions of images for optimal display, as seen in our responsive image example above. Doing this for every single image in your site as part of each build can be computationally expensive and make builds take a long time. Handing this off to Netlify to do on-demand the first time an asset is requested in a given size and then caching that result can simplify and speed up our build process.&lt;/p&gt;

&lt;p&gt;Including a &lt;code&gt;width&lt;/code&gt; or &lt;code&gt;height&lt;/code&gt; parameter in the URL will return a suitably resized image. Using just one or the other will retain the aspect ratio for us. Like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=100&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mml9xYuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D100" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mml9xYuc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D100" alt="/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=100" width="100" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=200&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LFBds4I3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D200" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LFBds4I3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D200" alt="/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=200" width="200" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=400&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iiR-npyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D400" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iiR-npyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/.netlify/images/%3Furl%3D/images/blue-flowers.jpg%26width%3D400" alt="/.netlify/images/?url=/images/blue-flowers.jpg&amp;amp;width=400" width="400" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Image credit: &lt;a href="https://unsplash.com/photos/blue-flowers-plant-zt6970TlRyA?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;TOMOKO UJ, Unsplash&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Tip
&lt;/h3&gt;

&lt;p&gt;For information about all of the parameters we support for things like resizing, cropping, transforming image formats,&lt;br&gt;
  and more, take a look at the Transform Images section of &lt;a href="https://docs.netlify.com/image-cdn/overview/#transform-images"&gt;the Image CDN&lt;br&gt;
  documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Utility URLs for resizing
&lt;/h2&gt;

&lt;p&gt;Now let's make these URLs more convenient and better abstracted on our site. Similar to the redirect rule we created for our full-sized images (&lt;code&gt;/images/full/file-name.jpg&lt;/code&gt;), we could create some mappings for common sizes we might want so that the keywords &lt;code&gt;small&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, and &lt;code&gt;large&lt;/code&gt; each map to a URL with given width parameters. We could also make a rule which lets us pass a width parameter dynamically, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[[redirects]]&lt;/span&gt;
  &lt;span class="c"&gt;# Get a width and file name value from the URL&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/images/:width/:file"&lt;/span&gt;
  &lt;span class="c"&gt;# ...and pass them along as the correct request parameters&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"/.netlify/images/?url=/images/:file&amp;amp;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;:width&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Order matters
&lt;/h3&gt;

&lt;p&gt;Watch out for an easy mistake here. Netlify treats the order that rules appear in the &lt;code&gt;netlify.toml&lt;/code&gt; file as the order of priority, meaning that the first matching rule found is the one that will be applied. This is handy for creating logic in your rules.&lt;/p&gt;

&lt;p&gt;To make our example work as we would like, we need to add the rule that catches the variable input for width &lt;em&gt;after&lt;/em&gt; the rule that catches the word "full" in the same part of the URL as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;
&lt;span class="nn"&gt;[[redirects]]&lt;/span&gt;
  &lt;span class="c"&gt;# Serve a full size version&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/images/full/:file"&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"/.netlify/images/?url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;/images/:file&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;

&lt;span class="nn"&gt;[[redirects]]&lt;/span&gt;
  &lt;span class="c"&gt;# ...or serve a resized version&lt;/span&gt;
  &lt;span class="py"&gt;from&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/images/:width/:file"&lt;/span&gt;
  &lt;span class="py"&gt;to&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;"/.netlify/images/?url=/images/:file&amp;amp;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;:width&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  &lt;span class="py"&gt;status&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nice. Now we have some intuitive URLs we can use to serve our images in any size.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/images/100/blue-flowers.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U1XZZac7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/100/blue-flowers.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U1XZZac7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/100/blue-flowers.jpg" alt="/images/100/blue-flowers.jpg" width="100" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/images/200/blue-flowers.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jW6SCpRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/200/blue-flowers.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jW6SCpRG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/200/blue-flowers.jpg" alt="/images/200/blue-flowers.jpg" width="200" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/images/400/blue-flowers.jpg&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CMqIrKAn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/400/blue-flowers.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CMqIrKAn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://developers.netlify.com/images/400/blue-flowers.jpg" alt="/images/400/blue-flowers.jpg" width="400" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(or &lt;a href="https://developers.netlify.com/images/full/blue-flowers.jpg"&gt;&lt;code&gt;/images/full/blue-flowers.jpg&lt;/code&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Different asset sizes for responsive images
&lt;/h2&gt;

&lt;p&gt;We've got everything we need to deliver the different asset sizes for use in our &lt;code&gt;srcset&lt;/code&gt; in responsive images. A full explanation of how the responsive images work is available at &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images"&gt;MDN&lt;/a&gt;, but here's a look the HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
    /images/200/blue-flowers.jpg   200w,
    /images/400/blue-flowers.jpg   400w,
    /images/800/blue-flowers.jpg   800w,
    /images/1200/blue-flowers.jpg 1200w
  "&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 450px) 200px,
         (max-width: 850px) 400px,
         (max-width: 100px) 800px,
         1200px"&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/1200/blue-flowers.jpg"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Some blue flowers"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lovely! We're using readable, intuitive image URLs serving assets that are resized, optimized, and cached for us on demand. And should we decide to make changes to the size variant in our set of images we only need to edit a URL.&lt;/p&gt;

&lt;p&gt;Depending on what tools you are using to build your sites, this can also be a useful place for another bit of abstraction. A partial or a component that generates this markup for you when you pass it a &lt;em&gt;file name&lt;/em&gt; and an &lt;em&gt;alt&lt;/em&gt; tag (don't forget those &lt;code&gt;alt&lt;/code&gt; tags, friends!) can keep your code nice and clear, and formalize some common conventions across your sites for how you deliver responsive images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using images from remote domains
&lt;/h2&gt;

&lt;p&gt;The example here uses image assets which are part of the same site, so that relative paths are passed to Netlify's Image CDN.&lt;/p&gt;

&lt;p&gt;You can also feed the Image CDN assets from external domains. In order to prevent your site from becoming a gateway for anyone to perform unlimited image transformations on any assets, we give you control over which domains can be used. To do this, it's time to add another bit of config to your &lt;code&gt;netlify.toml&lt;/code&gt; file, where you can add an array of granted domains and use Reg Ex to describe detailed paths etc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[images]&lt;/span&gt;
  &lt;span class="py"&gt;remote_images&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"https://my-images.com/.*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"https://animals.more-images.com/[bcr]at/.*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assets on relative paths, sourced from your site gain all the benefits of our atomic deploys and their default cache behaviors, so assets on the Image CDN don't become outdated as you deploy updates to your site. Assets on remote domains have different default cache characteristics. For information on how to control this, and other information about using remote domains with the Image CDN, take a look at &lt;a href="https://docs.netlify.com/image-cdn/overview/#remote-path"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus! Instant format optimization
&lt;/h3&gt;

&lt;p&gt;You can specify the format you'd like to use to deliver your assets by providing a format (&lt;a href="https://docs.netlify.com/image-cdn/overview/#format"&gt;&lt;code&gt;fm&lt;/code&gt;&lt;/a&gt;) parameter in the URL.&lt;/p&gt;

&lt;p&gt;However, if you &lt;em&gt;don't&lt;/em&gt; specify a format, the Netlify Image CDN will determine the most efficient format for the browser requesting the image, and automatically return that using the following logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use avif if accepted&lt;/li&gt;
&lt;li&gt;Otherwise, use webp if accepted&lt;/li&gt;
&lt;li&gt;If neither is accepted, use the original format&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Global infra in your local development
&lt;/h2&gt;

&lt;p&gt;To get access to these capabilities while running your code in a local development environment, run your build using &lt;code&gt;netlify dev&lt;/code&gt; which enables various Netlify Build and platform services locally, to smooth your development workflow.&lt;/p&gt;

&lt;p&gt;Running your local build this way will provide handlers to those special &lt;code&gt;/.netlify/&lt;/code&gt; URLs, including automatically replicating the image transformation behaviour so that you can review appropriately as you build.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;netlify dev&lt;/code&gt; command is made available by installing the &lt;a href="https://developers.netlify.com/cli/"&gt;Netlify CLI&lt;/a&gt; and will serve your sites locally in a way that provides access to Netlify Functions, Edge Functions, Redirects, Image CDN and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Install Netlify CLI&lt;/span&gt;
npm i &lt;span class="nt"&gt;-g&lt;/span&gt; netlify-cli

&lt;span class="c"&gt;# Run your build with additional Netlify utilities&lt;/span&gt;
netlify dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it on one of your sites today!&lt;/p&gt;

&lt;h2&gt;
  
  
  More resources for handling images
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/image-cdn/overview/"&gt;Netlify Image CDN documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://image-cdn-playground.netlify.app/"&gt;Netlify Image CDN playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.netlify.com/integrations/cloudinary/"&gt;Cloudinary + Netlify integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://unpic.pics/"&gt;Unpic&lt;/a&gt; an open source library of helpers for images and image CDN abstraction&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hosting</category>
      <category>performance</category>
      <category>tricks</category>
    </item>
  </channel>
</rss>
