diff --git a/packages/netlify/CHANGELOG.md b/packages/netlify/CHANGELOG.md
new file mode 100644
index 00000000..0c09187a
--- /dev/null
+++ b/packages/netlify/CHANGELOG.md
@@ -0,0 +1,894 @@
+# @astrojs/netlify
+
+## 3.0.2
+
+### Patch Changes
+
+- [#8661](https://github.com/withastro/astro/pull/8661) [`008f7647c`](https://github.com/withastro/astro/commit/008f7647c4788207aab55ab12c734bd80e6df9c5) Thanks [@Skn0tt](https://github.com/Skn0tt)! - fix build failures because of CJS builds and top-level await
+
+- Updated dependencies [[`69fbf95b2`](https://github.com/withastro/astro/commit/69fbf95b22c0fb0d8e7e5fef9ec61e26cac9767f)]:
+ - astro@3.1.4
+ - @astrojs/underscore-redirects@0.3.0
+
+## 3.0.1
+
+### Patch Changes
+
+- [#8346](https://github.com/withastro/astro/pull/8346) [`b74dacdb6`](https://github.com/withastro/astro/commit/b74dacdb6a49755f979f15091355f06bd6bd64bf) Thanks [@delucis](https://github.com/delucis)! - Update README
+
+- Updated dependencies [[`c5633434f`](https://github.com/withastro/astro/commit/c5633434f02cc477ee8da380e22efaccfa55d459), [`405ad9501`](https://github.com/withastro/astro/commit/405ad950173dadddc519cf1c2e7f2523bf5326a8), [`6b1e79814`](https://github.com/withastro/astro/commit/6b1e7981469d30aa4c3658487abed6ffea94797f)]:
+ - astro@3.0.7
+ - @astrojs/underscore-redirects@0.3.0
+
+## 3.0.0
+
+### Major Changes
+
+- [#8188](https://github.com/withastro/astro/pull/8188) [`d0679a666`](https://github.com/withastro/astro/commit/d0679a666f37da0fca396d42b9b32bbb25d29312) Thanks [@ematipico](https://github.com/ematipico)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023.
+
+- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate
+
+- [#8188](https://github.com/withastro/astro/pull/8188) [`7511a4980`](https://github.com/withastro/astro/commit/7511a4980fd36536464c317de33a5190427f430a) Thanks [@ematipico](https://github.com/ematipico)! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of `astro:assets` such as enforcing `alt`, no CLS etc to users
+
+- [#8188](https://github.com/withastro/astro/pull/8188) [`148e61d24`](https://github.com/withastro/astro/commit/148e61d2492456811f8a3c8daaab1c3429a2ffdc) Thanks [@ematipico](https://github.com/ematipico)! - Reduced the amount of polyfills provided by Astro. Astro will no longer provide (no-op) polyfills for several web apis such as HTMLElement, Image or Document. If you need access to those APIs on the server, we recommend using more proper polyfills available on npm.
+
+- [#8029](https://github.com/withastro/astro/pull/8029) [`2ee418e06`](https://github.com/withastro/astro/commit/2ee418e06ab1f7855dee0078afbad0b06de3b183) Thanks [@matthewp](https://github.com/matthewp)! - Remove the Netlify Edge adapter
+
+ `@astrojs/netlify/functions` now supports Edge middleware, so a separate adapter for Edge itself (deploying your entire app to the edge) is no longer necessary. Please update your Astro config to reflect this change:
+
+ ```diff
+ // astro.config.mjs
+ import { defineConfig } from 'astro/config';
+ - import netlify from '@astrojs/netlify/edge';
+ + import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ + edgeMiddleware: true
+ }),
+ });
+ ```
+
+ This adapter had several known limitations and compatibility issues that prevented many people from using it in production. To reduce maintenance costs and because we have a better story with Serveless + Edge Middleware, we are removing the Edge adapter.
+
+### Minor Changes
+
+- [#8188](https://github.com/withastro/astro/pull/8188) [`cd2d7e769`](https://github.com/withastro/astro/commit/cd2d7e76981ef9b9013453aa2629838e1e9fd422) Thanks [@ematipico](https://github.com/ematipico)! - Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter
+ can tell Astro if it can support it.
+
+ ```ts
+ import { AstroIntegration } from './astro';
+
+ function myIntegration(): AstroIntegration {
+ return {
+ name: 'astro-awesome-list',
+ // new feature map
+ supportedAstroFeatures: {
+ hybridOutput: 'experimental',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
+ };
+ }
+ ```
+
+- [#8188](https://github.com/withastro/astro/pull/8188) [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923) Thanks [@ematipico](https://github.com/ematipico)! - The `build.split` and `build.excludeMiddleware` configuration options are deprecated and have been replaced by options in the adapter config.
+
+ If your config includes the `build.excludeMiddleware` option, replace it with `edgeMiddleware` in your adapter options:
+
+ ```diff
+ import { defineConfig } from "astro/config";
+ import netlify from "@astrojs/netlify/functions";
+
+ export default defineConfig({
+ build: {
+ - excludeMiddleware: true
+ },
+ adapter: netlify({
+ + edgeMiddleware: true
+ }),
+ });
+ ```
+
+ If your config includes the `build.split` option, replace it with `functionPerRoute` in your adapter options:
+
+ ```diff
+ import { defineConfig } from "astro/config";
+ import netlify from "@astrojs/netlify/functions";
+
+ export default defineConfig({
+ build: {
+ - split: true
+ },
+ adapter: netlify({
+ + functionPerRoute: true
+ }),
+ });
+ ```
+
+### Patch Changes
+
+- Updated dependencies [[`d0679a666`](https://github.com/withastro/astro/commit/d0679a666f37da0fca396d42b9b32bbb25d29312), [`db39206cb`](https://github.com/withastro/astro/commit/db39206cbb85b034859ac416179f141184bb2bff), [`adf9fccfd`](https://github.com/withastro/astro/commit/adf9fccfdda107c2224558f1c2e6a77847ac0a8a), [`0c7b42dc6`](https://github.com/withastro/astro/commit/0c7b42dc6780e687e416137539f55a3a427d1d10), [`46c4c0e05`](https://github.com/withastro/astro/commit/46c4c0e053f830585b9ef229ce1c259df00a80f8), [`364d861bd`](https://github.com/withastro/astro/commit/364d861bd527b8511968e2837728148f090bedef), [`2484dc408`](https://github.com/withastro/astro/commit/2484dc4080e5cd84b9a53648a1de426d7c907be2), [`81545197a`](https://github.com/withastro/astro/commit/81545197a32fd015d763fc386c8b67e0e08b7393), [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7), [`c2c71d90c`](https://github.com/withastro/astro/commit/c2c71d90c264a2524f99e0373ab59015f23ad4b1), [`cd2d7e769`](https://github.com/withastro/astro/commit/cd2d7e76981ef9b9013453aa2629838e1e9fd422), [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923), [`e45f30293`](https://github.com/withastro/astro/commit/e45f3029340db718b6ed7e91b5d14f5cf14cd71d), [`c0de7a7b0`](https://github.com/withastro/astro/commit/c0de7a7b0f042cd49cbea4f4ac1b2ab6f9fef644), [`65c354969`](https://github.com/withastro/astro/commit/65c354969e6fe0ef6d622e8f4c545e2f717ce8c6), [`3c3100851`](https://github.com/withastro/astro/commit/3c31008519ce68b5b1b1cb23b71fbe0a2d506882), [`34cb20021`](https://github.com/withastro/astro/commit/34cb2002161ba88df6bcb72fecfd12ed867c134b), [`a824863ab`](https://github.com/withastro/astro/commit/a824863ab1c451f4068eac54f28dd240573e1cba), [`44f7a2872`](https://github.com/withastro/astro/commit/44f7a28728c56c04ac377b6e917329f324874043), [`1048aca55`](https://github.com/withastro/astro/commit/1048aca550769415e528016e42b358ffbfd44b61), [`be6bbd2c8`](https://github.com/withastro/astro/commit/be6bbd2c86b9bf5268e765bb937dda00ff15781a), [`9e021a91c`](https://github.com/withastro/astro/commit/9e021a91c57d10809f588dd47968fc0e7f8b4d5c), [`7511a4980`](https://github.com/withastro/astro/commit/7511a4980fd36536464c317de33a5190427f430a), [`c37632a20`](https://github.com/withastro/astro/commit/c37632a20d06164fb97a4c2fc48df6d960398832), [`acf652fc1`](https://github.com/withastro/astro/commit/acf652fc1d5db166231e87e22d0d50444f5556d8), [`42785c7b7`](https://github.com/withastro/astro/commit/42785c7b784b151e6d582570e5d74482129e8eb8), [`8450379db`](https://github.com/withastro/astro/commit/8450379db854fb1eaa9f38f21d65db240bc616cd), [`dbc97b121`](https://github.com/withastro/astro/commit/dbc97b121f42583728f1cdfdbf14575fda943f5b), [`7d2f311d4`](https://github.com/withastro/astro/commit/7d2f311d428e3d1c8c13b9bf2a708d6435713fc2), [`2540feedb`](https://github.com/withastro/astro/commit/2540feedb06785d5a20eecc3668849f147d778d4), [`ea7ff5177`](https://github.com/withastro/astro/commit/ea7ff5177dbcd7b2508cb1eef1b22b8ee1f47079), [`68efd4a8b`](https://github.com/withastro/astro/commit/68efd4a8b29f248397667801465b3152dc98e9a7), [`7bd1b86f8`](https://github.com/withastro/astro/commit/7bd1b86f85c06fdde0a1ed9146d01bac69990671), [`036388f66`](https://github.com/withastro/astro/commit/036388f66dab68ad54b895ed86f9176958dd83c8), [`519a1c4e8`](https://github.com/withastro/astro/commit/519a1c4e8407c7abcb8d879b67a9f4b960652cae), [`1f58a7a1b`](https://github.com/withastro/astro/commit/1f58a7a1bea6888868b689dac94801d554319b02), [`2ae9d37f0`](https://github.com/withastro/astro/commit/2ae9d37f0a9cb21ab288d3c30aecb6d84db87788), [`a8f35777e`](https://github.com/withastro/astro/commit/a8f35777e7e322068a4e2f520c2c9e43ade19e58), [`70f34f5a3`](https://github.com/withastro/astro/commit/70f34f5a355f42526ee9e5355f3de8e510002ea2), [`5208a3c8f`](https://github.com/withastro/astro/commit/5208a3c8fefcec7694857fb344af351f4631fc34), [`84af8ed9d`](https://github.com/withastro/astro/commit/84af8ed9d1e6401c6ebc9c60fe8cddb44d5044b0), [`f003e7364`](https://github.com/withastro/astro/commit/f003e7364317cafdb8589913b26b28e928dd07c9), [`ffc9e2d3d`](https://github.com/withastro/astro/commit/ffc9e2d3de46049bf3d82140ef018f524fb03187), [`732111cdc`](https://github.com/withastro/astro/commit/732111cdce441639db31f40f621df48442d00969), [`0f637c71e`](https://github.com/withastro/astro/commit/0f637c71e511cb4c51712128d217a26c8eee4d40), [`33b8910cf`](https://github.com/withastro/astro/commit/33b8910cfdce5713891c50a84a0a8fe926311710), [`8a5b0c1f3`](https://github.com/withastro/astro/commit/8a5b0c1f3a4be6bb62db66ec70144109ff5b4c59), [`148e61d24`](https://github.com/withastro/astro/commit/148e61d2492456811f8a3c8daaab1c3429a2ffdc), [`e79e3779d`](https://github.com/withastro/astro/commit/e79e3779df0ad35253abcdb931d622847d9adb12), [`632579dc2`](https://github.com/withastro/astro/commit/632579dc2094cc342929261c89e689f0dd358284), [`3674584e0`](https://github.com/withastro/astro/commit/3674584e02b161a698b429ceb66723918fdc56ac), [`1db4e92c1`](https://github.com/withastro/astro/commit/1db4e92c12ed73681217f5cefd39f2f47542f961), [`e7f872e91`](https://github.com/withastro/astro/commit/e7f872e91e852b901cf221a5151077dec64305bf), [`16f09dfff`](https://github.com/withastro/astro/commit/16f09dfff7722fda99dd0412e3006a7a39c80829), [`4477bb41c`](https://github.com/withastro/astro/commit/4477bb41c8ed688785c545731ef5b184b629f4e5), [`55c10d1d5`](https://github.com/withastro/astro/commit/55c10d1d564e805efc3c1a7c48e0d9a1cdf0c7ed), [`3e834293d`](https://github.com/withastro/astro/commit/3e834293d47ab2761a7aa013916e8371871efb7f), [`96beb883a`](https://github.com/withastro/astro/commit/96beb883ad87f8bbf5b2f57e14a743763d2a6f58), [`997a0db8a`](https://github.com/withastro/astro/commit/997a0db8a4e3851edd69384cf5eadbb969e1d547), [`80f1494cd`](https://github.com/withastro/astro/commit/80f1494cdaf72e58a420adb4f7c712d4089e1923), [`0f0625504`](https://github.com/withastro/astro/commit/0f0625504145f18cba7dc6cf20291cb2abddc5a9), [`e1ae56e72`](https://github.com/withastro/astro/commit/e1ae56e724d0f83db1230359e06cd6bc26f5fa26), [`f32d093a2`](https://github.com/withastro/astro/commit/f32d093a280faafff024228c12bb438156ec34d7), [`f01eb585e`](https://github.com/withastro/astro/commit/f01eb585e7c972d940761309b1595f682b6922d2), [`b76c166bd`](https://github.com/withastro/astro/commit/b76c166bdd8e28683f62806aef968d1e0c3b06d9), [`a87cbe400`](https://github.com/withastro/astro/commit/a87cbe400314341d5f72abf86ea264e6b47c091f), [`866ed4098`](https://github.com/withastro/astro/commit/866ed4098edffb052239cdb26e076cf8db61b1d9), [`767eb6866`](https://github.com/withastro/astro/commit/767eb68666eb777965baa0d6ade20bbafecf95bf), [`32669cd47`](https://github.com/withastro/astro/commit/32669cd47555e9c7433c3998a2b6e624dfb2d8e9)]:
+ - astro@3.0.0
+ - @astrojs/underscore-redirects@0.3.0
+
+## 3.0.0-rc.2
+
+### Major Changes
+
+- [#8179](https://github.com/withastro/astro/pull/8179) [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7) Thanks [@matthewp](https://github.com/matthewp)! - Astro 3.0 Release Candidate
+
+### Patch Changes
+
+- Updated dependencies [[`adf9fccfd`](https://github.com/withastro/astro/commit/adf9fccfdda107c2224558f1c2e6a77847ac0a8a), [`582132328`](https://github.com/withastro/astro/commit/5821323285646aee7ff9194a505f708028e4db57), [`81545197a`](https://github.com/withastro/astro/commit/81545197a32fd015d763fc386c8b67e0e08b7393), [`6011d52d3`](https://github.com/withastro/astro/commit/6011d52d38e43c3e3d52bc3bc41a60e36061b7b7), [`be6bbd2c8`](https://github.com/withastro/astro/commit/be6bbd2c86b9bf5268e765bb937dda00ff15781a), [`42785c7b7`](https://github.com/withastro/astro/commit/42785c7b784b151e6d582570e5d74482129e8eb8), [`95120efbe`](https://github.com/withastro/astro/commit/95120efbe817163663492181cbeb225849354493), [`2ae9d37f0`](https://github.com/withastro/astro/commit/2ae9d37f0a9cb21ab288d3c30aecb6d84db87788), [`f003e7364`](https://github.com/withastro/astro/commit/f003e7364317cafdb8589913b26b28e928dd07c9), [`732111cdc`](https://github.com/withastro/astro/commit/732111cdce441639db31f40f621df48442d00969), [`33b8910cf`](https://github.com/withastro/astro/commit/33b8910cfdce5713891c50a84a0a8fe926311710), [`e79e3779d`](https://github.com/withastro/astro/commit/e79e3779df0ad35253abcdb931d622847d9adb12), [`179796405`](https://github.com/withastro/astro/commit/179796405e053b559d83f84507e5a465861a029a), [`a87cbe400`](https://github.com/withastro/astro/commit/a87cbe400314341d5f72abf86ea264e6b47c091f), [`767eb6866`](https://github.com/withastro/astro/commit/767eb68666eb777965baa0d6ade20bbafecf95bf)]:
+ - astro@3.0.0-rc.5
+ - @astrojs/underscore-redirects@0.3.0-rc.1
+
+## 3.0.0-beta.1
+
+### Major Changes
+
+- [#8029](https://github.com/withastro/astro/pull/8029) [`2ee418e06`](https://github.com/withastro/astro/commit/2ee418e06ab1f7855dee0078afbad0b06de3b183) Thanks [@matthewp](https://github.com/matthewp)! - Remove the Netlify Edge adapter
+
+ `@astrojs/netlify/functions` now supports Edge middleware, so a separate adapter for Edge itself (deploying your entire app to the edge) is no longer necessary. Please update your Astro config to reflect this change:
+
+ ```diff
+ // astro.config.mjs
+ import { defineConfig } from 'astro/config';
+ - import netlify from '@astrojs/netlify/edge';
+ + import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ + edgeMiddleware: true
+ }),
+ });
+ ```
+
+ This adapter had several known limitations and compatibility issues that prevented many people from using it in production. To reduce maintenance costs and because we have a better story with Serveless + Edge Middleware, we are removing the Edge adapter.
+
+### Patch Changes
+
+- Updated dependencies [[`65c354969`](https://github.com/withastro/astro/commit/65c354969e6fe0ef6d622e8f4c545e2f717ce8c6), [`3c3100851`](https://github.com/withastro/astro/commit/3c31008519ce68b5b1b1cb23b71fbe0a2d506882), [`34cb20021`](https://github.com/withastro/astro/commit/34cb2002161ba88df6bcb72fecfd12ed867c134b), [`7bd1b86f8`](https://github.com/withastro/astro/commit/7bd1b86f85c06fdde0a1ed9146d01bac69990671), [`519a1c4e8`](https://github.com/withastro/astro/commit/519a1c4e8407c7abcb8d879b67a9f4b960652cae), [`70f34f5a3`](https://github.com/withastro/astro/commit/70f34f5a355f42526ee9e5355f3de8e510002ea2), [`0f637c71e`](https://github.com/withastro/astro/commit/0f637c71e511cb4c51712128d217a26c8eee4d40), [`866ed4098`](https://github.com/withastro/astro/commit/866ed4098edffb052239cdb26e076cf8db61b1d9), [`5b1e39ef6`](https://github.com/withastro/astro/commit/5b1e39ef6ec6dcebea96584f95d9530bd9aa715d)]:
+ - astro@3.0.0-beta.1
+ - @astrojs/underscore-redirects@0.3.0-beta.0
+
+## 3.0.0-beta.0
+
+### Major Changes
+
+- [`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023.
+
+- [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388) Thanks [@Princesseuh](https://github.com/Princesseuh)! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of `astro:assets` such as enforcing `alt`, no CLS etc to users
+
+- [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Reduced the amount of polyfills provided by Astro. Astro will no longer provide (no-op) polyfills for several web apis such as HTMLElement, Image or Document. If you need access to those APIs on the server, we recommend using more proper polyfills available on npm.
+
+### Minor Changes
+
+- [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215) Thanks [@ematipico](https://github.com/ematipico)! - Introduced the concept of feature map. A feature map is a list of features that are built-in in Astro, and an Adapter
+ can tell Astro if it can support it.
+
+ ```ts
+ import { AstroIntegration } from './astro';
+
+ function myIntegration(): AstroIntegration {
+ return {
+ name: 'astro-awesome-list',
+ // new feature map
+ supportedAstroFeatures: {
+ hybridOutput: 'experimental',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: false,
+ isSquooshCompatible: false,
+ },
+ },
+ };
+ }
+ ```
+
+- [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769) Thanks [@ematipico](https://github.com/ematipico)! - The `build.split` and `build.excludeMiddleware` configuration options are deprecated and have been replaced by options in the adapter config.
+
+ If your config includes the `build.excludeMiddleware` option, replace it with `edgeMiddleware` in your adapter options:
+
+ ```diff
+ import { defineConfig } from "astro/config";
+ import netlify from "@astrojs/netlify/functions";
+
+ export default defineConfig({
+ build: {
+ - excludeMiddleware: true
+ },
+ adapter: netlify({
+ + edgeMiddleware: true
+ }),
+ });
+ ```
+
+ If your config includes the `build.split` option, replace it with `functionPerRoute` in your adapter options:
+
+ ```diff
+ import { defineConfig } from "astro/config";
+ import netlify from "@astrojs/netlify/functions";
+
+ export default defineConfig({
+ build: {
+ - split: true
+ },
+ adapter: netlify({
+ + functionPerRoute: true
+ }),
+ });
+ ```
+
+### Patch Changes
+
+- Updated dependencies [[`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81), [`76ddef19c`](https://github.com/withastro/astro/commit/76ddef19ccab6e5f7d3a5740cd41acf10e334b38), [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`2f951cd40`](https://github.com/withastro/astro/commit/2f951cd403dfcc2c3ca6aae618ae3e1409516e32), [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388), [`67becaa58`](https://github.com/withastro/astro/commit/67becaa580b8f787df58de66b7008b7098f1209c), [`bc37331d8`](https://github.com/withastro/astro/commit/bc37331d8154e3e95a8df9131e4e014e78a7a9e7), [`dfc2d93e3`](https://github.com/withastro/astro/commit/dfc2d93e3c645995379358fabbdfa9aab99f43d8), [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a), [`1be84dfee`](https://github.com/withastro/astro/commit/1be84dfee3ce8e6f5cc624f99aec4e980f6fde37), [`35f01df79`](https://github.com/withastro/astro/commit/35f01df797d23315f2bee2fc3fd795adb0559c58), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`78de801f2`](https://github.com/withastro/astro/commit/78de801f21fd4ca1653950027d953bf08614566b), [`59d6e569f`](https://github.com/withastro/astro/commit/59d6e569f63e175c97e82e94aa7974febfb76f7c), [`7723c4cc9`](https://github.com/withastro/astro/commit/7723c4cc93298c2e6530e55da7afda048f22cf81), [`fb5cd6b56`](https://github.com/withastro/astro/commit/fb5cd6b56dc27a71366ed5e1ab8bfe9b8f96bac5), [`631b9c410`](https://github.com/withastro/astro/commit/631b9c410d5d66fa384674027ba95d69ebb5063f)]:
+ - astro@3.0.0-beta.0
+ - @astrojs/underscore-redirects@0.3.0-beta.0
+
+## 2.6.0
+
+### Minor Changes
+
+- [#7975](https://github.com/withastro/astro/pull/7975) [`f974c95a2`](https://github.com/withastro/astro/commit/f974c95a27ccbf91adbc66f6f1433f4cf11be33e) Thanks [@lilnasy](https://github.com/lilnasy)! - If you are using Netlify's On-demand Builders, you can now specify how long your pages should remain cached. By default, all pages will be rendered on first visit and reused on every subsequent visit until a redeploy. To set a custom revalidation time, call the `runtime.setBuildersTtl()` local in either your frontmatter or middleware.
+
+ ```astro
+ ---
+ import Layout from '../components/Layout.astro';
+
+ if (import.meta.env.PROD) {
+ // revalidates every 45 seconds
+ Astro.locals.runtime.setBuildersTtl(45);
+ }
+ ---
+
+
+ {new Date(Date.now())}
+
+ ```
+
+### Patch Changes
+
+- Updated dependencies [[`1b8d30209`](https://github.com/withastro/astro/commit/1b8d3020990130dabfaaf753db73a32c6e0c896a), [`405913cdf`](https://github.com/withastro/astro/commit/405913cdf20b26407aa351c090f0a0859a4e6f54), [`87d4b1843`](https://github.com/withastro/astro/commit/87d4b18437c7565c48cad4bea81831c2a244ebb8), [`c23377caa`](https://github.com/withastro/astro/commit/c23377caafbc75deb91c33b9678c1b6868ad40ea), [`86bee2812`](https://github.com/withastro/astro/commit/86bee2812185df6e14025e5962a335f51853587b)]:
+ - astro@2.10.6
+
+## 2.5.2
+
+### Patch Changes
+
+- [#7862](https://github.com/withastro/astro/pull/7862) [`1859960d0`](https://github.com/withastro/astro/commit/1859960d0443cc6638569408282544f37e0a90ae) Thanks [@Yan-Thomas](https://github.com/Yan-Thomas)! - Fix README GitHub search link
+
+- [#7754](https://github.com/withastro/astro/pull/7754) [`298dbb89f`](https://github.com/withastro/astro/commit/298dbb89f2963a547370b6e65cafd2650fdb1b27) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Improve `404` behavior for `serverless` and `edge`
+
+- Updated dependencies [[`298dbb89f`](https://github.com/withastro/astro/commit/298dbb89f2963a547370b6e65cafd2650fdb1b27), [`9e2203847`](https://github.com/withastro/astro/commit/9e22038472c8be05ed7a72620534b88324dce793), [`5c5da8d2f`](https://github.com/withastro/astro/commit/5c5da8d2fbb37830f3ee81830d4c9afcd2c1a3e3), [`0b8375fe8`](https://github.com/withastro/astro/commit/0b8375fe82a15bfff3f517f98de6454adb2779f1), [`89d015db6`](https://github.com/withastro/astro/commit/89d015db6ce4d15b5b1140f0eb6bfbef187d6ad7), [`ebf7ebbf7`](https://github.com/withastro/astro/commit/ebf7ebbf7ae767625d736fad327954cfb853837e)]:
+ - astro@2.9.7
+
+## 2.5.1
+
+### Patch Changes
+
+- [#7805](https://github.com/withastro/astro/pull/7805) [`42a21b5da`](https://github.com/withastro/astro/commit/42a21b5da631948da4495062a6ef30fbb91abd05) Thanks [@matthewp](https://github.com/matthewp)! - Prevent building .html file redirects in hybrid mode
+
+- Updated dependencies [[`31c4031ba`](https://github.com/withastro/astro/commit/31c4031ba7aea132a861f2465f38a83741f0cd05), [`5161cf919`](https://github.com/withastro/astro/commit/5161cf919c81bd3681af221def0abab7d25abec0), [`59b556232`](https://github.com/withastro/astro/commit/59b556232696d3aba3c2263ea104cd9922085fd2), [`267487e63`](https://github.com/withastro/astro/commit/267487e63ea0a4cfcb771c667a088afb16c62ba6), [`b063a2d8a`](https://github.com/withastro/astro/commit/b063a2d8aeaed18550d148511bfb68f9ba3cdb09), [`d5f526b33`](https://github.com/withastro/astro/commit/d5f526b3397cf24aa06353de2de91b2ba08cd4eb), [`7dbcbc86b`](https://github.com/withastro/astro/commit/7dbcbc86b3bd7e5458570906745364c9399d1a46)]:
+ - astro@2.9.4
+
+## 2.5.0
+
+### Minor Changes
+
+- [#7700](https://github.com/withastro/astro/pull/7700) [`a77741d25`](https://github.com/withastro/astro/commit/a77741d25e5d923461026003aba81869833863d4) Thanks [@delucis](https://github.com/delucis)! - When a project uses the new `build.excludeMiddleware` Astro config option, the `@astrojs/netlify/functions` adapter will bundle your middleware to run in a [Netlify Edge Function](https://docs.netlify.com/edge-functions/overview/).
+
+ See the [Netlify adapter documentation](https://docs.astro.build/en/guides/integrations-guide/netlify/#run-middleware-in-edge-functions) for more details.
+
+### Patch Changes
+
+- Updated dependencies [[`72bbfac97`](https://github.com/withastro/astro/commit/72bbfac976c2965a523eea88ff0543e64d848d80), [`d401866f9`](https://github.com/withastro/astro/commit/d401866f93bfe25a50c171bc54b2b1ee0f483cc9), [`4f6b5ae2b`](https://github.com/withastro/astro/commit/4f6b5ae2ba8eb162e03f25cbd600a905d434f529), [`06c255716`](https://github.com/withastro/astro/commit/06c255716ae8e922fb9d4ffa5595cbb34146fff6)]:
+ - astro@2.8.5
+
+## 2.4.0
+
+### Minor Changes
+
+- [#7615](https://github.com/withastro/astro/pull/7615) [`f21357b69`](https://github.com/withastro/astro/commit/f21357b69d94fe8d81f267efddb182d1a3cc678a) Thanks [@ematipico](https://github.com/ematipico)! - The Netlify adapter builds to a single function by default. Astro 2.7 added support for splitting your build into separate entry points per page. If you use this configuration, the Netlify adapter will generate a separate function for each page. This can help reduce the size of each function so they are only bundling code used on that page.
+
+ ```js
+ // astro.config.mjs
+ import { defineConfig } from 'astro/config';
+ import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ output: 'server',
+ adapter: netlify(),
+ build: {
+ split: true,
+ },
+ });
+ ```
+
+### Patch Changes
+
+- Updated dependencies [[`f21357b69`](https://github.com/withastro/astro/commit/f21357b69d94fe8d81f267efddb182d1a3cc678a), [`86e19c7cf`](https://github.com/withastro/astro/commit/86e19c7cf8696e065c1ccdc2eb841ad0a2b61ede)]:
+ - @astrojs/underscore-redirects@0.2.0
+ - astro@2.8.2
+
+## 2.3.0
+
+### Minor Changes
+
+- [#7067](https://github.com/withastro/astro/pull/7067) [`57f8d14c0`](https://github.com/withastro/astro/commit/57f8d14c027c30919363e12c664ccff4ed64d0fc) Thanks [@matthewp](https://github.com/matthewp)! - Support for experimental redirects
+
+ This adds support for the redirects RFC in the Netlify adapter, including a new `@astrojs/netlify/static` adapter for static sites.
+
+ No changes are necessary when using SSR. Simply use configured redirects and the adapter will update your `_redirects` file.
+
+### Patch Changes
+
+- [#7260](https://github.com/withastro/astro/pull/7260) [`39403c32f`](https://github.com/withastro/astro/commit/39403c32faea58399c61d3344b770f195be60d5b) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Unflags support for `output: 'hybrid'` mode, which enables pre-rendering by default. The additional `experimental.hybridOutput` flag can be safely removed from your configuration.
+
+- Updated dependencies [[`57f8d14c0`](https://github.com/withastro/astro/commit/57f8d14c027c30919363e12c664ccff4ed64d0fc), [`414eb19d2`](https://github.com/withastro/astro/commit/414eb19d2fcb55758f9d053076773b11b62f4c97), [`a7e2b37ff`](https://github.com/withastro/astro/commit/a7e2b37ff73871c46895c615846a86a539f45330), [`dd1a6b6c9`](https://github.com/withastro/astro/commit/dd1a6b6c941aeb7af934bd12db22412af262f5a1), [`d72cfa7ca`](https://github.com/withastro/astro/commit/d72cfa7cad758192163712ceb269405659fd14bc), [`144813f73`](https://github.com/withastro/astro/commit/144813f7308dcb9de64ebe3f0f2c6cba9ad81eb1), [`b5213654b`](https://github.com/withastro/astro/commit/b5213654b1b7f3ba573a48d3be688b2bdde7870f), [`e3b8c6296`](https://github.com/withastro/astro/commit/e3b8c62969d680d1915a122c610d281d6711aa63), [`890a2bc98`](https://github.com/withastro/astro/commit/890a2bc9891a2449ab99b01b65468f6dddba6b12), [`39403c32f`](https://github.com/withastro/astro/commit/39403c32faea58399c61d3344b770f195be60d5b), [`101f03209`](https://github.com/withastro/astro/commit/101f032098148b3daaac8d46ff1e535b79232e43)]:
+ - astro@2.6.0
+
+## 2.2.3
+
+### Patch Changes
+
+- [#6991](https://github.com/withastro/astro/pull/6991) [`719002ca5`](https://github.com/withastro/astro/commit/719002ca5b128744fb4316d4a52c5dcd46a42759) Thanks [@MoustaphaDev](https://github.com/MoustaphaDev)! - Enable experimental support for hybrid SSR with pre-rendering enabled by default
+
+ **astro.config.mjs**
+
+ ```js
+ import { defineConfig } from 'astro/config';
+ export defaultdefineConfig({
+ output: 'hybrid',
+ experimental: {
+ hybridOutput: true,
+ },
+ })
+ ```
+
+ Then add `export const prerender = false` to any page or endpoint you want to opt-out of pre-rendering.
+
+ **src/pages/contact.astro**
+
+ ```astro
+ ---
+ export const prerender = false;
+
+ if (Astro.request.method === 'POST') {
+ // handle form submission
+ }
+ ---
+
+
+ ```
+
+- [#7104](https://github.com/withastro/astro/pull/7104) [`826e02890`](https://github.com/withastro/astro/commit/826e0289005f645b902375b98d5549c6a95ccafa) Thanks [@bluwy](https://github.com/bluwy)! - Specify `"files"` field to only publish necessary files
+
+- Updated dependencies [[`4516d7b22`](https://github.com/withastro/astro/commit/4516d7b22c5979cde4537f196b53ae2826ba9561), [`e186ecc5e`](https://github.com/withastro/astro/commit/e186ecc5e292de8c6a2c441a2d588512c0813068), [`c6d7ebefd`](https://github.com/withastro/astro/commit/c6d7ebefdd554a9ef29cfeb426ac55cab80d6473), [`914c439bc`](https://github.com/withastro/astro/commit/914c439bccee9fec002c6d92beaa501c398e62ac), [`e9fc2c221`](https://github.com/withastro/astro/commit/e9fc2c2213036d47cd30a47a6cdad5633481a0f8), [`075eee08f`](https://github.com/withastro/astro/commit/075eee08f2e2b0baea008b97f3523f2cb937ee44), [`719002ca5`](https://github.com/withastro/astro/commit/719002ca5b128744fb4316d4a52c5dcd46a42759), [`fc52681ba`](https://github.com/withastro/astro/commit/fc52681ba2f8fe8bcd92eeedf3c6a52fd86a390e), [`fb84622af`](https://github.com/withastro/astro/commit/fb84622af04f795de8d17f24192de105f70fe910), [`cada10a46`](https://github.com/withastro/astro/commit/cada10a466f81f8edb0aa664f9cffdb6b5b8f307), [`cd410c5eb`](https://github.com/withastro/astro/commit/cd410c5eb71f825259279c27c4c39d0ad282c3f0), [`73ec6f6c1`](https://github.com/withastro/astro/commit/73ec6f6c16cadb71dafe9f664f0debde072c3173), [`410428672`](https://github.com/withastro/astro/commit/410428672ed97bba7ca0b3352c1a7ee564921462), [`763ff2d1e`](https://github.com/withastro/astro/commit/763ff2d1e44f54b899d7c65386f1b4b877c95737), [`c1669c001`](https://github.com/withastro/astro/commit/c1669c0011eecfe65a459d727848c18c189a54ca), [`3d525efc9`](https://github.com/withastro/astro/commit/3d525efc95cfb2deb5d9e04856d02965d66901c9)]:
+ - astro@2.5.0
+
+## 2.2.2
+
+### Patch Changes
+
+- [#6793](https://github.com/withastro/astro/pull/6793) [`1e3873c04`](https://github.com/withastro/astro/commit/1e3873c04abab6c498c93abc06828ecd235569d4) Thanks [@andremralves](https://github.com/andremralves)! - fix: no edge functions deployed to netlify
+
+## 2.2.1
+
+### Patch Changes
+
+- [#6651](https://github.com/withastro/astro/pull/6651) [`416ceb973`](https://github.com/withastro/astro/commit/416ceb9730ce604cd3f73c22200907d9b9978073) Thanks [@matthewp](https://github.com/matthewp)! - Use Deno API to set Astro.clientAddress in Netlify Edge
+
+- Updated dependencies [[`72fed684a`](https://github.com/withastro/astro/commit/72fed684a35f00d80c69bcf6e8af297fed0294fe), [`45bff6fcc`](https://github.com/withastro/astro/commit/45bff6fccb3f5c71ff24c1ceb48cd532196c90f6), [`52d7a4a01`](https://github.com/withastro/astro/commit/52d7a4a011a3bb722b522fffd88c5fe9a519a196), [`9e88e0f23`](https://github.com/withastro/astro/commit/9e88e0f23c5913c07f7e3e96fa0555219ef710dc), [`fa84f1a7d`](https://github.com/withastro/astro/commit/fa84f1a7d2c290479c75199f16e8de489036d7ea), [`a98f6f418`](https://github.com/withastro/astro/commit/a98f6f418c92261a06ef79624a8c86e288c21eab), [`7f74326b7`](https://github.com/withastro/astro/commit/7f74326b762bfc174ebe8e37ae03733563e4214f)]:
+ - astro@2.2.1
+
+## 2.2.0
+
+### Minor Changes
+
+- [#6213](https://github.com/withastro/astro/pull/6213) [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated compilation settings to disable downlevelling for Node 14
+
+### Patch Changes
+
+- Updated dependencies [[`fec583909`](https://github.com/withastro/astro/commit/fec583909ab62829dc0c1600e2387979365f2b94), [`b087b83fe`](https://github.com/withastro/astro/commit/b087b83fe266c431fe34a07d5c2293cc4ab011c6), [`694918a56`](https://github.com/withastro/astro/commit/694918a56b01104831296be0c25456135a63c784), [`a20610609`](https://github.com/withastro/astro/commit/a20610609863ae3b48afe96819b8f11ae4f414d5), [`a4a74ab70`](https://github.com/withastro/astro/commit/a4a74ab70cd2aa0d812a1f6b202c4e240a8913bf), [`75921b3cd`](https://github.com/withastro/astro/commit/75921b3cd916d439f6392c487c21532fde35ed13), [`afbbc4d5b`](https://github.com/withastro/astro/commit/afbbc4d5bfafc1779bac00b41c2a1cb1c90f2808)]:
+ - astro@2.1.0
+ - @astrojs/webapi@2.1.0
+
+## 2.1.3
+
+### Patch Changes
+
+- [#6323](https://github.com/withastro/astro/pull/6323) [`5e26bc891`](https://github.com/withastro/astro/commit/5e26bc891cbebb3598acfa760c135a25c548d624) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Updated Undici to 5.20.0. This fixes a security issue and handling of cookies in certain cases in dev
+
+- [#6317](https://github.com/withastro/astro/pull/6317) [`2eb73cb9d`](https://github.com/withastro/astro/commit/2eb73cb9d1c982df5f8788ddacd634645643c5c6) Thanks [@bluwy](https://github.com/bluwy)! - Use .mjs extension when building to support CJS environments
+
+- Updated dependencies [[`5e26bc891`](https://github.com/withastro/astro/commit/5e26bc891cbebb3598acfa760c135a25c548d624), [`a156ecbb7`](https://github.com/withastro/astro/commit/a156ecbb7f4df6a46124a9a12eb712f9163db2ed), [`ccd72e6bb`](https://github.com/withastro/astro/commit/ccd72e6bb41e570d42b1b158e8124c8e04a1943d), [`504c7bacb`](https://github.com/withastro/astro/commit/504c7bacb8c1f2308a31e6c412825ba34983ba33), [`63dda6ded`](https://github.com/withastro/astro/commit/63dda6dedd4c6ea1d5ce72e9cf3fe5f88339a927), [`f91a7f376`](https://github.com/withastro/astro/commit/f91a7f376c223f18b4d8fbed81f95f6bea1cef8d)]:
+ - astro@2.0.15
+
+## 2.1.2
+
+### Patch Changes
+
+- [#6117](https://github.com/withastro/astro/pull/6117) [`32abe49bd`](https://github.com/withastro/astro/commit/32abe49bd073417b480b1b990f432a837c12eb6f) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix polyfills not being available in certain cases
+
+- Updated dependencies [[`f6fc662c3`](https://github.com/withastro/astro/commit/f6fc662c3c59d164584c6287a930fcd1c9086ee6), [`592386b75`](https://github.com/withastro/astro/commit/592386b75541f3b7f7d95c631f86024b7e2d314d), [`1b591a143`](https://github.com/withastro/astro/commit/1b591a1431b44eacd239ed8f76809916cabca1db), [`bf8d7366a`](https://github.com/withastro/astro/commit/bf8d7366acb57e1b21181cc40fff55a821d8119e), [`ec38a8921`](https://github.com/withastro/astro/commit/ec38a8921f02a275949abcababe1b8afdf8184a2), [`f20a85b64`](https://github.com/withastro/astro/commit/f20a85b642994f240d8c94260fc55ffa1fd14294), [`9f22ac3d0`](https://github.com/withastro/astro/commit/9f22ac3d097ef2cb3b2bbe5343b8a8a49d83425d), [`cee70f5c6`](https://github.com/withastro/astro/commit/cee70f5c6ac9b0d2edc1f8a6f8f5043605576026), [`ac7fb04d6`](https://github.com/withastro/astro/commit/ac7fb04d6b162f28a337918138d5737e2c0fffad), [`d1f5611fe`](https://github.com/withastro/astro/commit/d1f5611febfd020cca4078c71bafe599015edd16), [`2189170be`](https://github.com/withastro/astro/commit/2189170be523f74f244e84ccab22c655219773ce), [`32abe49bd`](https://github.com/withastro/astro/commit/32abe49bd073417b480b1b990f432a837c12eb6f)]:
+ - astro@2.0.7
+
+## 2.1.1
+
+### Patch Changes
+
+- [#6090](https://github.com/withastro/astro/pull/6090) [`97a97196f`](https://github.com/withastro/astro/commit/97a97196fc4d2dd8ced838ddbca17a587cfa0957) Thanks [@matthewp](https://github.com/matthewp)! - Fix Netlify Function regression
+
+## 2.1.0
+
+### Minor Changes
+
+- [#5874](https://github.com/withastro/astro/pull/5874) [`1c230f103`](https://github.com/withastro/astro/commit/1c230f10373ec392b6cdcd5c196ae932f89033aa) Thanks [@juanmiguelguerrero](https://github.com/juanmiguelguerrero)! - Add `builders` config option for Netlify On-demand Builders.
+
+### Patch Changes
+
+- Updated dependencies [[`b4432cd6b`](https://github.com/withastro/astro/commit/b4432cd6b65bad685a99fe15867710b0663c13b2), [`98a4a914b`](https://github.com/withastro/astro/commit/98a4a914bc47f3da2764b3bdc01577d25fe2e261), [`071e1dee7`](https://github.com/withastro/astro/commit/071e1dee7e1943be67d1ded39a9af1b7a2aafd02), [`322e059d0`](https://github.com/withastro/astro/commit/322e059d0da9ab0d6a546a111fabda755bd5f1b6), [`b994f6f35`](https://github.com/withastro/astro/commit/b994f6f35e29b2d93ff8ddc281a69c0af3cc3edf), [`12c68343c`](https://github.com/withastro/astro/commit/12c68343c0aa891037d39d3c9b9378b004be6642)]:
+ - astro@2.0.3
+
+## 2.0.0
+
+### Major Changes
+
+- [#5584](https://github.com/withastro/astro/pull/5584) [`9963c6e4d`](https://github.com/withastro/astro/commit/9963c6e4d50c392c3d1ac4492237020f15ccb1de) & [#5842](https://github.com/withastro/astro/pull/5842) [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481) Thanks [@wulinsheng123](https://github.com/wulinsheng123) and [@natemoo-re](https://github.com/natemoo-re)! - **Breaking Change**: client assets are built to an `_astro` directory in the build output directory. Previously these were built to various locations, including `assets/`, `chunks/` and the root of build output.
+
+ You can control this location with the new `build` configuration option named `assets`.
+
+- [#5707](https://github.com/withastro/astro/pull/5707) [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b) Thanks [@bluwy](https://github.com/bluwy)! - Remove `astro:build:start` backwards compatibility code
+
+- [#5806](https://github.com/withastro/astro/pull/5806) [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53) Thanks [@matthewp](https://github.com/matthewp)! - Make astro a peerDependency of integrations
+
+ This marks `astro` as a peerDependency of several packages that are already getting `major` version bumps. This is so we can more properly track the dependency between them and what version of Astro they are being used with.
+
+### Patch Changes
+
+- [#5768](https://github.com/withastro/astro/pull/5768) [`2f6745019`](https://github.com/withastro/astro/commit/2f6745019ac25785032ac3659c2433b6e224f383) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix set-cookies not working in certain cases when using Node 18+
+
+- [#5904](https://github.com/withastro/astro/pull/5904) [`f5adbd6b5`](https://github.com/withastro/astro/commit/f5adbd6b55ca13a7523dff2cfc5dccdab9980fa7) Thanks [@matthewp](https://github.com/matthewp)! - Support prerender in \_redirects
+
+- [#5885](https://github.com/withastro/astro/pull/5885) [`8f1ae06e5`](https://github.com/withastro/astro/commit/8f1ae06e58f37c7d9e3b9076268b6e91546bdc07) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix issue with prerendered pages when using `edge-functions` adapter
+
+- Updated dependencies [[`93e633922`](https://github.com/withastro/astro/commit/93e633922c2e449df3bb2357b3683af1d3c0e07b), [`16dc36a87`](https://github.com/withastro/astro/commit/16dc36a870df47a4151a8ed2d91d0bd1bb812458), [`01f3f463b`](https://github.com/withastro/astro/commit/01f3f463bf2918b310d130a9fabbf3ee21d14029), [`e2019be6f`](https://github.com/withastro/astro/commit/e2019be6ffa46fa33d92cfd346f9ecbe51bb7144), [`05caf445d`](https://github.com/withastro/astro/commit/05caf445d4d2728f1010aeb2179a9e756c2fd17d), [`49ab4f231`](https://github.com/withastro/astro/commit/49ab4f231c23b34891c3ee86f4b92bf8d6d267a3), [`a342a486c`](https://github.com/withastro/astro/commit/a342a486c2831461e24e6c2f1ca8a9d3e15477b6), [`8fb28648f`](https://github.com/withastro/astro/commit/8fb28648f66629741cb976bfe34ccd9d8f55661e), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`c2180746b`](https://github.com/withastro/astro/commit/c2180746b4f6d9ef1b6f86924f21f52cc6ab4e63), [`ae8a012a7`](https://github.com/withastro/astro/commit/ae8a012a7b6884a03c50494332ee37b4505c2c3b), [`cf2de5422`](https://github.com/withastro/astro/commit/cf2de5422c26bfdea4c75f76e57b57299ded3e3a), [`ce5c5dbd4`](https://github.com/withastro/astro/commit/ce5c5dbd46afbe738b03600758bf5c35113de522), [`ec09bb664`](https://github.com/withastro/astro/commit/ec09bb6642064dbd7d2f3369afb090363ae18de2), [`665a2c222`](https://github.com/withastro/astro/commit/665a2c2225e42881f5a9550599e8f3fc1deea0b4), [`259a539d7`](https://github.com/withastro/astro/commit/259a539d7d70c783330c797794b15716921629cf), [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a), [`4987d6f44`](https://github.com/withastro/astro/commit/4987d6f44cfd0d81d88f21f5c380503403dc1e6a), [`304823811`](https://github.com/withastro/astro/commit/304823811eddd8e72aa1d8e2d39b40ab5cda3565), [`302e0ef8f`](https://github.com/withastro/astro/commit/302e0ef8f5d5232e3348afe680e599f3e537b5c5), [`55cea0a9d`](https://github.com/withastro/astro/commit/55cea0a9d8c8df91a46590fc04a9ac28089b3432), [`dd56c1941`](https://github.com/withastro/astro/commit/dd56c19411b126439b8bc42d681b6fa8c06e8c61), [`9963c6e4d`](https://github.com/withastro/astro/commit/9963c6e4d50c392c3d1ac4492237020f15ccb1de), [`46ecd5de3`](https://github.com/withastro/astro/commit/46ecd5de34df619e2ee73ccea39a57acd37bc0b8), [`be901dc98`](https://github.com/withastro/astro/commit/be901dc98c4a7f6b5536540aa8f7ba5108e939a0), [`f6cf92b48`](https://github.com/withastro/astro/commit/f6cf92b48317a19a3840ad781b77d6d3cae143bb), [`e818cc046`](https://github.com/withastro/astro/commit/e818cc0466a942919ea3c41585e231c8c80cb3d0), [`8c100a6fe`](https://github.com/withastro/astro/commit/8c100a6fe6cc652c3799d1622e12c2c969f30510), [`116d8835c`](https://github.com/withastro/astro/commit/116d8835ca9e78f8b5e477ee5a3d737b69f80706), [`840412128`](https://github.com/withastro/astro/commit/840412128b00a04515156e92c314a929d6b94f6d), [`1f49cddf9`](https://github.com/withastro/astro/commit/1f49cddf9e9ffc651efc171b2cbde9fbe9e8709d), [`7325df412`](https://github.com/withastro/astro/commit/7325df412107fc0e65cd45c1b568fb686708f723), [`16c7d0bfd`](https://github.com/withastro/astro/commit/16c7d0bfd49d2b9bfae45385f506bcd642f9444a), [`c55fbcb8e`](https://github.com/withastro/astro/commit/c55fbcb8edca1fe118a44f68c9f9436a4719d171), [`a9c292026`](https://github.com/withastro/astro/commit/a9c2920264e36cc5dc05f4adc1912187979edb0d), [`2a5786419`](https://github.com/withastro/astro/commit/2a5786419599b8674473c699300172b9aacbae2e), [`4a1cabfe6`](https://github.com/withastro/astro/commit/4a1cabfe6b9ef8a6fbbcc0727a0dc6fa300cedaa), [`a8d3e7924`](https://github.com/withastro/astro/commit/a8d3e79246605d252dcddad159e358e2d79bd624), [`fa8c131f8`](https://github.com/withastro/astro/commit/fa8c131f88ef67d14c62f1c00c97ed74d43a80ac), [`64b8082e7`](https://github.com/withastro/astro/commit/64b8082e776b832f1433ed288e6f7888adb626d0), [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`23dc9ea96`](https://github.com/withastro/astro/commit/23dc9ea96a10343852d965efd41fe6665294f1fb), [`63a6ceb38`](https://github.com/withastro/astro/commit/63a6ceb38d88331451dca64d0034c7c58e3d26f1), [`a3a7fc929`](https://github.com/withastro/astro/commit/a3a7fc9298e6d88abb4b7bee1e58f05fa9558cf1), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`5fd9208d4`](https://github.com/withastro/astro/commit/5fd9208d447f5ab8909a2188b6c2491a0debd49d), [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b), [`899214298`](https://github.com/withastro/astro/commit/899214298cee5f0c975c7245e623c649e1842d73), [`3a00ecb3e`](https://github.com/withastro/astro/commit/3a00ecb3eb4bc44be758c064f2bde6e247e8a593), [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b), [`2303f9514`](https://github.com/withastro/astro/commit/2303f95142aa740c99213a098f82b99dd37d74a0), [`1ca81c16b`](https://github.com/withastro/astro/commit/1ca81c16b8b66236e092e6eb6ec3f73f5668421c), [`b66d7195c`](https://github.com/withastro/astro/commit/b66d7195c17a55ea0931bc3744888bd4f5f01ce6)]:
+ - astro@2.0.0
+ - @astrojs/webapi@2.0.0
+
+## 2.0.0-beta.4
+
+### Patch Changes
+
+- [#5904](https://github.com/withastro/astro/pull/5904) [`f5adbd6b5`](https://github.com/withastro/astro/commit/f5adbd6b55ca13a7523dff2cfc5dccdab9980fa7) Thanks [@matthewp](https://github.com/matthewp)! - Support prerender in \_redirects
+
+- Updated dependencies [[`4987d6f44`](https://github.com/withastro/astro/commit/4987d6f44cfd0d81d88f21f5c380503403dc1e6a), [`304823811`](https://github.com/withastro/astro/commit/304823811eddd8e72aa1d8e2d39b40ab5cda3565), [`46ecd5de3`](https://github.com/withastro/astro/commit/46ecd5de34df619e2ee73ccea39a57acd37bc0b8), [`7325df412`](https://github.com/withastro/astro/commit/7325df412107fc0e65cd45c1b568fb686708f723), [`a8d3e7924`](https://github.com/withastro/astro/commit/a8d3e79246605d252dcddad159e358e2d79bd624), [`5fd9208d4`](https://github.com/withastro/astro/commit/5fd9208d447f5ab8909a2188b6c2491a0debd49d)]:
+ - astro@2.0.0-beta.4
+ - @astrojs/webapi@2.0.0-beta.1
+
+## 2.0.0-beta.3
+
+### Patch Changes
+
+- [#5885](https://github.com/withastro/astro/pull/5885) [`8f1ae06e5`](https://github.com/withastro/astro/commit/8f1ae06e58f37c7d9e3b9076268b6e91546bdc07) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fix issue with prerendered pages when using `edge-functions` adapter
+
+- Updated dependencies [[`16dc36a87`](https://github.com/withastro/astro/commit/16dc36a870df47a4151a8ed2d91d0bd1bb812458), [`05caf445d`](https://github.com/withastro/astro/commit/05caf445d4d2728f1010aeb2179a9e756c2fd17d), [`a342a486c`](https://github.com/withastro/astro/commit/a342a486c2831461e24e6c2f1ca8a9d3e15477b6), [`ce5c5dbd4`](https://github.com/withastro/astro/commit/ce5c5dbd46afbe738b03600758bf5c35113de522), [`be901dc98`](https://github.com/withastro/astro/commit/be901dc98c4a7f6b5536540aa8f7ba5108e939a0), [`e818cc046`](https://github.com/withastro/astro/commit/e818cc0466a942919ea3c41585e231c8c80cb3d0), [`8c100a6fe`](https://github.com/withastro/astro/commit/8c100a6fe6cc652c3799d1622e12c2c969f30510), [`64b8082e7`](https://github.com/withastro/astro/commit/64b8082e776b832f1433ed288e6f7888adb626d0), [`899214298`](https://github.com/withastro/astro/commit/899214298cee5f0c975c7245e623c649e1842d73), [`3a00ecb3e`](https://github.com/withastro/astro/commit/3a00ecb3eb4bc44be758c064f2bde6e247e8a593), [`1ca81c16b`](https://github.com/withastro/astro/commit/1ca81c16b8b66236e092e6eb6ec3f73f5668421c), [`b66d7195c`](https://github.com/withastro/astro/commit/b66d7195c17a55ea0931bc3744888bd4f5f01ce6)]:
+ - astro@2.0.0-beta.3
+
+## 2.0.0-beta.2
+
+### Major Changes
+
+- [#5842](https://github.com/withastro/astro/pull/5842) [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481) Thanks [@natemoo-re](https://github.com/natemoo-re)! - **Breaking Change**: client assets are built to an `_astro` directory in the build output directory. Previously these were built to various locations, including `assets/`, `chunks/` and the root of build output.
+
+ You can control this location with the new `build` configuration option named `assets`.
+
+- [#5806](https://github.com/withastro/astro/pull/5806) [`7572f7402`](https://github.com/withastro/astro/commit/7572f7402238da37de748be58d678fedaf863b53) Thanks [@matthewp](https://github.com/matthewp)! - Make astro a peerDependency of integrations
+
+ This marks `astro` as a peerDependency of several packages that are already getting `major` version bumps. This is so we can more properly track the dependency between them and what version of Astro they are being used with.
+
+### Patch Changes
+
+- Updated dependencies [[`01f3f463b`](https://github.com/withastro/astro/commit/01f3f463bf2918b310d130a9fabbf3ee21d14029), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`c2180746b`](https://github.com/withastro/astro/commit/c2180746b4f6d9ef1b6f86924f21f52cc6ab4e63), [`ae8a012a7`](https://github.com/withastro/astro/commit/ae8a012a7b6884a03c50494332ee37b4505c2c3b), [`cf2de5422`](https://github.com/withastro/astro/commit/cf2de5422c26bfdea4c75f76e57b57299ded3e3a), [`ec09bb664`](https://github.com/withastro/astro/commit/ec09bb6642064dbd7d2f3369afb090363ae18de2), [`665a2c222`](https://github.com/withastro/astro/commit/665a2c2225e42881f5a9550599e8f3fc1deea0b4), [`f7aa1ec25`](https://github.com/withastro/astro/commit/f7aa1ec25d1584f7abd421903fbef66b1c050e2a), [`302e0ef8f`](https://github.com/withastro/astro/commit/302e0ef8f5d5232e3348afe680e599f3e537b5c5), [`840412128`](https://github.com/withastro/astro/commit/840412128b00a04515156e92c314a929d6b94f6d), [`1f49cddf9`](https://github.com/withastro/astro/commit/1f49cddf9e9ffc651efc171b2cbde9fbe9e8709d), [`c55fbcb8e`](https://github.com/withastro/astro/commit/c55fbcb8edca1fe118a44f68c9f9436a4719d171), [`4a1cabfe6`](https://github.com/withastro/astro/commit/4a1cabfe6b9ef8a6fbbcc0727a0dc6fa300cedaa), [`c4b0cb8bf`](https://github.com/withastro/astro/commit/c4b0cb8bf2b41887d9106440bb2e70d421a5f481), [`1f92d64ea`](https://github.com/withastro/astro/commit/1f92d64ea35c03fec43aff64eaf704dc5a9eb30a), [`23dc9ea96`](https://github.com/withastro/astro/commit/23dc9ea96a10343852d965efd41fe6665294f1fb), [`63a6ceb38`](https://github.com/withastro/astro/commit/63a6ceb38d88331451dca64d0034c7c58e3d26f1), [`52209ca2a`](https://github.com/withastro/astro/commit/52209ca2ad72a30854947dcb3a90ab4db0ac0a6f), [`2303f9514`](https://github.com/withastro/astro/commit/2303f95142aa740c99213a098f82b99dd37d74a0)]:
+ - astro@2.0.0-beta.2
+ - @astrojs/webapi@2.0.0-beta.0
+
+## 2.0.0-beta.1
+
+### Patch Changes
+
+- [#5768](https://github.com/withastro/astro/pull/5768) [`2f6745019`](https://github.com/withastro/astro/commit/2f6745019ac25785032ac3659c2433b6e224f383) Thanks [@Princesseuh](https://github.com/Princesseuh)! - Fix set-cookies not working in certain cases when using Node 18+
+
+## 2.0.0-beta.0
+
+### Major Changes
+
+- [#5707](https://github.com/withastro/astro/pull/5707) [`5eba34fcc`](https://github.com/withastro/astro/commit/5eba34fcc663def20bdf6e0daad02a6a5472776b) Thanks [@bluwy](https://github.com/bluwy)! - Remove `astro:build:start` backwards compatibility code
+
+## 1.3.0
+
+### Minor Changes
+
+- [#5297](https://github.com/withastro/astro/pull/5297) [`d2960984c`](https://github.com/withastro/astro/commit/d2960984c59af7b60a3ea472c6c58fb00534a8e6) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Introduces the **experimental** Prerender API.
+
+ > **Note**
+ > This API is not yet stable and is subject to possible breaking changes!
+
+ - Deploy an Astro server without sacrificing the speed or cacheability of static HTML.
+ - The Prerender API allows you to statically prerender specific `pages/` at build time.
+
+ **Usage**
+
+ - First, run `astro build --experimental-prerender` or enable `experimental: { prerender: true }` in your `astro.config.mjs` file.
+ - Then, include `export const prerender = true` in any file in the `pages/` directory that you wish to prerender.
+
+## 1.2.2
+
+### Patch Changes
+
+- [#5534](https://github.com/withastro/astro/pull/5534) [`fabd9124b`](https://github.com/withastro/astro/commit/fabd9124bd3e654e885054f30e9c0d01eabf0470) Thanks [@bluwy](https://github.com/bluwy)! - Update esbuild dependency
+
+## 1.2.1
+
+### Patch Changes
+
+- [#5301](https://github.com/withastro/astro/pull/5301) [`a79a37cad`](https://github.com/withastro/astro/commit/a79a37cad549b21f91599ff86899e456d9dcc7df) Thanks [@bluwy](https://github.com/bluwy)! - Fix environment variables usage in edge functions
+
+## 1.2.0
+
+### Minor Changes
+
+- [#5056](https://github.com/withastro/astro/pull/5056) [`e55af8a23`](https://github.com/withastro/astro/commit/e55af8a23233b6335f45b7a04b9d026990fb616c) Thanks [@matthewp](https://github.com/matthewp)! - # New build configuration
+
+ The ability to customize SSR build configuration more granularly is now available in Astro. You can now customize the output folder for `server` (the server code for SSR), `client` (your client-side JavaScript and assets), and `serverEntry` (the name of the entrypoint server module). Here are the defaults:
+
+ ```js
+ import { defineConfig } from 'astro/config';
+
+ export default defineConfig({
+ output: 'server',
+ build: {
+ server: './dist/server/',
+ client: './dist/client/',
+ serverEntry: 'entry.mjs',
+ },
+ });
+ ```
+
+ These new configuration options are only supported in SSR mode and are ignored when building to SSG (a static site).
+
+ ## Integration hook change
+
+ The integration hook `astro:build:start` includes a param `buildConfig` which includes all of these same options. You can continue to use this param in Astro 1.x, but it is deprecated in favor of the new `build.config` options. All of the built-in adapters have been updated to the new format. If you have an integration that depends on this param we suggest upgrading to do this instead:
+
+ ```js
+ export default function myIntegration() {
+ return {
+ name: 'my-integration',
+ hooks: {
+ 'astro:config:setup': ({ updateConfig }) => {
+ updateConfig({
+ build: {
+ server: '...',
+ },
+ });
+ },
+ },
+ };
+ }
+ ```
+
+## 1.1.0
+
+### Minor Changes
+
+- [#4876](https://github.com/withastro/astro/pull/4876) [`d3091f89e`](https://github.com/withastro/astro/commit/d3091f89e92fcfe1ad48daca74055d54b1c853a3) Thanks [@matthewp](https://github.com/matthewp)! - Adds the Astro.cookies API
+
+ `Astro.cookies` is a new API for manipulating cookies in Astro components and API routes.
+
+ In Astro components, the new `Astro.cookies` object is a map-like object that allows you to get, set, delete, and check for a cookie's existence (`has`):
+
+ ```astro
+ ---
+ type Prefs = {
+ darkMode: boolean;
+ };
+
+ Astro.cookies.set(
+ 'prefs',
+ { darkMode: true },
+ {
+ expires: '1 month',
+ }
+ );
+
+ const prefs = Astro.cookies.get('prefs').json();
+ ---
+
+
+ ```
+
+ Once you've set a cookie with Astro.cookies it will automatically be included in the outgoing response.
+
+ This API is also available with the same functionality in API routes:
+
+ ```js
+ export function post({ cookies }) {
+ cookies.set('loggedIn', false);
+
+ return new Response(null, {
+ status: 302,
+ headers: {
+ Location: '/login',
+ },
+ });
+ }
+ ```
+
+ See [the RFC](https://github.com/withastro/rfcs/blob/main/proposals/0025-cookie-management.md) to learn more.
+
+### Patch Changes
+
+- [#4842](https://github.com/withastro/astro/pull/4842) [`812658ad2`](https://github.com/withastro/astro/commit/812658ad2ab3732a99e35c4fd903e302e723db46) Thanks [@bluwy](https://github.com/bluwy)! - Add missing dependencies, support strict dependency installation (e.g. pnpm)
+
+## 1.0.4
+
+### Patch Changes
+
+- [#4820](https://github.com/withastro/astro/pull/4820) [`9bfbd63f0`](https://github.com/withastro/astro/commit/9bfbd63f05d21b51f7fd726fc4c16949919529a0) Thanks [@matthewp](https://github.com/matthewp)! - Fix processing of images in Netlify Functions
+
+## 1.0.3
+
+### Patch Changes
+
+- [#4722](https://github.com/withastro/astro/pull/4722) [`4bc70f354`](https://github.com/withastro/astro/commit/4bc70f3545ab950da306de9c5417a08a7532fa28) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix route validation failures on Netlify Edge
+
+## 1.0.2
+
+### Patch Changes
+
+- [#4558](https://github.com/withastro/astro/pull/4558) [`742966456`](https://github.com/withastro/astro/commit/7429664566f05ecebf6d57906f950627e62e690c) Thanks [@tony-sull](https://github.com/tony-sull)! - Adding the `withastro` keyword to include the adapters on the [Integrations Catalog](https://astro.build/integrations)
+
+## 1.0.1
+
+### Patch Changes
+
+- [#4274](https://github.com/withastro/astro/pull/4274) [`d3d09a2c9`](https://github.com/withastro/astro/commit/d3d09a2c9f1af4dc467783c8bf4a71800924d129) Thanks [@matthewp](https://github.com/matthewp)! - Adds 404 routing logic to Netlify redirects file
+
+## 1.0.0
+
+### Major Changes
+
+- [`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308) - > Astro v1.0 is out! Read the [official announcement post](https://astro.build/blog/astro-1/).
+
+ **No breaking changes**. This package is now officially stable and compatible with `astro@1.0.0`!
+
+### Patch Changes
+
+- Updated dependencies [[`04ad44563`](https://github.com/withastro/astro/commit/04ad445632c67bdd60c1704e1e0dcbcaa27b9308)]:
+ - @astrojs/webapi@1.0.0
+
+## 0.5.0
+
+### Minor Changes
+
+- [#4015](https://github.com/withastro/astro/pull/4015) [`6fd161d76`](https://github.com/withastro/astro/commit/6fd161d7691cbf9d3ffa4646e46059dfd0940010) Thanks [@matthewp](https://github.com/matthewp)! - New `output` configuration option
+
+ This change introduces a new "output target" configuration option (`output`). Setting the output target lets you decide the format of your final build, either:
+
+ - `"static"` (default): A static site. Your final build will be a collection of static assets (HTML, CSS, JS) that you can deploy to any static site host.
+ - `"server"`: A dynamic server application. Your final build will be an application that will run in a hosted server environment, generating HTML dynamically for different requests.
+
+ If `output` is omitted from your config, the default value `"static"` will be used.
+
+ When using the `"server"` output target, you must also include a runtime adapter via the `adapter` configuration. An adapter will _adapt_ your final build to run on the deployed platform of your choice (Netlify, Vercel, Node.js, Deno, etc).
+
+ To migrate: No action is required for most users. If you currently define an `adapter`, you will need to also add `output: 'server'` to your config file to make it explicit that you are building a server. Here is an example of what that change would look like for someone deploying to Netlify:
+
+ ```diff
+ import { defineConfig } from 'astro/config';
+ import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ adapter: netlify(),
+ + output: 'server',
+ });
+ ```
+
+* [#4018](https://github.com/withastro/astro/pull/4018) [`0cc6ede36`](https://github.com/withastro/astro/commit/0cc6ede362996b9faba57481a790d6eb7fba2045) Thanks [@okikio](https://github.com/okikio)! - Support for 404 and 500 pages in SSR
+
+- [#3973](https://github.com/withastro/astro/pull/3973) [`5a23483ef`](https://github.com/withastro/astro/commit/5a23483efb3ba614b05a00064f84415620605204) Thanks [@matthewp](https://github.com/matthewp)! - Adds support for Astro.clientAddress
+
+ The new `Astro.clientAddress` property allows you to get the IP address of the requested user.
+
+ ```astro
+
+ ```
+
+ This property is only available when building for SSR, and only if the adapter you are using supports providing the IP address. If you attempt to access the property in a SSG app it will throw an error.
+
+## 0.4.10
+
+### Patch Changes
+
+- [#3885](https://github.com/withastro/astro/pull/3885) [`bf5d1cc1e`](https://github.com/withastro/astro/commit/bf5d1cc1e71da38a14658c615e9481f2145cc6e7) Thanks [@delucis](https://github.com/delucis)! - Integration README fixes
+
+## 0.4.9
+
+### Patch Changes
+
+- [#3865](https://github.com/withastro/astro/pull/3865) [`1f9e4857`](https://github.com/withastro/astro/commit/1f9e4857ff2b2cb7db89d619618cdf546cd3b3dc) Thanks [@delucis](https://github.com/delucis)! - Small README fixes
+
+* [#3854](https://github.com/withastro/astro/pull/3854) [`b012ee55`](https://github.com/withastro/astro/commit/b012ee55b107dea0730286263b27d83e530fad5d) Thanks [@bholmesdev](https://github.com/bholmesdev)! - [astro add] Support adapters and third party packages
+
+## 0.4.8
+
+### Patch Changes
+
+- [#3677](https://github.com/withastro/astro/pull/3677) [`8045c8ad`](https://github.com/withastro/astro/commit/8045c8ade16fe4306448b7f98a4560ef0557d378) Thanks [@Jutanium](https://github.com/Jutanium)! - Update READMEs
+
+## 0.4.7
+
+### Patch Changes
+
+- [#3734](https://github.com/withastro/astro/pull/3734) [`4acd245d`](https://github.com/withastro/astro/commit/4acd245d8f59871eb9c0083ae1a0fe7aa70c84f5) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: append shim to top of built file to avoid "can't read process of undefined" issues
+
+## 0.4.6
+
+### Patch Changes
+
+- [#3673](https://github.com/withastro/astro/pull/3673) [`ba5ad785`](https://github.com/withastro/astro/commit/ba5ad7855c4252e10e76b41b88fd4c74b4b7295b) Thanks [@hippotastic](https://github.com/hippotastic)! - Fix react dependencies to improve test reliability
+
+## 0.4.5
+
+### Patch Changes
+
+- [#3612](https://github.com/withastro/astro/pull/3612) [`fca58cfd`](https://github.com/withastro/astro/commit/fca58cfd91b68501ec82350ab023170b208d8ce7) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: "vpath" import error when building for netlify edge
+
+## 0.4.4
+
+### Patch Changes
+
+- [#3592](https://github.com/withastro/astro/pull/3592) [`0ddcef20`](https://github.com/withastro/astro/commit/0ddcef2043e3c2f65aaeec7a969c374c053e22f3) Thanks [@tony-sull](https://github.com/tony-sull)! - Adds support for base64 encoded responses in Netlify Functions
+
+## 0.4.3
+
+### Patch Changes
+
+- [#3535](https://github.com/withastro/astro/pull/3535) [`f3ab822e`](https://github.com/withastro/astro/commit/f3ab822e328725c3905b0adad9889ad37653c24a) Thanks [@matthewp](https://github.com/matthewp)! - Fixes Netlify Edge Function and Astro.glob
+
+## 0.4.2
+
+### Patch Changes
+
+- [#3503](https://github.com/withastro/astro/pull/3503) [`207f58d1`](https://github.com/withastro/astro/commit/207f58d1715ac024cc7c81b76e26aa49fca5173f) Thanks [@williamtetlow](https://github.com/williamtetlow)! - Alias `from 'astro'` imports to `'@astro/types'`
+ Update Deno and Netlify integrations to handle vite.resolves.alias as an array
+
+## 0.4.1
+
+### Patch Changes
+
+- Updated dependencies [[`4de53ecc`](https://github.com/withastro/astro/commit/4de53eccef346bed843b491b7ab93987d7d85655)]:
+ - @astrojs/webapi@0.12.0
+
+## 0.4.0
+
+### Minor Changes
+
+- [#3381](https://github.com/withastro/astro/pull/3381) [`43d92227`](https://github.com/withastro/astro/commit/43d922277afaeca9c90364fbf0b19477fd2c6566) Thanks [@sarahetter](https://github.com/sarahetter)! - Updating out directories for Netlify Functions
+
+* [#3377](https://github.com/withastro/astro/pull/3377) [`e1294c42`](https://github.com/withastro/astro/commit/e1294c422b3d3e98ccc745fe95d5672c9a17fe1f) Thanks [@sarahetter](https://github.com/sarahetter)! - Change out directories on dist and serverEntry
+
+## 0.3.4
+
+### Patch Changes
+
+- [#3342](https://github.com/withastro/astro/pull/3342) [`352fc316`](https://github.com/withastro/astro/commit/352fc3166fe3b3d3da3feff621394b20eacb9cc3) Thanks [@thepassle](https://github.com/thepassle)! - create redirects file for netlify edge adapter
+
+## 0.3.3
+
+### Patch Changes
+
+- [#3170](https://github.com/withastro/astro/pull/3170) [`19667c45`](https://github.com/withastro/astro/commit/19667c45f318ec13cdc2b51016f3fa3487b2a32d) Thanks [@matthewp](https://github.com/matthewp)! - Netlify Edge: Forward requests for static assets
+
+## 0.3.2
+
+### Patch Changes
+
+- [#3160](https://github.com/withastro/astro/pull/3160) [`ae9ac5cb`](https://github.com/withastro/astro/commit/ae9ac5cbdceba0687d83d56d9d5f80479ab88710) Thanks [@matthewp](https://github.com/matthewp)! - Allows using React.lazy, Suspense in SSR and with hydration
+
+## 0.3.1
+
+### Patch Changes
+
+- [#3150](https://github.com/withastro/astro/pull/3150) [`05cf1a50`](https://github.com/withastro/astro/commit/05cf1a506702f06ed48cd26cbe5ca108839ff0e6) Thanks [@matthewp](https://github.com/matthewp)! - Outputs manifest.json in correct folder for Netlify Edge Functions
+
+## 0.3.0
+
+### Minor Changes
+
+- [#3148](https://github.com/withastro/astro/pull/3148) [`4cf54c60`](https://github.com/withastro/astro/commit/4cf54c60aa63bd614b242da0602790015005673d) Thanks [@matthewp](https://github.com/matthewp)! - Adds support for Netlify Edge Functions
+
+## 0.2.3
+
+### Patch Changes
+
+- [#3092](https://github.com/withastro/astro/pull/3092) [`a5caf08e`](https://github.com/withastro/astro/commit/a5caf08e2494e9f779baa6b288d277490dd436b8) Thanks [@matthewp](https://github.com/matthewp)! - Fixes setting multiple cookies with the Netlify adapter
+
+## 0.2.2
+
+### Patch Changes
+
+- [#3079](https://github.com/withastro/astro/pull/3079) [`9f248b05`](https://github.com/withastro/astro/commit/9f248b0563828db0e01e685aac177eaf8107906e) Thanks [@hippotastic](https://github.com/hippotastic)! - Make Netlify adapter actually append redirects
+
+## 0.2.1
+
+### Patch Changes
+
+- [`815d62f1`](https://github.com/withastro/astro/commit/815d62f151a36fef7d09590d4962ca71bda61b32) Thanks [@FredKSchott](https://github.com/FredKSchott)! - no changes.
+
+## 0.2.0
+
+### Minor Changes
+
+- [`732ea388`](https://github.com/withastro/astro/commit/732ea3881e216f0e6de3642c549afd019d32409f) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Improve the Netlify adapter:
+
+ 1. Remove `site` config requirement
+ 2. Fix an issue where query params were being stripped
+ 3. Pass the event body to the request object
+
+### Patch Changes
+
+- [#2996](https://github.com/withastro/astro/pull/2996) [`77aa3a5c`](https://github.com/withastro/astro/commit/77aa3a5c504c5f51ed1c4d2c8abc4997397deec2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add human-readable error when a site is not provided in your astro.config
+
+* [#3011](https://github.com/withastro/astro/pull/3011) [`c6f8bce7`](https://github.com/withastro/astro/commit/c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e) Thanks [@matthewp](https://github.com/matthewp)! - Fixes dynamic routes in the Netlify adapter
+
+## 0.1.1-beta.1
+
+### Patch Changes
+
+- [#3011](https://github.com/withastro/astro/pull/3011) [`c6f8bce7`](https://github.com/withastro/astro/commit/c6f8bce7c35cc4fd450fe1b6cc8297a81e413b8e) Thanks [@matthewp](https://github.com/matthewp)! - Fixes dynamic routes in the Netlify adapter
+
+## 0.1.1-beta.0
+
+### Patch Changes
+
+- [#2996](https://github.com/withastro/astro/pull/2996) [`77aa3a5c`](https://github.com/withastro/astro/commit/77aa3a5c504c5f51ed1c4d2c8abc4997397deec2) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Add human-readable error when a site is not provided in your astro.config
+
+## 0.1.0
+
+### Minor Changes
+
+- [`e425f896`](https://github.com/withastro/astro/commit/e425f896b668d98033ad3b998b50c1f28bc7f6ee) Thanks [@FredKSchott](https://github.com/FredKSchott)! - Update config options to respect [RFC0019](https://github.com/withastro/rfcs/blob/main/proposals/0019-config-finalization.md)
+
+## 0.0.2
+
+### Patch Changes
+
+- [#2879](https://github.com/withastro/astro/pull/2879) [`80034c6c`](https://github.com/withastro/astro/commit/80034c6cbc89761618847e6df43fd49560a05aa9) Thanks [@matthewp](https://github.com/matthewp)! - Netlify Adapter
+
+ This change adds a Netlify adapter that uses Netlify Functions. You can use it like so:
+
+ ```js
+ import { defineConfig } from 'astro/config';
+ import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ adapter: netlify(),
+ });
+ ```
diff --git a/packages/netlify/README.md b/packages/netlify/README.md
new file mode 100644
index 00000000..a313486d
--- /dev/null
+++ b/packages/netlify/README.md
@@ -0,0 +1,279 @@
+# @astrojs/netlify
+
+This adapter allows Astro to deploy your SSR site to [Netlify](https://www.netlify.com/).
+
+Learn how to deploy your Astro site in our [Netlify deployment guide](https://docs.astro.build/en/guides/deploy/netlify/).
+
+- [Why Astro Netlify](#why-astro-netlify)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Configuration](#configuration)
+- [Examples](#examples)
+- [Troubleshooting](#troubleshooting)
+- [Contributing](#contributing)
+- [Changelog](#changelog)
+
+## Why Astro Netlify
+
+If you're using Astro as a static site builder—its behavior out of the box—you don't need an adapter.
+
+If you wish to [use server-side rendering (SSR)](https://docs.astro.build/en/guides/server-side-rendering/), Astro requires an adapter that matches your deployment runtime.
+
+[Netlify](https://www.netlify.com/) is a deployment platform that allows you to host your site by connecting directly to your GitHub repository. This adapter enhances the Astro build process to prepare your project for deployment through Netlify.
+
+## Installation
+
+Add the Netlify adapter to enable SSR in your Astro project with the following `astro add` command. This will install the adapter and make the appropriate changes to your `astro.config.mjs` file in one step.
+
+```sh
+# Using NPM
+npx astro add netlify
+# Using Yarn
+yarn astro add netlify
+# Using PNPM
+pnpm astro add netlify
+```
+
+### Add dependencies manually
+
+If you prefer to install the adapter manually instead, complete the following two steps:
+
+1. Install the Netlify adapter to your project’s dependencies using your preferred package manager. If you’re using npm or aren’t sure, run this in the terminal:
+
+ ```bash
+ npm install @astrojs/netlify
+ ```
+
+1. Add two new lines to your `astro.config.mjs` project configuration file.
+
+ ```js ins={3, 6-7}
+ // astro.config.mjs
+ import { defineConfig } from 'astro/config';
+ import netlify from '@astrojs/netlify/functions';
+
+ export default defineConfig({
+ output: 'server',
+ adapter: netlify(),
+ });
+ ```
+
+### Run middleware in Edge Functions
+
+When deploying to Netlify Functions, you can choose to use an Edge Function to run your Astro middleware.
+
+To enable this, set the `edgeMiddleware` config option to `true`:
+
+```js ins={9}
+// astro.config.mjs
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ edgeMiddleware: true,
+ }),
+});
+```
+
+#### Pass edge context to your site
+
+Netlify Edge Functions provide a [context object](https://docs.netlify.com/edge-functions/api/#netlify-specific-context-object) including metadata about the request, such as a user’s IP, geolocation data, and cookies.
+
+To expose values from this context to your site, create a `netlify-edge-middleware.ts` (or `.js`) file in your project’s [source directory](https://docs.astro.build/en/reference/configuration-reference/#srcdir). This file must export a function that returns the data to add to [Astro’s `locals` object](https://docs.astro.build/en/guides/middleware/#locals), which is available in middleware and Astro routes.
+
+In this example, `visitorCountry` and `hasEdgeMiddleware` would both be added to Astro’s `locals` object:
+
+```ts
+// src/netlify-edge-middleware.ts
+import type { Context } from 'https://edge.netlify.com';
+
+export default function ({ request, context }: { request: Request; context: Context }) {
+ // Return serializable data to add to Astro.locals
+ return {
+ visitorCountry: context.geo.country.name,
+ hasEdgeMiddleware: true,
+ };
+}
+```
+
+> **Note**
+> Netlify Edge Functions run in [a Deno environment](https://docs.netlify.com/edge-functions/api/#runtime-environment), so import statements in this file must use Deno’s URL syntax.
+
+`netlify-edge-middleware.ts` must provide a function as its default export. This function:
+
+- must return a JSON-serializable object, which cannot include types like `Map`, `function`, `Set`, etc.
+- will always run first, before any other middleware and routes.
+- cannot return a response or redirect.
+
+### Per-page functions
+
+The Netlify adapter builds to a single function by default. Astro 2.7 added support for splitting your build into separate entry points per page. If you use this configuration, the Netlify adapter will generate a separate function for each page. This can help reduce the size of each function so they are only bundling code used on that page.
+
+```js
+// astro.config.mjs
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ functionPerRoute: true,
+ }),
+});
+```
+
+### Static sites
+
+For static sites you usually don't need an adapter. However, if you use `redirects` configuration in your Astro config, the Netlify adapter can be used to translate this to the proper `_redirects` format.
+
+```js
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/static';
+
+export default defineConfig({
+ adapter: netlify(),
+
+ redirects: {
+ '/blog/old-post': '/blog/new-post',
+ },
+});
+```
+
+Once you run `astro build` there will be a `dist/_redirects` file. Netlify will use that to properly route pages in production.
+
+> **Note**
+> You can still include a `public/_redirects` file for manual redirects. Any redirects you specify in the redirects config are appended to the end of your own.
+
+### On-demand Builders
+
+[Netlify On-demand Builders](https://docs.netlify.com/configure-builds/on-demand-builders/) are serverless functions used to generate web content as needed that’s automatically cached on Netlify’s Edge CDN. You can enable these functions using the [`builders` configuration](#builders).
+
+By default, all pages will be rendered on first visit and the rendered result will be reused for every subsequent visit until you redeploy. To set a revalidation time, call the [`runtime.setBuildersTtl(ttl)` local](https://docs.astro.build/en/guides/middleware/#locals) with the duration (in seconds).
+
+The following example sets a revalidation time of 45, causing Netlify to store the rendered HTML for 45 seconds.
+
+```astro
+---
+import Layout from '../components/Layout.astro';
+
+if (import.meta.env.PROD) {
+ Astro.locals.runtime.setBuildersTtl(45);
+}
+---
+
+
+ {new Date(Date.now())}
+
+```
+
+It is important to note that On-demand Builders ignore query params when checking for cached pages. For example, if `example.com/?x=y` is cached, it will be served for `example.com/?a=b` (different query params) and `example.com/` (no query params) as well.
+
+## Usage
+
+[Read the full deployment guide here.](https://docs.astro.build/en/guides/deploy/netlify/)
+
+After [performing a build](https://docs.astro.build/en/guides/deploy/#building-your-site-locally) the `netlify/` folder will contain [Netlify Functions](https://docs.netlify.com/functions/overview/) in the `netlify/functions/` folder.
+
+Now you can deploy. Install the [Netlify CLI](https://docs.netlify.com/cli/get-started/) and run:
+
+```sh
+netlify deploy --build
+```
+
+The [Netlify Blog post on Astro](https://www.netlify.com/blog/how-to-deploy-astro/) and the [Netlify Documentation](https://docs.netlify.com/integrations/frameworks/astro/) provide more information on how to use this integration to deploy to Netlify.
+
+## Configuration
+
+To configure this adapter, pass an object to the `netlify()` function call in `astro.config.mjs` - there's only one possible configuration option:
+
+### dist
+
+We build to the `dist` directory at the base of your project. To change this, use the `dist` option:
+
+```js
+// astro.config.mjs
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ dist: new URL('./dist/', import.meta.url),
+ }),
+});
+```
+
+And then point to the dist in your `netlify.toml`:
+
+```toml title="netlify.toml"
+[functions]
+directory = "dist/functions"
+```
+
+### builders
+
+You can enable On-demand Builders using the `builders` option:
+
+```js
+// astro.config.mjs
+import { defineConfig } from 'astro/config';
+import netlify from '@astrojs/netlify/functions';
+
+export default defineConfig({
+ output: 'server',
+ adapter: netlify({
+ builders: true,
+ }),
+});
+```
+
+On-demand Builders are only available with the `@astrojs/netlify/functions` adapter and are not compatible with Edge Functions.
+
+### binaryMediaTypes
+
+> This option is only needed for the Functions adapter and is not needed for Edge Functions.
+
+Netlify Functions requires binary data in the `body` to be base64 encoded. The `@astrojs/netlify/functions` adapter handles this automatically based on the `Content-Type` header.
+
+We check for common mime types for audio, image, and video files. To include specific mime types that should be treated as binary data, include the `binaryMediaTypes` option with a list of binary mime types.
+
+```js {12}
+// src/pages/image.jpg.ts
+
+import fs from 'node:fs';
+
+export function GET() {
+ const buffer = fs.readFileSync('../image.jpg');
+
+ // Return the buffer directly, @astrojs/netlify will base64 encode the body
+ return new Response(buffer, {
+ status: 200,
+ headers: {
+ 'content-type': 'image/jpeg',
+ },
+ });
+}
+```
+
+## Examples
+
+- The [Astro Netlify Edge Starter](https://github.com/sarahetter/astro-netlify-edge-starter) provides an example and a guide in the README.
+
+- [Browse Astro Netlify projects on GitHub](https://github.com/search?q=path%3A**%2Fastro.config.mjs+%40astrojs%2Fnetlify&type=code) for more examples!
+
+## Troubleshooting
+
+For help, check out the `#support` channel on [Discord](https://astro.build/chat). Our friendly Support Squad members are here to help!
+
+You can also check our [Astro Integration Documentation][astro-integration] for more on integrations.
+
+## Contributing
+
+This package is maintained by Astro's Core team. You're welcome to submit an issue or PR!
+
+## Changelog
+
+See [CHANGELOG.md](CHANGELOG.md) for a history of changes to this integration.
+
+[astro-integration]: https://docs.astro.build/en/guides/integrations-guide/
diff --git a/packages/netlify/builders-types.d.ts b/packages/netlify/builders-types.d.ts
new file mode 100644
index 00000000..7c778be4
--- /dev/null
+++ b/packages/netlify/builders-types.d.ts
@@ -0,0 +1,9 @@
+interface NetlifyLocals {
+ runtime: {
+ /**
+ * On-demand Builders support an optional time to live (TTL) pattern that allows you to set a fixed duration of time after which a cached builder response is invalidated. This allows you to force a refresh of a builder-generated response without a new deploy.
+ * @param ttl time to live, in seconds
+ */
+ setBuildersTtl(ttl: number): void;
+ };
+}
diff --git a/packages/netlify/package.json b/packages/netlify/package.json
new file mode 100644
index 00000000..6081ed07
--- /dev/null
+++ b/packages/netlify/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "@astrojs/netlify",
+ "description": "Deploy your site to Netlify",
+ "version": "3.0.2",
+ "type": "module",
+ "types": "./dist/index.d.ts",
+ "author": "withastro",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/withastro/astro.git",
+ "directory": "packages/integrations/netlify"
+ },
+ "keywords": [
+ "withastro",
+ "astro-adapter"
+ ],
+ "bugs": "https://github.com/withastro/astro/issues",
+ "homepage": "https://docs.astro.build/en/guides/integrations-guide/netlify/",
+ "exports": {
+ ".": "./dist/index.js",
+ "./functions": "./dist/integration-functions.js",
+ "./netlify-functions.js": "./dist/netlify-functions.js",
+ "./edge-functions": "./dist/integration-edge-functions.js",
+ "./netlify-edge-functions.js": "./dist/netlify-edge-functions.js",
+ "./package.json": "./package.json"
+ },
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "build": "astro-scripts build \"src/**/*.ts\" && tsc",
+ "build:ci": "astro-scripts build \"src/**/*.ts\"",
+ "dev": "astro-scripts dev \"src/**/*.ts\"",
+ "test-fn": "mocha --exit --timeout 20000 --file \"./test/setup.js\" test/functions/",
+ "test-edge": "deno test --allow-run --allow-read --allow-net --allow-env --allow-write ./test/edge-functions/",
+ "test": "pnpm test-fn",
+ "test:hosted": "mocha --exit --timeout 30000 test/hosted"
+ },
+ "dependencies": {
+ "@astrojs/underscore-redirects": "workspace:*",
+ "@netlify/functions": "^2.0.1",
+ "esbuild": "^0.19.2"
+ },
+ "peerDependencies": {
+ "astro": "workspace:^3.1.4"
+ },
+ "devDependencies": {
+ "@netlify/edge-functions": "^2.0.0",
+ "@netlify/edge-handler-types": "^0.34.1",
+ "@types/node": "^18.17.8",
+ "astro": "workspace:*",
+ "astro-scripts": "workspace:*",
+ "chai": "^4.3.7",
+ "chai-jest-snapshot": "^2.0.0",
+ "cheerio": "1.0.0-rc.12",
+ "mocha": "^10.2.0",
+ "vite": "^4.4.9"
+ },
+ "astro": {
+ "external": true
+ }
+}
diff --git a/packages/netlify/src/index.ts b/packages/netlify/src/index.ts
new file mode 100644
index 00000000..a374020f
--- /dev/null
+++ b/packages/netlify/src/index.ts
@@ -0,0 +1,2 @@
+export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js';
+export { netlifyStatic } from './integration-static.js';
diff --git a/packages/netlify/src/integration-functions.ts b/packages/netlify/src/integration-functions.ts
new file mode 100644
index 00000000..33e7bade
--- /dev/null
+++ b/packages/netlify/src/integration-functions.ts
@@ -0,0 +1,142 @@
+import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro';
+import { writeFile } from 'node:fs/promises';
+import { extname, join } from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { generateEdgeMiddleware } from './middleware.js';
+import type { Args } from './netlify-functions.js';
+import { createRedirects } from './shared.js';
+
+export const NETLIFY_EDGE_MIDDLEWARE_FILE = 'netlify-edge-middleware';
+export const ASTRO_LOCALS_HEADER = 'x-astro-locals';
+
+export function getAdapter({ functionPerRoute, edgeMiddleware, ...args }: Args): AstroAdapter {
+ return {
+ name: '@astrojs/netlify/functions',
+ serverEntrypoint: '@astrojs/netlify/netlify-functions.js',
+ exports: ['handler'],
+ args,
+ adapterFeatures: {
+ functionPerRoute,
+ edgeMiddleware,
+ },
+ supportedAstroFeatures: {
+ hybridOutput: 'stable',
+ staticOutput: 'stable',
+ serverOutput: 'stable',
+ assets: {
+ supportKind: 'stable',
+ isSharpCompatible: true,
+ isSquooshCompatible: true,
+ },
+ },
+ };
+}
+
+interface NetlifyFunctionsOptions {
+ dist?: URL;
+ builders?: boolean;
+ binaryMediaTypes?: string[];
+ edgeMiddleware?: boolean;
+ functionPerRoute?: boolean;
+}
+
+function netlifyFunctions({
+ dist,
+ builders,
+ binaryMediaTypes,
+ functionPerRoute = false,
+ edgeMiddleware = false,
+}: NetlifyFunctionsOptions = {}): AstroIntegration {
+ let _config: AstroConfig;
+ let _entryPoints: Map;
+ let ssrEntryFile: string;
+ let _middlewareEntryPoint: URL;
+ return {
+ name: '@astrojs/netlify',
+ hooks: {
+ 'astro:config:setup': ({ config, updateConfig }) => {
+ const outDir = dist ?? new URL('./dist/', config.root);
+ updateConfig({
+ outDir,
+ build: {
+ redirects: false,
+ client: outDir,
+ server: new URL('./.netlify/functions-internal/', config.root),
+ },
+ });
+ },
+ 'astro:build:ssr': async ({ entryPoints, middlewareEntryPoint }) => {
+ if (middlewareEntryPoint) {
+ _middlewareEntryPoint = middlewareEntryPoint;
+ }
+ _entryPoints = entryPoints;
+ },
+ 'astro:config:done': ({ config, setAdapter }) => {
+ setAdapter(getAdapter({ binaryMediaTypes, builders, functionPerRoute, edgeMiddleware }));
+ _config = config;
+ ssrEntryFile = config.build.serverEntry.replace(/\.m?js/, '');
+
+ if (config.output === 'static') {
+ console.warn(
+ `[@astrojs/netlify] \`output: "server"\` or \`output: "hybrid"\` is required to use this adapter.`
+ );
+ console.warn(
+ `[@astrojs/netlify] Otherwise, this adapter is not required to deploy a static site to Netlify.`
+ );
+ }
+ },
+ 'astro:build:done': async ({ routes, dir }) => {
+ const functionsConfig = {
+ version: 1,
+ config: {
+ nodeModuleFormat: 'esm',
+ },
+ };
+ const functionsConfigPath = join(fileURLToPath(_config.build.server), 'entry.json');
+ await writeFile(functionsConfigPath, JSON.stringify(functionsConfig));
+
+ const type = builders ? 'builders' : 'functions';
+ const kind = type ?? 'functions';
+
+ if (_entryPoints.size) {
+ const routeToDynamicTargetMap = new Map();
+ for (const [route, entryFile] of _entryPoints) {
+ const wholeFileUrl = fileURLToPath(entryFile);
+
+ const extension = extname(wholeFileUrl);
+ const relative = wholeFileUrl
+ .replace(fileURLToPath(_config.build.server), '')
+ .replace(extension, '')
+ .replaceAll('\\', '/');
+ const dynamicTarget = `/.netlify/${kind}/${relative}`;
+
+ routeToDynamicTargetMap.set(route, dynamicTarget);
+ }
+ await createRedirects(_config, routeToDynamicTargetMap, dir);
+ } else {
+ const dynamicTarget = `/.netlify/${kind}/${ssrEntryFile}`;
+ const map: [RouteData, string][] = routes.map((route) => {
+ return [route, dynamicTarget];
+ });
+ const routeToDynamicTargetMap = new Map(Array.from(map));
+
+ await createRedirects(_config, routeToDynamicTargetMap, dir);
+ }
+ if (_middlewareEntryPoint) {
+ const outPath = fileURLToPath(new URL('./.netlify/edge-functions/', _config.root));
+ const netlifyEdgeMiddlewareHandlerPath = new URL(
+ NETLIFY_EDGE_MIDDLEWARE_FILE,
+ _config.srcDir
+ );
+ await generateEdgeMiddleware(
+ _middlewareEntryPoint,
+ outPath,
+ netlifyEdgeMiddlewareHandlerPath
+ );
+ }
+ },
+ },
+ };
+}
+
+export { netlifyFunctions as default, netlifyFunctions };
diff --git a/packages/netlify/src/integration-static.ts b/packages/netlify/src/integration-static.ts
new file mode 100644
index 00000000..af284986
--- /dev/null
+++ b/packages/netlify/src/integration-static.ts
@@ -0,0 +1,30 @@
+import type { AstroIntegration, RouteData } from 'astro';
+import { createRedirects } from './shared.js';
+
+export function netlifyStatic(): AstroIntegration {
+ let _config: any;
+ return {
+ name: '@astrojs/netlify',
+ hooks: {
+ 'astro:config:setup': ({ updateConfig }) => {
+ updateConfig({
+ build: {
+ // Do not output HTML redirects because we are building a `_redirects` file.
+ redirects: false,
+ },
+ });
+ },
+ 'astro:config:done': ({ config }) => {
+ _config = config;
+ },
+ 'astro:build:done': async ({ dir, routes }) => {
+ const mappedRoutes: [RouteData, string][] = routes.map((route) => [
+ route,
+ `/.netlify/static/`,
+ ]);
+ const routesToDynamicTargetMap = new Map(Array.from(mappedRoutes));
+ await createRedirects(_config, routesToDynamicTargetMap, dir);
+ },
+ },
+ };
+}
diff --git a/packages/netlify/src/middleware.ts b/packages/netlify/src/middleware.ts
new file mode 100644
index 00000000..3c2f4f69
--- /dev/null
+++ b/packages/netlify/src/middleware.ts
@@ -0,0 +1,75 @@
+import { existsSync } from 'node:fs';
+import { join } from 'node:path';
+import { fileURLToPath, pathToFileURL } from 'node:url';
+import { ASTRO_LOCALS_HEADER } from './integration-functions.js';
+import { DENO_SHIM } from './shared.js';
+
+/**
+ * It generates a Netlify edge function.
+ *
+ */
+export async function generateEdgeMiddleware(
+ astroMiddlewareEntryPointPath: URL,
+ outPath: string,
+ netlifyEdgeMiddlewareHandlerPath: URL
+): Promise {
+ const entryPointPathURLAsString = JSON.stringify(
+ fileURLToPath(astroMiddlewareEntryPointPath).replace(/\\/g, '/')
+ );
+
+ const code = edgeMiddlewareTemplate(entryPointPathURLAsString, netlifyEdgeMiddlewareHandlerPath);
+ const bundledFilePath = join(outPath, 'edgeMiddleware.js');
+ const esbuild = await import('esbuild');
+ await esbuild.build({
+ stdin: {
+ contents: code,
+ resolveDir: process.cwd(),
+ },
+ target: 'es2020',
+ platform: 'browser',
+ outfile: bundledFilePath,
+ allowOverwrite: true,
+ format: 'esm',
+ bundle: true,
+ minify: false,
+ banner: {
+ js: DENO_SHIM,
+ },
+ });
+ return pathToFileURL(bundledFilePath);
+}
+
+function edgeMiddlewareTemplate(middlewarePath: string, netlifyEdgeMiddlewareHandlerPath: URL) {
+ const filePathEdgeMiddleware = fileURLToPath(netlifyEdgeMiddlewareHandlerPath);
+ let handlerTemplateImport = '';
+ let handlerTemplateCall = '{}';
+ if (existsSync(filePathEdgeMiddleware + '.js') || existsSync(filePathEdgeMiddleware + '.ts')) {
+ const stringified = JSON.stringify(filePathEdgeMiddleware.replace(/\\/g, '/'));
+ handlerTemplateImport = `import handler from ${stringified}`;
+ handlerTemplateCall = `handler({ request, context })`;
+ } else {
+ }
+ return `
+ ${handlerTemplateImport}
+import { onRequest } from ${middlewarePath};
+import { createContext, trySerializeLocals } from 'astro/middleware';
+export default async function middleware(request, context) {
+ const url = new URL(request.url);
+ const ctx = createContext({
+ request,
+ params: {}
+ });
+ ctx.locals = ${handlerTemplateCall};
+ const next = async () => {
+ request.headers.set(${JSON.stringify(ASTRO_LOCALS_HEADER)}, trySerializeLocals(ctx.locals));
+ return await context.next();
+ };
+
+ return onRequest(ctx, next);
+}
+
+export const config = {
+ path: "/*"
+}
+`;
+}
diff --git a/packages/netlify/src/netlify-functions.ts b/packages/netlify/src/netlify-functions.ts
new file mode 100644
index 00000000..8c051d9f
--- /dev/null
+++ b/packages/netlify/src/netlify-functions.ts
@@ -0,0 +1,225 @@
+import { builder, type Handler } from '@netlify/functions';
+import type { SSRManifest } from 'astro';
+import { App } from 'astro/app';
+import { applyPolyfills } from 'astro/app/node';
+import { ASTRO_LOCALS_HEADER } from './integration-functions.js';
+
+applyPolyfills();
+
+export interface Args {
+ builders?: boolean;
+ binaryMediaTypes?: string[];
+ edgeMiddleware: boolean;
+ functionPerRoute: boolean;
+}
+
+function parseContentType(header?: string) {
+ return header?.split(';')[0] ?? '';
+}
+
+const clientAddressSymbol = Symbol.for('astro.clientAddress');
+
+export const createExports = (manifest: SSRManifest, args: Args) => {
+ const app = new App(manifest);
+
+ const builders = args.builders ?? false;
+ const binaryMediaTypes = args.binaryMediaTypes ?? [];
+ const knownBinaryMediaTypes = new Set([
+ 'audio/3gpp',
+ 'audio/3gpp2',
+ 'audio/aac',
+ 'audio/midi',
+ 'audio/mpeg',
+ 'audio/ogg',
+ 'audio/opus',
+ 'audio/wav',
+ 'audio/webm',
+ 'audio/x-midi',
+ 'image/avif',
+ 'image/bmp',
+ 'image/gif',
+ 'image/vnd.microsoft.icon',
+ 'image/heif',
+ 'image/jpeg',
+ 'image/png',
+ 'image/svg+xml',
+ 'image/tiff',
+ 'image/webp',
+ 'video/3gpp',
+ 'video/3gpp2',
+ 'video/mp2t',
+ 'video/mp4',
+ 'video/mpeg',
+ 'video/ogg',
+ 'video/x-msvideo',
+ 'video/webm',
+ ...binaryMediaTypes,
+ ]);
+
+ const myHandler: Handler = async (event) => {
+ const { httpMethod, headers, rawUrl, body: requestBody, isBase64Encoded } = event;
+ const init: RequestInit = {
+ method: httpMethod,
+ headers: new Headers(headers as any),
+ };
+ // Attach the event body the request, with proper encoding.
+ if (httpMethod !== 'GET' && httpMethod !== 'HEAD') {
+ const encoding = isBase64Encoded ? 'base64' : 'utf-8';
+ init.body =
+ typeof requestBody === 'string' ? Buffer.from(requestBody, encoding) : requestBody;
+ }
+
+ const request = new Request(rawUrl, init);
+
+ const routeData = app.match(request);
+ const ip = headers['x-nf-client-connection-ip'];
+ Reflect.set(request, clientAddressSymbol, ip);
+
+ let locals: Record = {};
+
+ if (request.headers.has(ASTRO_LOCALS_HEADER)) {
+ let localsAsString = request.headers.get(ASTRO_LOCALS_HEADER);
+ if (localsAsString) {
+ locals = JSON.parse(localsAsString);
+ }
+ }
+
+ let responseTtl = undefined;
+
+ locals.runtime = builders
+ ? {
+ setBuildersTtl(ttl: number) {
+ responseTtl = ttl;
+ },
+ }
+ : {};
+
+ const response: Response = await app.render(request, routeData, locals);
+ const responseHeaders = Object.fromEntries(response.headers.entries());
+
+ const responseContentType = parseContentType(responseHeaders['content-type']);
+ const responseIsBase64Encoded = knownBinaryMediaTypes.has(responseContentType);
+
+ let responseBody: string;
+ if (responseIsBase64Encoded) {
+ const ab = await response.arrayBuffer();
+ responseBody = Buffer.from(ab).toString('base64');
+ } else {
+ responseBody = await response.text();
+ }
+
+ const fnResponse: any = {
+ statusCode: response.status,
+ headers: responseHeaders,
+ body: responseBody,
+ isBase64Encoded: responseIsBase64Encoded,
+ ttl: responseTtl,
+ };
+
+ const cookies = response.headers.get('set-cookie');
+ if (cookies) {
+ fnResponse.multiValueHeaders = {
+ 'set-cookie': Array.isArray(cookies) ? cookies : splitCookiesString(cookies),
+ };
+ }
+
+ // Apply cookies set via Astro.cookies.set/delete
+ if (app.setCookieHeaders) {
+ const setCookieHeaders = Array.from(app.setCookieHeaders(response));
+ fnResponse.multiValueHeaders = fnResponse.multiValueHeaders || {};
+ if (!fnResponse.multiValueHeaders['set-cookie']) {
+ fnResponse.multiValueHeaders['set-cookie'] = [];
+ }
+ fnResponse.multiValueHeaders['set-cookie'].push(...setCookieHeaders);
+ }
+
+ return fnResponse;
+ };
+
+ const handler = builders ? builder(myHandler) : myHandler;
+
+ return { handler };
+};
+
+/*
+ From: https://github.com/nfriedly/set-cookie-parser/blob/5cae030d8ef0f80eec58459e3583d43a07b984cb/lib/set-cookie.js#L144
+ Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
+ that are within a single set-cookie field-value, such as in the Expires portion.
+ This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
+ Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
+ React Native's fetch does this for *every* header, including set-cookie.
+ Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
+ Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
+*/
+function splitCookiesString(cookiesString: string): string[] {
+ if (Array.isArray(cookiesString)) {
+ return cookiesString;
+ }
+ if (typeof cookiesString !== 'string') {
+ return [];
+ }
+
+ let cookiesStrings = [];
+ let pos = 0;
+ let start;
+ let ch;
+ let lastComma;
+ let nextStart;
+ let cookiesSeparatorFound;
+
+ function skipWhitespace() {
+ while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
+ pos += 1;
+ }
+ return pos < cookiesString.length;
+ }
+
+ function notSpecialChar() {
+ ch = cookiesString.charAt(pos);
+
+ return ch !== '=' && ch !== ';' && ch !== ',';
+ }
+
+ while (pos < cookiesString.length) {
+ start = pos;
+ cookiesSeparatorFound = false;
+
+ while (skipWhitespace()) {
+ ch = cookiesString.charAt(pos);
+ if (ch === ',') {
+ // ',' is a cookie separator if we have later first '=', not ';' or ','
+ lastComma = pos;
+ pos += 1;
+
+ skipWhitespace();
+ nextStart = pos;
+
+ while (pos < cookiesString.length && notSpecialChar()) {
+ pos += 1;
+ }
+
+ // currently special character
+ if (pos < cookiesString.length && cookiesString.charAt(pos) === '=') {
+ // we found cookies separator
+ cookiesSeparatorFound = true;
+ // pos is inside the next cookie, so back up and return it.
+ pos = nextStart;
+ cookiesStrings.push(cookiesString.substring(start, lastComma));
+ start = pos;
+ } else {
+ // in param ',' or param separator ';',
+ // we continue from that comma
+ pos = lastComma + 1;
+ }
+ } else {
+ pos += 1;
+ }
+ }
+
+ if (!cookiesSeparatorFound || pos >= cookiesString.length) {
+ cookiesStrings.push(cookiesString.substring(start, cookiesString.length));
+ }
+ }
+
+ return cookiesStrings;
+}
diff --git a/packages/netlify/src/shared.ts b/packages/netlify/src/shared.ts
new file mode 100644
index 00000000..175b9d04
--- /dev/null
+++ b/packages/netlify/src/shared.ts
@@ -0,0 +1,114 @@
+import { createRedirectsFromAstroRoutes } from '@astrojs/underscore-redirects';
+import type { AstroConfig, RouteData } from 'astro';
+import esbuild from 'esbuild';
+import fs from 'node:fs';
+import npath from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+export const DENO_SHIM = `globalThis.process = {
+ argv: [],
+ env: Deno.env.toObject(),
+};`;
+
+export interface NetlifyEdgeFunctionsOptions {
+ dist?: URL;
+}
+
+export interface NetlifyEdgeFunctionManifestFunctionPath {
+ function: string;
+ path: string;
+}
+
+export interface NetlifyEdgeFunctionManifestFunctionPattern {
+ function: string;
+ pattern: string;
+}
+
+export type NetlifyEdgeFunctionManifestFunction =
+ | NetlifyEdgeFunctionManifestFunctionPath
+ | NetlifyEdgeFunctionManifestFunctionPattern;
+
+export interface NetlifyEdgeFunctionManifest {
+ functions: NetlifyEdgeFunctionManifestFunction[];
+ version: 1;
+}
+
+export async function createRedirects(
+ config: AstroConfig,
+ routeToDynamicTargetMap: Map,
+ dir: URL
+) {
+ const _redirectsURL = new URL('./_redirects', dir);
+
+ const _redirects = createRedirectsFromAstroRoutes({
+ config,
+ routeToDynamicTargetMap,
+ dir,
+ });
+ const content = _redirects.print();
+
+ // Always use appendFile() because the redirects file could already exist,
+ // e.g. due to a `/public/_redirects` file that got copied to the output dir.
+ // If the file does not exist yet, appendFile() automatically creates it.
+ await fs.promises.appendFile(_redirectsURL, content, 'utf-8');
+}
+
+export async function createEdgeManifest(routes: RouteData[], entryFile: string, dir: URL) {
+ const functions: NetlifyEdgeFunctionManifestFunction[] = [];
+ for (const route of routes) {
+ if (route.pathname) {
+ functions.push({
+ function: entryFile,
+ path: route.pathname,
+ });
+ } else {
+ functions.push({
+ function: entryFile,
+ // Make route pattern serializable to match expected
+ // Netlify Edge validation format. Mirrors Netlify's own edge bundler:
+ // https://github.com/netlify/edge-bundler/blob/main/src/manifest.ts#L34
+ pattern: route.pattern.source.replace(/\\\//g, '/').toString(),
+ });
+ }
+ }
+
+ const manifest: NetlifyEdgeFunctionManifest = {
+ functions,
+ version: 1,
+ };
+
+ const baseDir = new URL('./.netlify/edge-functions/', dir);
+ await fs.promises.mkdir(baseDir, { recursive: true });
+
+ const manifestURL = new URL('./manifest.json', baseDir);
+ const _manifest = JSON.stringify(manifest, null, ' ');
+ await fs.promises.writeFile(manifestURL, _manifest, 'utf-8');
+}
+
+export async function bundleServerEntry(entryUrl: URL, serverUrl?: URL, vite?: any | undefined) {
+ const pth = fileURLToPath(entryUrl);
+ await esbuild.build({
+ target: 'es2020',
+ platform: 'browser',
+ entryPoints: [pth],
+ outfile: pth,
+ allowOverwrite: true,
+ format: 'esm',
+ bundle: true,
+ external: ['@astrojs/markdown-remark', 'astro/middleware'],
+ banner: {
+ js: DENO_SHIM,
+ },
+ });
+
+ // Remove chunks, if they exist. Since we have bundled via esbuild these chunks are trash.
+ if (vite && serverUrl) {
+ try {
+ const chunkFileNames =
+ vite?.build?.rollupOptions?.output?.chunkFileNames ?? `chunks/chunk.[hash].mjs`;
+ const chunkPath = npath.dirname(chunkFileNames);
+ const chunksDirUrl = new URL(chunkPath + '/', serverUrl);
+ await fs.promises.rm(chunksDirUrl, { recursive: true, force: true });
+ } catch {}
+ }
+}
diff --git a/packages/netlify/test/functions/404.test.js b/packages/netlify/test/functions/404.test.js
new file mode 100644
index 00000000..f12919a3
--- /dev/null
+++ b/packages/netlify/test/functions/404.test.js
@@ -0,0 +1,27 @@
+import { expect } from 'chai';
+import netlifyAdapter from '../../dist/index.js';
+import { loadFixture, testIntegration } from './test-utils.js';
+
+describe('404 page', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/404/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/404/dist/', import.meta.url),
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ });
+ await fixture.build();
+ });
+
+ it('404 route is included in the redirect file', async () => {
+ const redir = await fixture.readFile('/_redirects');
+ const expr = new RegExp('/* /.netlify/functions/entry 404');
+ expect(redir).to.match(expr);
+ });
+});
diff --git a/packages/netlify/test/functions/base64-response.test.js b/packages/netlify/test/functions/base64-response.test.js
new file mode 100644
index 00000000..6e59bd19
--- /dev/null
+++ b/packages/netlify/test/functions/base64-response.test.js
@@ -0,0 +1,62 @@
+import { expect } from 'chai';
+import { loadFixture, testIntegration } from './test-utils.js';
+import netlifyAdapter from '../../dist/index.js';
+
+describe('Base64 Responses', () => {
+ /** @type {import('../../../astro/test/test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/base64-response/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/base64-response/dist/', import.meta.url),
+ binaryMediaTypes: ['font/otf'],
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ });
+ await fixture.build();
+ });
+
+ it('Can return base64 encoded strings', async () => {
+ const entryURL = new URL(
+ './fixtures/base64-response/.netlify/functions-internal/entry.mjs',
+ import.meta.url
+ );
+ const { handler } = await import(entryURL);
+ const resp = await handler({
+ httpMethod: 'GET',
+ headers: {},
+ rawUrl: 'http://example.com/image',
+ body: '{}',
+ isBase64Encoded: false,
+ });
+ expect(resp.statusCode, 'successful response').to.equal(200);
+ expect(resp.isBase64Encoded, 'includes isBase64Encoded flag').to.be.true;
+
+ const buffer = Buffer.from(resp.body, 'base64');
+ expect(buffer.toString(), 'decoded base64 string matches').to.equal('base64 test string');
+ });
+
+ it('Can define custom binaryMediaTypes', async () => {
+ const entryURL = new URL(
+ './fixtures/base64-response/.netlify/functions-internal/entry.mjs',
+ import.meta.url
+ );
+ const { handler } = await import(entryURL);
+ const resp = await handler({
+ httpMethod: 'GET',
+ headers: {},
+ rawUrl: 'http://example.com/font',
+ body: '{}',
+ isBase64Encoded: false,
+ });
+ expect(resp.statusCode, 'successful response').to.equal(200);
+ expect(resp.isBase64Encoded, 'includes isBase64Encoded flag').to.be.true;
+
+ const buffer = Buffer.from(resp.body, 'base64');
+ expect(buffer.toString(), 'decoded base64 string matches').to.equal('base64 test font');
+ });
+});
diff --git a/packages/netlify/test/functions/builders.test.js b/packages/netlify/test/functions/builders.test.js
new file mode 100644
index 00000000..d47af92c
--- /dev/null
+++ b/packages/netlify/test/functions/builders.test.js
@@ -0,0 +1,37 @@
+import { expect } from 'chai';
+import { loadFixture, testIntegration } from './test-utils.js';
+import netlifyAdapter from '../../dist/index.js';
+
+describe('Builders', () => {
+ /** @type {import('../../../astro/test/test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/builders/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/builders/dist/', import.meta.url),
+ builders: true,
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ });
+ await fixture.build();
+ });
+
+ it('A route can set builders ttl', async () => {
+ const entryURL = new URL(
+ './fixtures/builders/.netlify/functions-internal/entry.mjs',
+ import.meta.url
+ );
+ const { handler } = await import(entryURL);
+ const resp = await handler({
+ httpMethod: 'GET',
+ headers: {},
+ rawUrl: 'http://example.com/',
+ isBase64Encoded: false,
+ });
+ expect(resp.ttl).to.equal(45);
+ });
+});
diff --git a/packages/netlify/test/functions/cookies.test.js b/packages/netlify/test/functions/cookies.test.js
new file mode 100644
index 00000000..f1569523
--- /dev/null
+++ b/packages/netlify/test/functions/cookies.test.js
@@ -0,0 +1,41 @@
+import { expect } from 'chai';
+import { loadFixture, testIntegration } from './test-utils.js';
+import netlifyAdapter from '../../dist/index.js';
+
+describe('Cookies', () => {
+ /** @type {import('../../../astro/test/test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/cookies/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/cookies/dist/', import.meta.url),
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ });
+ await fixture.build();
+ });
+
+ it('Can set multiple', async () => {
+ const entryURL = new URL(
+ './fixtures/cookies/.netlify/functions-internal/entry.mjs',
+ import.meta.url
+ );
+ const { handler } = await import(entryURL);
+ const resp = await handler({
+ httpMethod: 'POST',
+ headers: {},
+ rawUrl: 'http://example.com/login',
+ body: '{}',
+ isBase64Encoded: false,
+ });
+ expect(resp.statusCode).to.equal(301);
+ expect(resp.headers.location).to.equal('/');
+ expect(resp.multiValueHeaders).to.be.deep.equal({
+ 'set-cookie': ['foo=foo; HttpOnly', 'bar=bar; HttpOnly'],
+ });
+ });
+});
diff --git a/packages/netlify/test/functions/dynamic-route.test.js b/packages/netlify/test/functions/dynamic-route.test.js
new file mode 100644
index 00000000..6bb68eab
--- /dev/null
+++ b/packages/netlify/test/functions/dynamic-route.test.js
@@ -0,0 +1,33 @@
+import { expect } from 'chai';
+import netlifyAdapter from '../../dist/index.js';
+import { loadFixture, testIntegration } from './test-utils.js';
+
+describe('Dynamic pages', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/dynamic-route/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/dynamic-route/dist/', import.meta.url),
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ });
+ await fixture.build();
+ });
+
+ it('Dynamic pages are included in the redirects file', async () => {
+ const redir = await fixture.readFile('/_redirects');
+ expect(redir).to.match(/\/products\/:id/);
+ });
+
+ it('Prerendered routes are also included using placeholder syntax', async () => {
+ const redir = await fixture.readFile('/_redirects');
+ expect(redir).to.include('/pets/:cat /pets/:cat/index.html 200');
+ expect(redir).to.include('/pets/:dog /pets/:dog/index.html 200');
+ expect(redir).to.include('/pets /.netlify/functions/entry 200');
+ });
+});
diff --git a/packages/netlify/test/functions/edge-middleware.test.js b/packages/netlify/test/functions/edge-middleware.test.js
new file mode 100644
index 00000000..a83720a4
--- /dev/null
+++ b/packages/netlify/test/functions/edge-middleware.test.js
@@ -0,0 +1,44 @@
+import netlifyAdapter from '../../dist/index.js';
+import { testIntegration, loadFixture } from './test-utils.js';
+import { expect } from 'chai';
+
+describe('Middleware', () => {
+ it('with edge handle file, should successfully build the middleware', async () => {
+ /** @type {import('./test-utils').Fixture} */
+ const fixture = await loadFixture({
+ root: new URL('./fixtures/middleware-with-handler-file/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/middleware-with-handler-file/dist/', import.meta.url),
+ edgeMiddleware: true,
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ build: {
+ excludeMiddleware: true,
+ },
+ });
+ await fixture.build();
+ const contents = await fixture.readFile('../.netlify/edge-functions/edgeMiddleware.js');
+ expect(contents.includes('"Hello world"')).to.be.true;
+ });
+
+ it('without edge handle file, should successfully build the middleware', async () => {
+ /** @type {import('./test-utils').Fixture} */
+ const fixture = await loadFixture({
+ root: new URL('./fixtures/middleware-without-handler-file/', import.meta.url).toString(),
+ output: 'server',
+ adapter: netlifyAdapter({
+ dist: new URL('./fixtures/middleware-without-handler-file/dist/', import.meta.url),
+ }),
+ site: `http://example.com`,
+ integrations: [testIntegration()],
+ build: {
+ excludeMiddleware: true,
+ },
+ });
+ await fixture.build();
+ const contents = await fixture.readFile('../.netlify/edge-functions/edgeMiddleware.js');
+ expect(contents.includes('"Hello world"')).to.be.false;
+ });
+});
diff --git a/packages/netlify/test/functions/fixtures/.gitignore b/packages/netlify/test/functions/fixtures/.gitignore
new file mode 100644
index 00000000..916f6064
--- /dev/null
+++ b/packages/netlify/test/functions/fixtures/.gitignore
@@ -0,0 +1 @@
+**/netlify
diff --git a/packages/netlify/test/functions/fixtures/404/src/pages/404.astro b/packages/netlify/test/functions/fixtures/404/src/pages/404.astro
new file mode 100644
index 00000000..b60b5e55
--- /dev/null
+++ b/packages/netlify/test/functions/fixtures/404/src/pages/404.astro
@@ -0,0 +1,11 @@
+---
+
+---
+
+
+ Not found
+
+
+