+ Edge Functions Examples / ${title}
+
+ `;
+}
diff --git a/examples/edge-functions/components/layout.js b/examples/edge-functions/components/layout.js
new file mode 100644
index 0000000..28f5433
--- /dev/null
+++ b/examples/edge-functions/components/layout.js
@@ -0,0 +1,58 @@
+import head from "./head.js";
+import header from "./header.js";
+import footer from "./footer.js";
+import deployButton from "./deploy-button.js";
+
+const explainer = `
+
+
What are Edge Functions?
+
Using JavaScript and TypeScript, Netlify Edge Functions give you the power to modify network requests to localize content, serve relevant ads, authenticate visitors, A/B test content, and much more! And this all happens at the Edge — directly from the worldwide location closest to each user.
+
To use Edge Functions on Netlify, add JavaScript or TypeScript files to an edge-functions directory in your project, and add [[edge_functions]] entries to your netlify.toml file.
Try out Edge Functions on Netlify today! Click the button below to deploy this site with all of its demos to your Netlify account.
+ ${deployButton()}
+
+
+
+ ${footer()}
+
+
+`;
+}
diff --git a/examples/edge-functions/components/repo-link.js b/examples/edge-functions/components/repo-link.js
new file mode 100644
index 0000000..e75729b
--- /dev/null
+++ b/examples/edge-functions/components/repo-link.js
@@ -0,0 +1,7 @@
+export default function repoLink(file, customText) {
+ const text = customText || "The Edge Function code:";
+
+ const root = "https://github.com/netlify/edge-functions-examples/tree/main/netlify/edge-functions";
+
+ return `${text} ${file}`;
+}
diff --git a/examples/edge-functions/netlify.toml b/examples/edge-functions/netlify.toml
new file mode 100644
index 0000000..1430193
--- /dev/null
+++ b/examples/edge-functions/netlify.toml
@@ -0,0 +1,92 @@
+[dev]
+ framework = "#static"
+
+[build]
+ command = "echo No build for this site, we are living on the edge"
+ publish = "public"
+
+# The URL for each edge function
+[[edge_functions]]
+ function = "transform"
+ path = "/*"
+
+[[edge_functions]]
+ function = "set-response-header"
+ path = "/*"
+
+[[edge_functions]]
+ function = "set-request-header"
+ path = "/*"
+
+[[edge_functions]]
+ function = "include"
+ path = "/*"
+
+[[edge_functions]]
+ path = "/hello"
+ function = "hello"
+
+[[edge_functions]]
+ path = "/geolocation"
+ function = "geolocation"
+
+[[edge_functions]]
+ path = "/json"
+ function = "json"
+
+[[edge_functions]]
+ path = "/cookies"
+ function = "cookies"
+
+[[edge_functions]]
+ path = "/rewrite"
+ function = "rewrite"
+
+[[edge_functions]]
+ path = "/abtest"
+ function = "abtest"
+
+[[edge_functions]]
+ path = "/image-internal"
+ function = "image-internal"
+
+[[edge_functions]]
+ path = "/image-external"
+ function = "image-external"
+
+[[edge_functions]]
+ path = "/log"
+ function = "log"
+
+[[edge_functions]]
+ path = "/country-block"
+ function = "country-block"
+
+[[edge_functions]]
+ path = "/localized-content"
+ function = "localized-content"
+
+[[edge_functions]]
+ path = "/fetch-joke"
+ function = "proxy-requests"
+
+# Serve pages explaining each example
+[[edge_functions]]
+ path = "/example/*"
+ function = "[page]"
+
+# Serve our index page
+[[edge_functions]]
+ path = "/"
+ function = "[page]"
+
+[[redirects]]
+ from = "/img/og/:text"
+ to = "https://res.cloudinary.com/netlify/image/upload/c_fit,g_west,h_400,co_rgb:FFFFFFFF,l_text:netlify.com:Pacaembu-Bold.ttf_57::text,w_1053,x_46/v1619123320/netlify.com/default-og-background-learn-more.png"
+ status = 200
+
+
+
+
+
+
diff --git a/examples/edge-functions/netlify/edge-functions/[page].js b/examples/edge-functions/netlify/edge-functions/[page].js
new file mode 100644
index 0000000..1a89c05
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/[page].js
@@ -0,0 +1,67 @@
+// A global page template for all of our HTML views
+// You know, for consistency.
+import layout from "../../components/layout.js";
+
+// A bit convoluted, but necessary for the moment
+// until we can import the page templates we need
+// dynamically from withing the exported function
+import pageHome from "../../pages/home/index.js";
+import pageHello from "../../pages/hello/index.js";
+import pageTransform from "../../pages/transform/index.js";
+import pageInclude from "../../pages/include/index.js";
+import pageRewrite from "../../pages/rewrite/index.js";
+import pageGeolocation from "../../pages/geolocation/index.js";
+import pageJson from "../../pages/json/index.js";
+import pageSetRequestHeader from "../../pages/set-request-header/index.js";
+import pageSetResponseHeader from "../../pages/set-response-header/index.js";
+import pageCookiesSet from "../../pages/cookies-set/index.js";
+import pageCookiesRead from "../../pages/cookies-read/index.js";
+import pageCookiesDelete from "../../pages/cookies-delete/index.js";
+import pageABTest from "../../pages/abtest/index.js";
+import pageImage from "../../pages/image/index.js";
+import pageLog from "../../pages/log/index.js";
+import pageCountryBlock from "../../pages/country-block/index.js";
+import pageLocalizedContent from "../../pages/localized-content/index.js";
+import pageProxyRequests from "../../pages/proxy-requests/index.js";
+
+// The keys here correspond to the path in the request to `/example/PATH`
+const pages = {
+ home: pageHome,
+ hello: pageHello,
+ transform: pageTransform,
+ include: pageInclude,
+ json: pageJson,
+ "set-response-header": pageSetResponseHeader,
+ "set-request-header": pageSetRequestHeader,
+ "cookies-set": pageCookiesSet,
+ "cookies-read": pageCookiesRead,
+ "cookies-delete": pageCookiesDelete,
+ rewrite: pageRewrite,
+ geolocation: pageGeolocation,
+ abtest: pageABTest,
+ image: pageImage,
+ log: pageLog,
+ "country-block": pageCountryBlock,
+ "localized-content": pageLocalizedContent,
+ "proxy-requests": pageProxyRequests,
+};
+
+export default async(Request, Context) => {
+ const url = new URL(Request.url);
+ const path = url.pathname.split("/example/")[1] || "home";
+
+ Context.log(`serve page for ${url} `);
+
+ // render the appropriate page with the global layout
+ const html = layout({
+ url: url,
+ title: pages[path].title,
+ content: pages[path].page({ geo: Context.geo }),
+ metaDescription: pages[path].metaDescription,
+ });
+
+ // send our response
+ return new Response(html, {
+ headers: { "content-type": "text/html" },
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/abtest.ts b/examples/edge-functions/netlify/edge-functions/abtest.ts
new file mode 100644
index 0000000..1f42b12
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/abtest.ts
@@ -0,0 +1,31 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // look for existing "test_bucket" cookie
+ const bucketName = "test_bucket";
+ const bucket = context.cookies.get(bucketName);
+
+ // return here if we find a cookie
+ if (bucket) {
+ return new Response(`Welcome back! You were assigned ${bucketName} **${bucket}** when you last visited the site!`);
+ }
+
+ // if no "test_bucket" cookie is found, assign the user to a bucket
+ // in this example we're using two buckets (a, b) with an equal weighting of 50/50
+ const weighting = 0.5;
+
+ // get a random number between (0-1)
+ // this is a basic example and you may want to experiment
+ const random = Math.random();
+ const newBucketValue = random <= weighting ? "a" : "b";
+
+ // set the new "test_bucket" cookie
+ context.cookies.set({
+ name: bucketName,
+ value: newBucketValue,
+ });
+
+ return new Response(
+ `Congratulations! You have been assigned ${bucketName} **${newBucketValue}**. View your browser cookies to check it out!`,
+ );
+};
diff --git a/examples/edge-functions/netlify/edge-functions/cookies.ts b/examples/edge-functions/netlify/edge-functions/cookies.ts
new file mode 100644
index 0000000..2e6bd30
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/cookies.ts
@@ -0,0 +1,29 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const url = new URL(request.url);
+
+ switch (url.searchParams.get("action")) {
+ case "set":
+ context.cookies.set({
+ name: "action",
+ value: "hello",
+ });
+
+ return new Response('Cookie value has been set. Reload this page without the "action" parameter to see it.');
+
+ case "clear":
+ context.cookies.delete("action");
+
+ return new Response(
+ 'Cookie value has been cleared. Reload this page without the "action" parameter to see the new state.',
+ );
+ }
+
+ const value = context.cookies.get("action");
+ const message = value
+ ? `Cookie value is "${value}". You can clear it by using "?action=clear".`
+ : 'Cookie has not been set. You can do so by adding "?action=set" to the URL.';
+
+ return new Response(message);
+};
diff --git a/examples/edge-functions/netlify/edge-functions/country-block.ts b/examples/edge-functions/netlify/edge-functions/country-block.ts
new file mode 100644
index 0000000..a150de8
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/country-block.ts
@@ -0,0 +1,34 @@
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Here's what's available on context.geo
+
+ // context: {
+ // geo: {
+ // city?: string;
+ // country?: {
+ // code?: string;
+ // name?: string;
+ // },
+ // subdivision?: {
+ // code?: string;
+ // name?: string;
+ // },
+ // }
+ // }
+
+ const BLOCKED_COUNTRY_CODE = "GB";
+ const countryCode = context.geo?.country?.code || "US";
+ const countryName = context.geo?.country?.name || "United States of America";
+
+ if (countryCode === BLOCKED_COUNTRY_CODE) {
+ return new Response(`We're sorry, you can't access our content from ${countryName}!`, {
+ headers: { "content-type": "text/html" },
+ status: 451,
+ });
+ }
+
+ return new Response(`Hello there! You can freely access our content from ${countryName}!`, {
+ headers: { "content-type": "text/html" },
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/geolocation.ts b/examples/edge-functions/netlify/edge-functions/geolocation.ts
new file mode 100644
index 0000000..0bdbffb
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/geolocation.ts
@@ -0,0 +1,24 @@
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Here's what's available on context.geo
+
+ // context: {
+ // geo: {
+ // city?: string;
+ // country?: {
+ // code?: string;
+ // name?: string;
+ // },
+ // subdivision?: {
+ // code?: string;
+ // name?: string;
+ // },
+ // }
+ // }
+
+ return context.json({
+ geo: context.geo,
+ header: request.headers.get("x-nf-geo"),
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/hello.js b/examples/edge-functions/netlify/edge-functions/hello.js
new file mode 100644
index 0000000..b1577fe
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/hello.js
@@ -0,0 +1,5 @@
+export default async (Request) => {
+ return new Response("Hello, World!", {
+ headers: { "content-type": "text/html" },
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/image-external.ts b/examples/edge-functions/netlify/edge-functions/image-external.ts
new file mode 100644
index 0000000..67a528a
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/image-external.ts
@@ -0,0 +1,11 @@
+import type { Context } from "netlify:edge";
+
+// Let's serve an image of a kitten from the internet
+
+export default async (request: Request, context: Context) => {
+ // fetch() is supported natively by Deno!
+ // Returning the awaited response automatically sets the
+ // content-type headers!
+ const kitten = await fetch("https://github.com/service/https://placekitten.com/g/300/300");
+ return kitten;
+};
diff --git a/examples/edge-functions/netlify/edge-functions/image-internal.ts b/examples/edge-functions/netlify/edge-functions/image-internal.ts
new file mode 100644
index 0000000..a1486f0
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/image-internal.ts
@@ -0,0 +1,8 @@
+import type { Context } from "netlify:edge";
+
+// Let's serve an image that's stored in the repo
+// by rewriting the URL.
+
+export default async (request: Request, context: Context) => {
+ return context.rewrite("/apple-touch-icon.png");
+};
diff --git a/examples/edge-functions/netlify/edge-functions/include.ts b/examples/edge-functions/netlify/edge-functions/include.ts
new file mode 100644
index 0000000..95a4eb7
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/include.ts
@@ -0,0 +1,25 @@
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+
+ // Just return what was requested without transforming it,
+ // unless we fnd the query parameter for this demo
+ const url = new URL(request.url);
+ if (url.searchParams.get("include") !== "pricing") {
+ return;
+ }
+
+ console.log("Including pricing content into the page");
+
+ // Get the page content
+ const response = await context.next();
+ const page = await response.text();
+
+ // Search for the placeholder
+ const regex = /{{INCLUDE_PRICE_INFO}}/i;
+
+ // Replace the content
+ const pricingContent = "It's expensive, but buy it anyway.";
+ const updatedPage = page.replace(regex, pricingContent);
+ return new Response(updatedPage, response);
+};
diff --git a/examples/edge-functions/netlify/edge-functions/json.ts b/examples/edge-functions/netlify/edge-functions/json.ts
new file mode 100644
index 0000000..725c4f1
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/json.ts
@@ -0,0 +1,5 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ return context.json({ hello: "world" });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/localized-content.js b/examples/edge-functions/netlify/edge-functions/localized-content.js
new file mode 100644
index 0000000..9e9a868
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/localized-content.js
@@ -0,0 +1,15 @@
+export default async (request, context) => {
+ const translations = {
+ UNKNOWN: "Hello!",
+ US: "Howdy y'all!",
+ GB: "How do you do?",
+ AU: "G'day, mate!",
+ };
+
+ const countryCode = context.geo?.country?.code || "UNKNOWN";
+ const countryName = context.geo?.country?.name || "somewhere in the world";
+
+ return new Response(`Your personalized greeting for ${countryName} is: ${translations[countryCode]}`, {
+ headers: { "content-type": "text/html" },
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/log.ts b/examples/edge-functions/netlify/edge-functions/log.ts
new file mode 100644
index 0000000..dd89c79
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/log.ts
@@ -0,0 +1,9 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ context.log("Hello from the logging service");
+
+ return new Response("The request to this URL was logged", {
+ headers: { "content-type": "text/html" },
+ });
+};
diff --git a/examples/edge-functions/netlify/edge-functions/proxy-requests.ts b/examples/edge-functions/netlify/edge-functions/proxy-requests.ts
new file mode 100644
index 0000000..37c4994
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/proxy-requests.ts
@@ -0,0 +1,12 @@
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+
+ const joke = await fetch("https://github.com/service/https://icanhazdadjoke.com/", {
+ "headers": {
+ "Accept": "application/json"
+ }
+ });
+ const jsonData = await joke.json();
+ return context.json(jsonData);
+};
diff --git a/examples/edge-functions/netlify/edge-functions/rewrite.ts b/examples/edge-functions/netlify/edge-functions/rewrite.ts
new file mode 100644
index 0000000..712861b
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/rewrite.ts
@@ -0,0 +1,5 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ return context.rewrite("/something-to-serve-with-a-rewrite");
+};
diff --git a/examples/edge-functions/netlify/edge-functions/set-request-header.ts b/examples/edge-functions/netlify/edge-functions/set-request-header.ts
new file mode 100644
index 0000000..4a9db23
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/set-request-header.ts
@@ -0,0 +1,5 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ request.headers.set("X-Your-Custom-Header", "Your custom header value");
+};
diff --git a/examples/edge-functions/netlify/edge-functions/set-response-header.ts b/examples/edge-functions/netlify/edge-functions/set-response-header.ts
new file mode 100644
index 0000000..b0e99ae
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/set-response-header.ts
@@ -0,0 +1,15 @@
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const url = new URL(request.url);
+
+ if (url.searchParams.get("method") !== "set-response-header") {
+ return context.next();
+ }
+
+ context.log(`Adding a custom header to the response for ${url}`);
+
+ const response = await context.next();
+ response.headers.set("X-Your-Custom-Header", "Your custom header value");
+ return response;
+};
diff --git a/examples/edge-functions/netlify/edge-functions/transform.ts b/examples/edge-functions/netlify/edge-functions/transform.ts
new file mode 100644
index 0000000..811c45e
--- /dev/null
+++ b/examples/edge-functions/netlify/edge-functions/transform.ts
@@ -0,0 +1,17 @@
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const url = new URL(request.url);
+
+ // Look for the query parameter, and return if we don't find it
+ if (url.searchParams.get("method") !== "transform") {
+ return;
+ }
+
+ context.log(`Transforming the response from this ${url}`);
+
+ const response = await context.next();
+
+ const text = await response.text();
+ return new Response(text.toUpperCase(), response);
+};
diff --git a/examples/edge-functions/package-lock.json b/examples/edge-functions/package-lock.json
new file mode 100644
index 0000000..e2eebb3
--- /dev/null
+++ b/examples/edge-functions/package-lock.json
@@ -0,0 +1,13 @@
+{
+ "name": "edge-functions-examples",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "edge-functions-examples",
+ "version": "1.0.0",
+ "license": "ISC"
+ }
+ }
+}
diff --git a/examples/edge-functions/package.json b/examples/edge-functions/package.json
new file mode 100644
index 0000000..63097b3
--- /dev/null
+++ b/examples/edge-functions/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "edge-functions-examples",
+ "description": "Explore a library of reference examples for learning about Edge Functions on Netlify.",
+ "version": "1.0.0",
+ "scripts": {},
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/netlify/edge-functions-examples.git"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/netlify/edge-functions-examples/issues"
+ },
+ "homepage": "https://github.com/netlify/edge-functions-examples#readme",
+ "dependencies": {}
+}
diff --git a/examples/edge-functions/pages/abtest/README.md b/examples/edge-functions/pages/abtest/README.md
new file mode 100644
index 0000000..355a3ca
--- /dev/null
+++ b/examples/edge-functions/pages/abtest/README.md
@@ -0,0 +1,27 @@
+
+
+# A/B Test with Netlify Edge Functions
+
+A/B tests are a great way to test new features on your site. A basic A/B test works by assigning visitors to a
+particular test "bucket" the first time they visit a site, usually using a random number between 0 and 1.
+
+Visitors can then be redirected to different pages, depending on the bucket and cookie they were assigned.
+
+You could even use A/B testing in combination with Geolocation at The Edge!
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/abtest.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/abtest
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/abtest/index.js b/examples/edge-functions/pages/abtest/index.js
new file mode 100644
index 0000000..d6ad2d7
--- /dev/null
+++ b/examples/edge-functions/pages/abtest/index.js
@@ -0,0 +1,60 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Set up an AB Test",
+ metaDescription: "Use cookies to power an A/B test at The Edge.",
+ page: function() {
+ return `
+
+
Set up an A/B Test at The Edge
+
A/B tests are a great way to test new features on your site. A basic A/B test works by assigning visitors to a particular test "bucket" the first time they visit a site, usually using a random number between 0 and 1.
+
Visitors can then be redirected to different pages, depending on the bucket and cookie they were assigned.
+
You could even use A/B testing in combination with Geolocation at The Edge!
+
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // look for existing "test_bucket" cookie
+ const bucketName = "test_bucket";
+ const bucket = context.cookies.get(bucketName);
+
+ // return here if we find a cookie
+ if (bucket) {
+ return new Response(`${bucketName} ${bucket} already assigned!`);
+ }
+
+ // if no "test_bucket" cookie is found, assign the user to a bucket
+ // in this example we're using two buckets (a, b) with an equal weighting of 50/50
+ const weighting = 0.5;
+
+ // get a random number between (0-1)
+ // this is a basic example and you may want to experiment
+ const random = Math.random();
+ const newBucketValue = random <= weighting ? "a" : "b";
+
+ // set the new "test_bucket" cookie
+ context.cookies.set({
+ name: bucketName,
+ value: newBucketValue,
+ });
+
+ return new Response(
+ `You have been assigned ${bucketName} ${newBucketValue}.`,
+ );
+};
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/cookies-delete/README.md b/examples/edge-functions/pages/cookies-delete/README.md
new file mode 100644
index 0000000..dc9c799
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-delete/README.md
@@ -0,0 +1,40 @@
+
+
+# Read, write, and delete cookies with Netlify Edge Functions
+
+Manipulate HTTP cookies
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Set a cookie
+ context.cookies.set({
+ name: "My cookie",
+ value: "hello",
+ });
+
+ // Delete a cookie
+ context.cookies.delete("My cookie");
+
+ // Read the value of a cookie
+ const value = context.cookies.get("My cookie");
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/cookies.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/cookies
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/cookies-delete/index.js b/examples/edge-functions/pages/cookies-delete/index.js
new file mode 100644
index 0000000..4758c50
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-delete/index.js
@@ -0,0 +1,31 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Deleting cookies",
+ metaDescription: "Delete an HTTP cookie",
+ page: function () {
+ return `
+
+
Delete HTTP cookies
+
Use an Edge Function to delete cookies.
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Delete a cookie
+ context.cookies.delete("My cookie");
+};
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/cookies-read/README.md b/examples/edge-functions/pages/cookies-read/README.md
new file mode 100644
index 0000000..dc9c799
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-read/README.md
@@ -0,0 +1,40 @@
+
+
+# Read, write, and delete cookies with Netlify Edge Functions
+
+Manipulate HTTP cookies
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Set a cookie
+ context.cookies.set({
+ name: "My cookie",
+ value: "hello",
+ });
+
+ // Delete a cookie
+ context.cookies.delete("My cookie");
+
+ // Read the value of a cookie
+ const value = context.cookies.get("My cookie");
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/cookies.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/cookies
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/cookies-read/index.js b/examples/edge-functions/pages/cookies-read/index.js
new file mode 100644
index 0000000..18b51b7
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-read/index.js
@@ -0,0 +1,30 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Reading cookies",
+ metaDescription: "Read HTTP cookie values",
+ page: function () {
+ return `
+
+
Reading cookies
+
Use an Edge Function to read and manage HTTP cookies.
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Read the value of a cookie
+ const value = context.cookies.get("My cookie");
+};
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/cookies-set/README.md b/examples/edge-functions/pages/cookies-set/README.md
new file mode 100644
index 0000000..dc9c799
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-set/README.md
@@ -0,0 +1,40 @@
+
+
+# Read, write, and delete cookies with Netlify Edge Functions
+
+Manipulate HTTP cookies
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Set a cookie
+ context.cookies.set({
+ name: "My cookie",
+ value: "hello",
+ });
+
+ // Delete a cookie
+ context.cookies.delete("My cookie");
+
+ // Read the value of a cookie
+ const value = context.cookies.get("My cookie");
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/cookies.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/cookies
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/cookies-set/index.js b/examples/edge-functions/pages/cookies-set/index.js
new file mode 100644
index 0000000..c220758
--- /dev/null
+++ b/examples/edge-functions/pages/cookies-set/index.js
@@ -0,0 +1,34 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Setting cookies",
+ metaDescription: "Set HTTP cookie values",
+ page: function () {
+ return `
+
+
Setting cookies
+
Use an Edge Function to create and manage HTTP cookies.
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Set a cookie
+ context.cookies.set({
+ name: "My cookie",
+ value: "hello",
+ });
+};
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/country-block/README.md b/examples/edge-functions/pages/country-block/README.md
new file mode 100644
index 0000000..d03b8a1
--- /dev/null
+++ b/examples/edge-functions/pages/country-block/README.md
@@ -0,0 +1,40 @@
+
+
+# {Name of example} with Netlify Edge Functions
+
+You can use geolocation data to identify a user's country and block content if required.
+
+Geolocation information is available on the `Context.geo` object.
+
+```javascript
+context: {
+ geo: {
+ city?: string;
+ country?: {
+ code?: string;
+ name?: string;
+ },
+ subdivision?: {
+ code?: string;
+ name?: string;
+ },
+ }
+}
+```
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/country-block.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/country-block
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/country-block/index.js b/examples/edge-functions/pages/country-block/index.js
new file mode 100644
index 0000000..906b353
--- /dev/null
+++ b/examples/edge-functions/pages/country-block/index.js
@@ -0,0 +1,40 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Block content according to country",
+ metaDescription: "Use geolocation data to block content according to country.",
+ page: function () {
+ return `
+
+
Block content according to country
+
You can use geolocation data to identify a user's country and block content if required.
+
Geolocation information is available on the Context.geo object.
+
+
import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const BLOCKED_COUNTRY_CODE = "GB";
+ const countryCode = context.geo?.country?.code || "US";
+ const countryName = context.geo?.country?.name || "United States of America";
+
+ if (countryCode === BLOCKED_COUNTRY_CODE) {
+ return new Response(`We're sorry, you can't access our content from ${countryName}!`, {
+ headers: { "content-type": "text/html" },
+ status: 451,
+ });
+ }
+
+ return new Response(`Hello there! You can freely access our content from ${countryName}!`, {
+ headers: { "content-type": "text/html" },
+ });
+};
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/geolocation/README.md b/examples/edge-functions/pages/geolocation/README.md
new file mode 100644
index 0000000..0a9d59a
--- /dev/null
+++ b/examples/edge-functions/pages/geolocation/README.md
@@ -0,0 +1,41 @@
+
+
+# Geolocation with Netlify Edge Functions
+
+You can use Edge Functions to get information about a user's location to serve location-specific content and personalize
+their experience.
+
+Geolocation information is available on the `Context.geo` object.
+
+```javascript
+context: {
+ geo: {
+ city?: string;
+ country?: {
+ code?: string;
+ name?: string;
+ },
+ subdivision?: {
+ code?: string;
+ name?: string;
+ },
+ }
+}
+```
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/geolocation.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/geolocation
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/geolocation/index.js b/examples/edge-functions/pages/geolocation/index.js
new file mode 100644
index 0000000..128355e
--- /dev/null
+++ b/examples/edge-functions/pages/geolocation/index.js
@@ -0,0 +1,50 @@
+import repoLink from "../../components/repo-link.js";
+import geolocationInfo from "../../components/geolocation-info.js";
+
+export default {
+ title: "Geolocation",
+ metaDescription:
+ "Use Netlify Edge Functions to get information about a user's location to serve location-specific content.",
+ page: function ({ geo }) {
+ return `
+
+
Geolocation
+
You can use Edge Functions to get information about a user's location to serve location-specific content and personalize their experience.
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/hello/README.md b/examples/edge-functions/pages/hello/README.md
new file mode 100644
index 0000000..090f47b
--- /dev/null
+++ b/examples/edge-functions/pages/hello/README.md
@@ -0,0 +1,31 @@
+
+
+# Hello, World! with Netlify Edge Functions
+
+You can use Edge Functions to return a plain HTTP text/html response. In this example, we return the string "Hello,
+World!" as text/html.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```js
+export default async (Request) => {
+ return new Response("Hello, World!", {
+ headers: { "content-type": "text/html" },
+ });
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/hello.js)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/hello
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/hello/index.js b/examples/edge-functions/pages/hello/index.js
new file mode 100644
index 0000000..80eba45
--- /dev/null
+++ b/examples/edge-functions/pages/hello/index.js
@@ -0,0 +1,32 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Hello world",
+ metaDescription: "Explore our library of edge function examples and deploy your own to Netlify.",
+ page: function () {
+ return `
+
+
Hello, world!
+
+ You can use Edge Functions to return a plain HTTP text/html response. In this example, we return the string "Hello, World!" as text/html.
+
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/image/README.md b/examples/edge-functions/pages/image/README.md
new file mode 100644
index 0000000..796a6ca
--- /dev/null
+++ b/examples/edge-functions/pages/image/README.md
@@ -0,0 +1,23 @@
+
+
+# Image Response with Netlify Edge Functions
+
+You can use Edge Functions to return an image. In these examples, we return an internal and external image.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+- [Return an internal image](../../netlify/edge-functions/image-internal.ts)
+- [Return an external image](../../netlify/edge-functions/image-external.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/image
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/image/index.js b/examples/edge-functions/pages/image/index.js
new file mode 100644
index 0000000..b4b9e0e
--- /dev/null
+++ b/examples/edge-functions/pages/image/index.js
@@ -0,0 +1,37 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Return an image",
+ metaDescription: "Use Edge Functions to return an image from your project, or an image from the internet.",
+ page: function () {
+ return `
+
+
Image Response
+
You can use Edge Functions to return an image.
+
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+
+ // Return an internal image using context.rewrite()
+ // This image is stored in the /public directory of this project
+ return context.rewrite("/apple-touch-icon.png");
+
+ // OR
+
+ // Use fetch() and return the image response
+ const kitten = await fetch("https://github.com/service/https://placekitten.com/g/300/300");
+ return kitten;
+};
+
${repoLink("image-internal.ts", "View the code for the internal image request:")}
+
${repoLink("image-external.ts", "View the code for the external image request:")}
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/include/README.md b/examples/edge-functions/pages/include/README.md
new file mode 100644
index 0000000..2b5f02a
--- /dev/null
+++ b/examples/edge-functions/pages/include/README.md
@@ -0,0 +1,44 @@
+
+
+# Edge Includes with Netlify Edge Functions
+
+The ability to transform the content of an HTTP response with Edge Functions enables you to substitute content into
+templates as you would with Edge Includes.
+
+In this example, we look for an {{INCLUDE_PRICE_INFO}} placeholder in our response, and replace it with
+some other content.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ // Get the page content
+ const response = await context.next();
+ const page = await response.text();
+
+ // Search for the placeholder
+ const regex = /{{INCLUDE_PRICE_INFO}}/i;
+
+ // Replace the content
+ const pricingContent = "It's expensive, but buy it anyway.";
+ const updatedPage = page.replace(regex, pricingContent);
+ return new Response(updatedPage, response);
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/include.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/includes
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/include/index.js b/examples/edge-functions/pages/include/index.js
new file mode 100644
index 0000000..e006324
--- /dev/null
+++ b/examples/edge-functions/pages/include/index.js
@@ -0,0 +1,59 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Includes at The Edge",
+ metaDescription: "Dynamically include content into templates at The Edge.",
+ page: function() {
+ return `
+
+
Include content into templates at The Edge
+
+ The ability to transform the content of an HTTP response with Edge Functions enables you to substitute content into templates as you would with Edge Includes.
+
+
+ In this example, we look for an {{INCLUDE_PRICE_INFO}} placeholder in our response, and replace it with some other content.
+
+
+
import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+
+ // Just return what was requested without transforming it,
+ // unless we fnd the query parameter for this demo
+ const url = new URL(request.url);
+ if (url.searchParams.get("include") !== "pricing") {
+ return;
+ }
+
+ console.log("Including pricing content into the page");
+
+ // Get the page content
+ const response = await context.next();
+ const page = await response.text();
+
+ // Search for the placeholder
+ const regex = /{{INCLUDE_PRICE_INFO}}/i;
+
+ // Replace the content
+ const pricingContent = "It's expensive, but buy it anyway.";
+ const updatedPage = page.replace(regex, pricingContent);
+ return new Response(updatedPage, response);
+};
+
+
+
+
This include Edge Function is set up to run using the include=pricing query parameter on any URL, using this entry in the netlify.toml file:
+
+
[[edge_functions]]
+ function = "include"
+ path = "/*"
+
+ `;
+ },
+};
\ No newline at end of file
diff --git a/examples/edge-functions/pages/json/README.md b/examples/edge-functions/pages/json/README.md
new file mode 100644
index 0000000..1adc53b
--- /dev/null
+++ b/examples/edge-functions/pages/json/README.md
@@ -0,0 +1,31 @@
+
+
+# JSON Response with Netlify Edge Functions
+
+You can use Edge Functions to return a JSON response by returning `context.json()` with a JavaScript object — no need to
+`JSON.stringify`!
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ return context.json({ hello: "world" });
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/json.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/json
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/json/index.js b/examples/edge-functions/pages/json/index.js
new file mode 100644
index 0000000..4f5eddf
--- /dev/null
+++ b/examples/edge-functions/pages/json/index.js
@@ -0,0 +1,32 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "JSON Response",
+ metaDescription: "Use Edge Functions to return a JSON response using Context.json().",
+ page: function () {
+ return `
+
+
JSON Response
+
You can use Edge Functions to return a JSON response by returning context.json() with a JavaScript object — no need to JSON.stringify!
+
In this example, we return a JSON object containing hello: "world".
Need to return text/html from an Edge Function? Check out the Hello, world example.
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/localized-content/README.md b/examples/edge-functions/pages/localized-content/README.md
new file mode 100644
index 0000000..efbbd13
--- /dev/null
+++ b/examples/edge-functions/pages/localized-content/README.md
@@ -0,0 +1,40 @@
+
+
+# Serve localized content with Netlify Edge Functions
+
+You can use geolocation data to serve localized content according to country code.
+
+## Code example
+
+Geolocation information is available on the `Context.geo` object.
+
+```javascript
+context: {
+ geo: {
+ city?: string;
+ country?: {
+ code?: string;
+ name?: string;
+ },
+ subdivision?: {
+ code?: string;
+ name?: string;
+ },
+ }
+}
+```
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/localized-content.js)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/localized-content
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/localized-content/index.js b/examples/edge-functions/pages/localized-content/index.js
new file mode 100644
index 0000000..6b9ad0f
--- /dev/null
+++ b/examples/edge-functions/pages/localized-content/index.js
@@ -0,0 +1,43 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Serve localized content",
+ metaDescription: "Use geolocation data to serve localized content according to country.",
+ page: function () {
+ return `
+
+
Serve localized content
+
You can use geolocation data to serve localized content according to country code.
+
Geolocation information is available on the Context.geo object.
You can also combine geolocation data with URL rewrites for another way to serve internationalized content.
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/log/README.md b/examples/edge-functions/pages/log/README.md
new file mode 100644
index 0000000..1558cd3
--- /dev/null
+++ b/examples/edge-functions/pages/log/README.md
@@ -0,0 +1,30 @@
+
+
+# Logging with Netlify Edge Functions
+
+Output content to the logs from an Edge Function using `context.log()`.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ context.log("Hello from the logging service");
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/log.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/log
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/log/index.js b/examples/edge-functions/pages/log/index.js
new file mode 100644
index 0000000..a01cfd0
--- /dev/null
+++ b/examples/edge-functions/pages/log/index.js
@@ -0,0 +1,29 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Logging with Edge Functions",
+ metaDescription: "Output content to the logs from an edge function",
+ page: function () {
+ return `
+
+
Logging with Edge Functions
+
You can output content to the logs during the execution of your Edge Function.
+
import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ context.log("Hello from the logging service");
+};
You can still use console.log() in your Edge Functions, but using context.log() will tell you which Edge Function generated the message for easier debugging!
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/proxy-requests/README.md b/examples/edge-functions/pages/proxy-requests/README.md
new file mode 100644
index 0000000..30eae17
--- /dev/null
+++ b/examples/edge-functions/pages/proxy-requests/README.md
@@ -0,0 +1,38 @@
+
+
+# Proxy requests to another source
+
+You can use [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/fetch) to make requests to other sources via an Edge Function.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+
+ const joke = await fetch("https://github.com/service/https://icanhazdadjoke.com/", {
+ "headers": {
+ "Accept": "application/json"
+ }
+ });
+ const jsonData = await joke.json();
+ return context.json(jsonData);
+};
+
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/proxy-requests.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/proxy-requests.ts
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/proxy-requests/index.js b/examples/edge-functions/pages/proxy-requests/index.js
new file mode 100644
index 0000000..cf7c365
--- /dev/null
+++ b/examples/edge-functions/pages/proxy-requests/index.js
@@ -0,0 +1,37 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Proxy requests to another source",
+ metaDescription: "Make requests to other sources via an Edge Function",
+ page: function() {
+ return `
+
+
Proxy requests to another source
+
You can use fetch() to make requests to other sources via an Edge Function.
Curious about context.json() in the code example above? Check out how you can return a JSON response using Edge Functions.
+
+
+`;
+ },
+};
\ No newline at end of file
diff --git a/examples/edge-functions/pages/rewrite/README.md b/examples/edge-functions/pages/rewrite/README.md
new file mode 100644
index 0000000..cd65b29
--- /dev/null
+++ b/examples/edge-functions/pages/rewrite/README.md
@@ -0,0 +1,30 @@
+
+
+# Rewrite with Netlify Edge Functions
+
+You can rewrite requests on one URL to resources available on another URL using an Edge Function.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ return context.rewrite("/something-to-serve-with-a-rewrite");
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/rewrite.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/rewrite
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/rewrite/index.js b/examples/edge-functions/pages/rewrite/index.js
new file mode 100644
index 0000000..551fdca
--- /dev/null
+++ b/examples/edge-functions/pages/rewrite/index.js
@@ -0,0 +1,31 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Rewrite with Edge Functions",
+ metaDescription: "Rewrite HTTP requests with an edge function",
+ page: function() {
+ return `
+
+
Rewrite with Edge Functions
+
You can rewrite requests on one URL to resources available on another URL using an Edge Function.
You can combine geolocation data with URL rewrites to serve different URLs powering internationalized content.
+
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/set-request-header/README.md b/examples/edge-functions/pages/set-request-header/README.md
new file mode 100644
index 0000000..93f8ab3
--- /dev/null
+++ b/examples/edge-functions/pages/set-request-header/README.md
@@ -0,0 +1,32 @@
+
+
+# Set custom HTTP request headers with Netlify Edge Functions
+
+Use an Edge Function to add HTTP headers to any HTTP request at The Edge.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const response = await context.next();
+ response.headers.set("X-Your-Custom-Header", "A custom header value");
+ return response;
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/set-request-header.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/set-request-header
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/set-request-header/index.js b/examples/edge-functions/pages/set-request-header/index.js
new file mode 100644
index 0000000..820f7b1
--- /dev/null
+++ b/examples/edge-functions/pages/set-request-header/index.js
@@ -0,0 +1,22 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Set HTTP request header",
+ metaDescription: "Set a custom HTTP request header",
+ page: function() {
+ return `
+
+
Set custom HTTP request headers with an Edge Function
+
Use an Edge Function to add HTTP headers to any HTTP request.
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/set-response-header/README.md b/examples/edge-functions/pages/set-response-header/README.md
new file mode 100644
index 0000000..a1eca53
--- /dev/null
+++ b/examples/edge-functions/pages/set-response-header/README.md
@@ -0,0 +1,32 @@
+
+
+# Set custom HTTP response headers with Netlify Edge Functions
+
+Use an Edge Function to add HTTP headers to any HTTP response at The Edge.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const response = await context.next();
+ response.headers.set("X-Your-Custom-Header", "A custom header value");
+ return response;
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/set-response-header.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/set-response-header
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/set-response-header/index.js b/examples/edge-functions/pages/set-response-header/index.js
new file mode 100644
index 0000000..04a8c11
--- /dev/null
+++ b/examples/edge-functions/pages/set-response-header/index.js
@@ -0,0 +1,27 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Set HTTP response header",
+ metaDescription: "Set a custom HTTP response header",
+ page: function() {
+ return `
+
+
Set custom HTTP response headers with an Edge Function
+
Use an Edge Function to add HTTP headers to any HTTP response.
+
+ `;
+ },
+};
diff --git a/examples/edge-functions/pages/transform/README.md b/examples/edge-functions/pages/transform/README.md
new file mode 100644
index 0000000..e4c6c89
--- /dev/null
+++ b/examples/edge-functions/pages/transform/README.md
@@ -0,0 +1,44 @@
+
+
+# Transform responses with Netlify Edge Functions
+
+You can use Edge Functions to transform the content of an HTTP response. In this example, we transform the response of a
+request to `/hello` with JavaScript's toUpperCase() function, using the query parameter
+`?method=transform`.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const url = new URL(request.url);
+
+ // Look for the query parameter, and return if we don't find it
+ if (url.searchParams.get("method") !== "transform") {
+ return;
+ }
+
+ context.log(`Transforming the response from this ${url}`);
+
+ const response = await context.next();
+
+ const text = await response.text();
+ return new Response(text.toUpperCase(), response);
+};
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/transform.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/transform
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples)
diff --git a/examples/edge-functions/pages/transform/index.js b/examples/edge-functions/pages/transform/index.js
new file mode 100644
index 0000000..8bffa6a
--- /dev/null
+++ b/examples/edge-functions/pages/transform/index.js
@@ -0,0 +1,44 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Transform HTTP Response",
+ metaDescription: "Dynamically transform any page response at The Edge.",
+ page: function () {
+ return `
+
+
Transform responses
+
+ You can use Edge Functions to transform the content of an HTTP response. In this example, we transform the response of a request to /hello with a toUpperCase() function, using the query parameter method=transform.
+
+
+
import { Context } from "netlify:edge";
+
+export default async (request: Request, context: Context) => {
+ const url = new URL(request.url);
+
+ // Look for the query parameter, and return if we don't find it
+ if (url.searchParams.get("method") !== "transform") {
+ return;
+ }
+
+ const response = await context.next();
+ const text = await response.text();
+ return new Response(text.toUpperCase(), response);
+};
+
+
+
This transform Edge Function is set up to run using the method=transform query parameter on any URL, using this entry in the netlify.toml file:
+
+
[[edge_functions]]
+ function = "transform"
+ path = "/*"