diff --git a/pages/cloudflare/howtos/_meta.json b/pages/cloudflare/howtos/_meta.json
index c8fe30e..c2190c7 100644
--- a/pages/cloudflare/howtos/_meta.json
+++ b/pages/cloudflare/howtos/_meta.json
@@ -6,5 +6,7 @@
"image": "Image Optimization",
"custom-worker": "Custom Worker",
"keep_names": "__name issues",
- "workerd": "workerd specific packages"
+ "workerd": "workerd specific packages",
+ "skew": "Skew Protection",
+ "assets": "Static assets"
}
diff --git a/pages/cloudflare/howtos/assets.mdx b/pages/cloudflare/howtos/assets.mdx
new file mode 100644
index 0000000..6c05ebf
--- /dev/null
+++ b/pages/cloudflare/howtos/assets.mdx
@@ -0,0 +1,56 @@
+## Static assets (public folder)
+
+The [static assets of Next located in the public folder](https://nextjs.org/docs/app/api-reference/file-conventions/public-folder) are served using [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/).
+
+Workers Static Assets can intercept requests to the application ([`run_worker_first=false`](https://developers.cloudflare.com/workers/static-assets/) which is the default). This is the most cost efficient option as asset requests will not be billed in that case.
+
+Another option is to run the Worker first (`run_worker_first=true`) to offer more flexibility at the expense of a higher cost.
+
+Note that `run_worker_first` could also be set to a list of patterns - this is a great option if you need more flexibility for only a subset of the statids assets.
+
+### run_worker_first=false
+
+When `run_worker_first` is set to `false`, requests are intercepted before reaching the worker and are not billed:
+
+```jsonc
+// wrangler.jsonc
+{
+ "name": "my-app",
+ // ...
+ "assets": {
+ "directory": ".open-next/assets",
+ "binding": "ASSETS",
+ // Optional as false is the default value
+ "run_worker_first": false,
+ },
+ // ...
+}
+```
+
+This is the most cost efficient option to use when you do not need to serve assets behind the middleware or Next rewrites and headers from [the Next config](https://nextjs.org/docs/app/api-reference/config/next-config-js).
+
+When `run_worker_first=false` you can still configure [headers](https://developers.cloudflare.com/workers/static-assets/headers/) and [redirects](https://developers.cloudflare.com/workers/static-assets/redirects/) via Worker Static Assets.
+
+### run_worker_first=true
+
+When `run_worker_first` is set to `true`, all the requests will reach the Worker and be billed:
+
+```jsonc
+// wrangler.jsonc
+{
+ "name": "my-app",
+ // ...
+ "assets": {
+ "directory": ".open-next/assets",
+ "binding": "ASSETS",
+ "run_worker_first": true,
+ },
+ // ...
+}
+```
+
+The Open Next asset resolver will be used to retrieve the assets from the Worker.
+
+When `run_worker_first=true`, assets are served behind the middleware and Next rewrites and headers from [the Next config](https://nextjs.org/docs/app/api-reference/config/next-config-js). The [headers](https://developers.cloudflare.com/workers/static-assets/headers/) and [redirects](https://developers.cloudflare.com/workers/static-assets/redirects/) configured for the Worker Static Assets do not apply in this case.
+
+`run_worker_first=true` should be used if you plan to use skew protection.
diff --git a/pages/cloudflare/howtos/skew.mdx b/pages/cloudflare/howtos/skew.mdx
new file mode 100644
index 0000000..fe6e1a3
--- /dev/null
+++ b/pages/cloudflare/howtos/skew.mdx
@@ -0,0 +1,88 @@
+import { Callout } from "nextra/components";
+
+## Skew protection
+
+The Cloudflare adapter has _experimental support_ for skew protection based on [the preview URLs](https://developers.cloudflare.com/workers/configuration/previews/).
+
+
+ Preview URLs are disabled for [Workers that implement a Durable
+ Object](https://developers.cloudflare.com/workers/configuration/previews/#limitations). If your app uses
+ Durable Objects, they will need to be implemented in a separate Worker.
+
+
+### How to enable the skew protection
+
+**OpenNext config**
+
+Set `cloudflare.skewProtection.enabled` to `true` to enable skew protection:
+
+```ts
+// open-next.config.ts
+export default {
+ // ...
+ cloudflare: {
+ skewProtection: {
+ enabled: true,
+ // Maximum number of previous versions to use.
+ // Optional, default to 20.
+ maxNumberOfVersions: 20,
+ // Age of the oldest version to use (from the last deplyment date)
+ // Optional, default to 7 days.
+ maxVersionAgeDays: 7,
+ },
+ },
+} satisfies OpenNextConfig;
+```
+
+**Wrangler configuration**
+
+The Worker needs to serve the correct version of the app assets. For that it need be be executed before incoming requests are matched against the assets. Set [`run_worker_first`](https://developers.cloudflare.com/workers/static-assets/binding/#run_worker_first) to `true` in your wrangler configuration to enable this behavior:
+
+```jsonc
+// wrangler.jsonc
+{
+ "name": "my-app",
+ // ...
+ "assets": {
+ "directory": ".open-next/assets",
+ "binding": "ASSETS",
+ "run_worker_first": true,
+ },
+ // ...
+}
+```
+
+**Environment variables**
+
+The following environment variables should be set when the skew protection is used:
+
+- `CF_WORKER_NAME` should be set to the name of the worker, i.e. `my-app` given the config above. If you're using environment, the name of the app should contain your env, i.e. `my-app-`
+- `CF_PREVIEW_DOMAIN` is the the subdomain of `workers.dev` where the previews are deployed, i.e. `..workers.dev`
+- `CF_WORKERS_SCRIPTS_API_TOKEN` is an API token with the `Workers Scripts:Read` permission
+- `CF_ACCOUNT_ID` is the Cloudflare account id where the app is deployed.
+
+Those variables are used to retrieve the past deployments of your application.
+
+**Next config**
+
+You must set a different `deploymentId` in your next config each time your app is deployed. You will get an error if the `deployementId` has already been used by a previous deployment.
+
+The cloudflare adapter exports a `getDeploymentId()` function that can be used to generate a unique deployment id.
+
+```ts
+// next.config.ts
+import { getDeploymentId } from "@opennextjs/cloudflare";
+
+const nextConfig = {
+ // ...
+ deploymentId: getDeploymentId(),
+};
+```
+
+### What you should know
+
+- Because the Worker is configured to run in front of the assets Worker (`run_worker_first`), requesting an asset will count as a request to your Worker
+- Requesting an older deployment will generate 2 requests: the request to the latest version and the request to the older version
+- It is not currently possible to delete a deployment
+- Requests to an older deployment will be a few milli-seconds slower than requests to the latest version of the app
+- Request to a deployment older than the `maxNumberOfVersions` or older than `maxVersionAgeDays` will fallback to the current deployment