diff --git a/app/components/IntegrationsList.vue b/app/components/IntegrationsList.vue
index 377978ed2..dfd5a13b1 100644
--- a/app/components/IntegrationsList.vue
+++ b/app/components/IntegrationsList.vue
@@ -30,6 +30,12 @@ const integrations = [
to: '/guides/integrations/netlify',
logo: '/docs/img/tutorials/netlify.png',
},
+ {
+ title: 'Cloudflare Workers',
+ description: 'Integrate Directus with Cloudflare Workers Builds to deploy Workers and track build status.',
+ to: '/guides/integrations/cloudflare-workers',
+ logo: '/docs/img/cloudflare.svg',
+ },
{
title: 'Framer',
description: 'Sync content between Directus collections and Framer\'s CMS in both directions.',
diff --git a/content/guides/10.deployments/0.index.md b/content/guides/10.deployments/0.index.md
index 1269f1d04..63fadfd26 100644
--- a/content/guides/10.deployments/0.index.md
+++ b/content/guides/10.deployments/0.index.md
@@ -9,7 +9,7 @@ If your frontend is statically generated or server-rendered using Directus as a
## Key Features
- **Trigger deployments** for any connected project with one click
-- **Real-time status updates** via provider webhooks
+- **Deployment status** in Directus (Vercel and Netlify use webhooks; **Cloudflare Workers** updates via polling—use **Refresh** when needed)
- **Build logs** with search and filtering
- **Deployment history** with stats and duration tracking
- **Role-based access control** using native Directus permissions
@@ -26,6 +26,10 @@ Connect Vercel projects and deploy from Directus.
Connect Netlify sites and deploy from Directus.
:::
+:::card{title="Cloudflare Workers" icon="simple-icons:cloudflare" to="/guides/integrations/cloudflare-workers"}
+Connect Cloudflare Workers (Workers Builds) and deploy from Directus.
+:::
+
::
## Getting Started
@@ -35,7 +39,7 @@ Connect Netlify sites and deploy from Directus.
3. Select the projects you want to manage
4. Start deploying
-For provider-specific setup instructions, see the [Vercel](/guides/integrations/vercel) or [Netlify](/guides/integrations/netlify) integration guides.
+For provider-specific setup instructions, see the [Vercel](/guides/integrations/vercel), [Netlify](/guides/integrations/netlify), or [Cloudflare Workers](/guides/integrations/cloudflare-workers) integration guides.
## Security
diff --git a/content/guides/10.deployments/1.security.md b/content/guides/10.deployments/1.security.md
index 252063011..2f65df205 100644
--- a/content/guides/10.deployments/1.security.md
+++ b/content/guides/10.deployments/1.security.md
@@ -41,13 +41,14 @@ Each permission can include access policy filters to limit what a user can see o
For example:
- Filter `provider` = `vercel` on `directus_deployments` to give a role access to Vercel deployments only
+- Filter `provider` = `cloudflare` on `directus_deployments` to give a role access to Cloudflare Workers deployments only
- Filter `name` on `directus_deployment_projects` to limit access to specific projects by name
When filtering by provider or project, apply matching filters across all three collections to keep access consistent.
## Credential Protection
-Provider API tokens (Vercel Personal Access Token, Netlify Personal Access Token) are:
+Provider API tokens (Vercel Personal Access Token, Netlify Personal Access Token, Cloudflare user-scoped API token) are:
- **Encrypted at rest** in the database
- **Masked in the UI** so they cannot be read back after saving
@@ -71,4 +72,8 @@ Set up and configure the Vercel integration.
Set up and configure the Netlify integration.
:::
+:::card{title="Cloudflare Workers Integration" icon="simple-icons:cloudflare" to="/guides/integrations/cloudflare-workers"}
+Set up and configure the Cloudflare Workers integration.
+:::
+
::
diff --git a/content/guides/12.integrations/6.cloudflare-workers/.navigation.yml b/content/guides/12.integrations/6.cloudflare-workers/.navigation.yml
new file mode 100644
index 000000000..59eefc9d1
--- /dev/null
+++ b/content/guides/12.integrations/6.cloudflare-workers/.navigation.yml
@@ -0,0 +1,2 @@
+title: Cloudflare Workers
+headline: Cloudflare Workers
diff --git a/content/guides/12.integrations/6.cloudflare-workers/0.index.md b/content/guides/12.integrations/6.cloudflare-workers/0.index.md
new file mode 100644
index 000000000..1e64590b8
--- /dev/null
+++ b/content/guides/12.integrations/6.cloudflare-workers/0.index.md
@@ -0,0 +1,97 @@
+---
+id: cloudflare-workers-integration
+title: Cloudflare Workers
+description: Integrate Directus with Cloudflare Workers Builds to trigger deployments, track build progress, and manage Workers from within your Directus instance.
+technologies:
+ - cloudflare
+---
+
+When your frontend runs on Cloudflare Workers and pulls content from Directus, publishing a content change doesn't automatically trigger a new build. This integration adds deployment controls to Directus so your team can trigger builds, track progress, and review logs without switching to the Cloudflare dashboard.
+
+::callout{icon="heroicons-outline:rocket-launch"}
+**Quick Start**
+1. **Enable the Deployment module** in your Directus project settings (under **Modules**).
+2. **Link Cloudflare**: open the Deployment module and choose **Configure Cloudflare Workers** (or add the provider from **Settings**).
+3. **Enter credentials and Account ID** (see below), save, then **select which Workers** to manage.
+4. **Deploy** from a Worker's project view, or use an optional **Deploy Hook** action if you configured hook URLs.
+5. **Optional:** To record builds started **outside** Directus (for example CI) without relying only on opening the app, set up **Cloudflare Queues + Workers Builds event subscriptions** and paste an **Event Subscription Queue ID**. See **[Build events (queue) →](/guides/integrations/cloudflare-workers/build-events)**.
+::
+
+:partial{content="deployment-public-instance"}
+
+## Getting Started
+
+### Link Your Cloudflare Account
+
+1. In Directus, go to **Settings**.
+2. Under **Modules**, enable **Deployment**.
+3. Open the **Deployment** module from the primary navigation.
+4. Select **Configure Cloudflare Workers** (the label may appear as **Cloudflare Workers** in the provider list).
+5. Provide your credentials:
+ - **Personal Access Token**: a user-scoped Cloudflare API token (not an account token) with at least:
+ - **Workers Builds Configuration: Edit**
+ - **Workers Scripts: Read**
+ - **Account ID**: your Cloudflare account ID (the 32-character hex string shown in the dashboard URL and account overview).
+
+ If you use **[build events via a queue](/guides/integrations/cloudflare-workers/build-events)**, add **Account → Queues → Edit** to that token (read + write) so Directus can pull and acknowledge messages.
+
+ Use **Open Cloudflare Settings** in the form to create or manage tokens in the Cloudflare dashboard.
+6. Click **Save** to validate and continue to project selection.
+
+Directus stores the token encrypted. Changing the token or Account ID after setup can make previously selected Workers unavailable until you update credentials or re-select them.
+
+### Workers Builds Prerequisites
+
+For a Worker to appear as **deployable** in Directus, Cloudflare must have:
+
+- **Workers Builds** enabled for that Worker.
+- A **connected Git repository** and a **build trigger** configured.
+
+If Directus shows that a Worker is not deployable, open **Worker Settings → Builds** in the Cloudflare dashboard and complete setup (the in-app copy points you there).
+
+### Configure Workers
+
+1. From the **Cloudflare Workers** configuration screen, choose **which Workers** Directus should manage.
+2. Click **Save** to store the selection.
+3. Return to integration settings anytime to add or remove Workers.
+
+::callout{icon="material-symbols:warning" color="warning"}
+**Removing Workers**
+
+Removing a Worker from this integration **permanently deletes** all deployment history stored in Directus for that Worker. This cannot be undone.
+::
+
+### Optional: Deploy Hooks
+
+In Cloudflare, create **Deploy Hook** URLs under **Worker Settings → Builds → Deploy Hooks**. In Directus, you can add each hook with a **name** and **URL**. Those hooks appear in the **Deploy** menu as extra actions (for example **Deploy via …**) alongside the default production deploy.
+
+### Optional: Build events (Cloudflare Queue)
+
+Without an **Event Subscription Queue ID**, Directus still triggers builds and updates run status when you open deployment views in the app. To **create and update runs automatically** when builds start or finish in Cloudflare, including builds started by git push or CI, configure a Cloudflare **Queue** with **HTTP pull**, add **Workers Builds event subscriptions** for each Worker, then paste the queue ID in Directus.
+
+Step-by-step guidance (Cloudflare dashboard, Wrangler, tokens, and troubleshooting) lives here:
+
+**[Build events (queue) →](/guides/integrations/cloudflare-workers/build-events)**
+
+### View Your Workers
+
+Once set up, connected Workers appear under the **Cloudflare Workers** provider. From here you can:
+
+- See selected Workers and their deployment activity.
+- Open a Worker to run deployments and browse **deployment runs**, logs, and links.
+
+::callout{icon="material-symbols:shield" color="info"}
+**Permissions**
+
+The Deployment module uses Directus native permissions. See **[Deployment Security](/guides/deployments/security)** for details on configuring roles and access policies.
+::
+
+## Documentation
+
+**[Working with Deployments →](/guides/integrations/cloudflare-workers/deployments)**
+
+Trigger deployments, track build status, and view logs from within Directus.
+
+**[Build events (queue) →](/guides/integrations/cloudflare-workers/build-events)**
+
+Optional: wire Workers Builds into a Cloudflare Queue so Directus can ingest build events without a custom webhook URL.
diff --git a/content/guides/12.integrations/6.cloudflare-workers/build-events.md b/content/guides/12.integrations/6.cloudflare-workers/build-events.md
new file mode 100644
index 000000000..f95032c3f
--- /dev/null
+++ b/content/guides/12.integrations/6.cloudflare-workers/build-events.md
@@ -0,0 +1,79 @@
+---
+id: cloudflare-workers-build-events
+title: Build events (queue)
+description: Optional Cloudflare Queues and Workers Builds event subscriptions so Directus can create and update deployment runs when builds run outside the app.
+technologies:
+ - cloudflare
+---
+
+::callout{icon="material-symbols:info-outline" color="info"}
+**Optional setup**
+
+The Cloudflare Workers deployment provider works without a queue. Trigger builds from Directus and view run status and logs in the app. Add a **queue** when you want runs to update **automatically** for builds started elsewhere (for example git push or CI), similar to webhook-based providers, without hosting your own proxy.
+::
+
+## Before You Start
+
+- Complete the **[Cloudflare Workers](/guides/integrations/cloudflare-workers)** provider setup (token, Account ID, Worker selection).
+- In Cloudflare, enable **Workers Builds** and connect Git for each Worker you will subscribe to.
+
+**[← Back to Cloudflare Workers Integration](/guides/integrations/cloudflare-workers)**
+
+**[Working with Deployments →](/guides/integrations/cloudflare-workers/deployments)**
+
+## What you are configuring
+
+1. A **Cloudflare Queue** that receives Workers Builds events (started, succeeded, failed, canceled).
+2. **HTTP pull** enabled on that queue so the Directus API can pull and acknowledge messages from Cloudflare's queue API.
+3. An **event subscription** per Worker you care about, all writing to the **same** queue. Directus stores **one queue ID**; each message identifies the Worker so Directus can route it to the right project.
+4. In Directus, the **Event Subscription Queue ID** field on the **Cloudflare Workers** provider, plus an API token that can use **Queues** (see below).
+
+## In Cloudflare
+
+1. **Create a queue** (Workers & Pages → **Queues**).
+ - Open **Cloudflare Dashboard** → your account → **Workers & Pages** → **Queues**.
+ - Click **Create queue**.
+ - Give it a clear name (for example `directus-build-events`).
+ - Open the queue details and copy the queue **ID**. Paste this exact ID into Directus later.
+
+ You can also create queues with Wrangler (`queues create`) if your team uses CLI-first workflows.
+
+2. **Enable HTTP pull** on that queue:
+ - In the queue details, open **Consumers**.
+ - Add an **HTTP pull consumer**.
+ - Confirm the queue now shows an HTTP pull consumer as active.
+
+ Wrangler example:
+
+ ```bash
+ npx wrangler queues consumer http add
+ ```
+
+ If the queue already has a **push** consumer, Cloudflare may require you to remove it before HTTP pull works.
+
+3. **Create an event subscription** for each Worker Directus should track:
+ - In the same queue, open **Subscriptions** and click **Add subscription**.
+ - Source: **Workers Builds** / worker (labels in the dashboard may vary).
+ - **Worker**: the script that uses Workers Builds (the same one you deploy from Directus or CI).
+ - **Events**: include at least **started**, **succeeded**, **failed**, and **canceled** (or the subset you need).
+ - Save the subscription and confirm it appears in the queue's subscriptions list.
+
+ Use the dashboard **Subscriptions** UI on the queue, or Wrangler (`queues subscription create`) if the UI is unreliable.
+
+**Multiple Workers:** add one subscription per Worker, each targeting the **same** queue. In Directus you still paste that queue's ID only once.
+
+## In Directus
+
+1. Open **Settings** → **Deployments** (or your product's deployment settings) and edit the **Cloudflare Workers** provider.
+2. Paste the queue **ID** into **Event Subscription Queue ID** and save.
+3. Keep every Worker you want events for **selected** in the provider's project list. Directus matches Cloudflare's worker name on each message to those projects.
+
+**API token:** the token used for this provider needs **Account → Queues → Edit** (read and write) in addition to your existing Workers Builds and Scripts permissions. A single combined token is the usual approach.
+
+**Polling:** Directus pulls the queue on a timer (about **once per minute** by default). Host administrators can override the schedule with the environment variable `DEPLOYMENT_CLOUDFLARE_QUEUE_POLL_SCHEDULE` using the same cron style as other Directus scheduled jobs.
+
+
+## Next Steps
+
+- **[Working with Deployments](/guides/integrations/cloudflare-workers/deployments)**: trigger builds, status, and logs
+- **[← Back to Cloudflare Workers Integration](/guides/integrations/cloudflare-workers)**
diff --git a/content/guides/12.integrations/6.cloudflare-workers/deployments.md b/content/guides/12.integrations/6.cloudflare-workers/deployments.md
new file mode 100644
index 000000000..a6316ba26
--- /dev/null
+++ b/content/guides/12.integrations/6.cloudflare-workers/deployments.md
@@ -0,0 +1,80 @@
+---
+id: cloudflare-deployments
+title: Deployments
+description: Trigger Workers Builds, track deployment status, and view logs for Cloudflare Workers from Directus.
+technologies:
+ - cloudflare
+---
+
+After linking your Cloudflare account and selecting Workers, manage deployments from the **Deployment** module.
+
+**[← Back to Cloudflare Workers Integration](/guides/integrations/cloudflare-workers)**
+
+## Triggering Deployments
+
+1. Open **Deployment**.
+2. Choose **Cloudflare Workers**.
+3. Select the Worker you want to build.
+4. Open the **Deploy** menu (top right):
+ - **Deploy**: triggers a build via the configured production flow (Workers Builds / trigger).
+ - **Deploy via …**: appears when you saved **Deploy Hook** entries; POSTs to that hook URL.
+ - **Refresh**: reloads runs and project data from Cloudflare.
+
+A new run appears in the list with the provider's build identifier when available.
+
+## Monitoring Deployment Status
+
+In the runs list, you will typically see:
+
+- **Deployment ID**: Cloudflare's identifier for the build.
+- **Status**: for example **Building**, **Ready**, **Failed**, **Canceled** (per Directus labels).
+- **Target**: for example production, when Cloudflare exposes it.
+- **Started**: when the build started.
+- **Author**: who triggered the deployment when known.
+
+**How status updates**
+
+- Whenever you open a run or list, Directus asks Cloudflare for the latest status and logs.
+- If you configured an **Event Subscription Queue ID** on the Cloudflare Workers provider, Directus also **polls Cloudflare's queue on a schedule** (about once a minute by default) and updates runs when Workers Builds events arrive. That helps when builds start outside Directus (for example CI). See **[Build events (queue)](/guides/integrations/cloudflare-workers/build-events)**.
+
+If a run still looks stale after a build finishes, reopen the run details to request the latest data from Cloudflare.
+
+## Viewing Build Logs
+
+1. Open a deployment from the Worker's run list.
+2. Review logs as Cloudflare returns them (timestamps and log levels as shown in the UI).
+3. **Search** and filter by log level where available.
+4. **Download** logs if you need a file copy.
+
+## Exporting Logs
+
+1. Open the deployment detail view.
+2. Use **Download** (or the download control shown in the toolbar) to save logs.
+
+## Visiting Builds in Cloudflare
+
+From deployment details, use **Visit** or **Open in Cloudflare Workers** (wording per Directus version) to open the build or dashboard in Cloudflare when a URL is available.
+
+## Canceling a Deployment
+
+If the run is still active and Cloudflare allows canceling it, the detail view may offer **Stop** or cancel with a confirmation. If the action is not available, cancel from the Cloudflare dashboard.
+
+## Best Practices
+
+**Deployment Workflow**
+
+- Complete Workers Builds setup (Git repository and build trigger) in Cloudflare before deploying from Directus.
+- Deploy after publishing content changes that affect your Worker or site.
+- Monitor initial deployments after setup to confirm builds complete successfully.
+
+**Troubleshooting**
+
+- For failed runs, review build logs first, then verify build settings and API token permissions in Cloudflare.
+- Rotate API tokens in Cloudflare and update Directus when you revoke old tokens.
+
+## Next Steps
+
+- **[← Back to Cloudflare Workers Integration](/guides/integrations/cloudflare-workers)**
+- **[Build events (queue)](/guides/integrations/cloudflare-workers/build-events)**: optional queue + subscriptions for automatic run updates
+- **[Deployment Security](/guides/deployments/security)**: roles and access control
+- **[Vercel Integration](/guides/integrations/vercel)** and **[Netlify Integration](/guides/integrations/netlify)**: other supported deployment providers
diff --git a/content/guides/12.integrations/7.framer/.navigation.yml b/content/guides/12.integrations/7.framer/.navigation.yml
new file mode 100644
index 000000000..9dac12af0
--- /dev/null
+++ b/content/guides/12.integrations/7.framer/.navigation.yml
@@ -0,0 +1,2 @@
+title: Framer
+headline: Framer
diff --git a/content/guides/12.integrations/7.framer/0.index.md b/content/guides/12.integrations/7.framer/0.index.md
new file mode 100644
index 000000000..6f7ed44e5
--- /dev/null
+++ b/content/guides/12.integrations/7.framer/0.index.md
@@ -0,0 +1,114 @@
+---
+id: framer-integration
+title: Framer
+description: Connect your Directus collections to Framer's CMS to sync content in both directions using the Directus Framer plugin.
+technologies:
+ - framer
+---
+
+The Directus Framer plugin connects a Framer CMS collection to a Directus collection, letting you pull content into Framer or push edits back to Directus without leaving your project.
+
+::callout{icon="heroicons-outline:rocket-launch"}
+**Quick Start**
+
+1. **Open a collection**: In Framer, create or open a regular CMS collection, then open the Directus plugin from it
+2. **Connect**: Enter your Directus URL and access token, then click **Connect**
+3. **Map and sync**: Select a Directus collection, map your fields, click **Configure Collection**, then run **Sync from Directus** or **Sync to Directus**
+::
+
+## Before You Start
+
+You will need:
+
+- A Framer account with a project open
+- A Directus instance (cloud or self-hosted)
+- A Directus API access token with permissions to read and write the collections you want to sync
+
+To generate an API token in Directus, open **Settings**, go to **Users**, select or create a user, scroll to **Token**, click **Generate Token**, and save.
+
+## How It Works
+
+The plugin runs inside Framer as a panel. You install it once per project and use it for each collection you want to connect to Directus.
+
+Each Framer CMS collection has its own saved Directus connection and field mapping. To connect a second collection, open that collection in Framer, open the plugin again, and configure it separately. The plugin stores each collection's config independently.
+
+Only **regular** (user-created) CMS collections are supported.
+
+## Getting Started
+
+### First-time setup
+
+1. In Framer, create or open a regular CMS collection. Go to **Add data** and select **Collection**, or open an existing one.
+2. Open the **Directus** plugin from within that collection.
+3. Enter your Directus URL and access token, then click **Connect**.
+4. Choose which Directus collection to sync. Select an existing collection from the list, or choose **Create new** to create a new Directus collection based on your Framer fields.
+5. Map your fields: set which field is the slug, which is the ID, and adjust any field types as needed. Click **Configure Collection**. The plugin adds the mapped fields to your Framer collection.
+6. Click **Sync from Directus** to pull items in, or **Sync to Directus** to push your Framer items out.
+
+### Syncing again later
+
+1. Open the same Framer collection.
+2. Open the Directus plugin. It restores the saved configuration automatically.
+3. Run **Sync from Directus** or **Sync to Directus** as needed.
+
+To change the field mapping after your first sync, click **Reconfigure** on the sync screen. The **Back** button is only available before you have run a sync.
+
+## Field Mapping
+
+### The slug field
+
+Every Framer CMS collection requires one field as the **slug** - a unique, URL-safe identifier for each item (for example, `my-article-title`). During field mapping, mark one Directus field as the slug. If none of your Directus fields work as a slug, the plugin can generate one automatically from the item ID.
+
+The slug is used to match items between Framer and Directus on every subsequent sync. Changing the slug field after your first sync will cause items to be treated as new rather than updated.
+
+### Field types
+
+When syncing from Directus to Framer, each Directus field is mapped to a Framer field type. The plugin infers a sensible default:
+
+| Directus type | Default Framer type |
+| ------------------------- | -------------------------------- |
+| Text, string, UUID, JSON | String |
+| Integer, float, decimal | Number |
+| Boolean | Boolean |
+| Date, datetime, timestamp | Date |
+| Image / file relation | Image |
+| Rich text (HTML) | Formatted text |
+| Color | Color |
+| Many-to-one relation | Collection reference (see below) |
+
+You can change any inferred type in the mapping screen before clicking **Configure Collection**.
+
+
+
+### Collection references
+
+A **collection reference** field links an item in your current collection to an item in a different Framer collection (for example, an article linked to its author). These are created from Directus many-to-one (m2o) relation fields.
+
+Collection reference rows appear unchecked by default. To enable one:
+
+1. Check the row to include it.
+2. Select the **related Framer collection** from the dropdown that appears.
+3. Select the **match field** - the field in that related collection that holds the Directus UUID, used to look up the linked item.
+
+Both fields must be set before you can click **Configure Collection**.
+
+## Syncing Data
+
+### Sync from Directus
+
+The plugin fetches items from the Directus collection, converts them to Framer items, and adds or updates them in your Framer collection. Existing items with a matching ID are updated; new items are added. The sync does not wipe the collection - it only adds or updates.
+
+Framer enforces one item per slug. If Directus has duplicate slugs, the plugin keeps the first item and skips the rest. The plugin reports how many items were skipped. Use unique slugs in Directus to avoid this, or sync into a new empty Framer collection for a clean start.
+
+### Sync to Directus
+
+The plugin reads your Framer items, maps them to Directus fields, and creates or updates items in Directus by slug. You can edit item content in Framer and then run **Sync to Directus** to push those changes.
+
+## Conflict Resolution
+
+A conflict occurs when the same item has been updated in both Framer and Directus since the last sync. The plugin detects conflicts in both sync directions.
+
+- **Always overwrite (skip conflict screen) checked**: The plugin uses the source side's version for every item and skips the conflict screen.
+- **Always overwrite (skip conflict screen) unchecked** (default): Items with changes on both sides are listed individually. For each one, click **Use Framer** to keep the Framer version or **Use Directus** to accept the Directus version.
+
+
diff --git a/public/img/cloudflare.svg b/public/img/cloudflare.svg
new file mode 100644
index 000000000..66cc02086
--- /dev/null
+++ b/public/img/cloudflare.svg
@@ -0,0 +1 @@
+
\ No newline at end of file