---
title: Cloudflare Workers
description: "Proxy delle richieste /docs tramite un Worker Cloudflare verso il tuo sito Jamdesk, con configurazione di route e cache."
---

> **For AI agents:** the complete documentation index is at [llms.txt](/docs/llms.txt). Append `.md` to any page URL for its markdown version.

Un [Cloudflare Worker](https://workers.cloudflare.com/) intercetta le richieste a `/docs` sul tuo dominio, le riscrive verso il tuo sottodominio Jamdesk e restituisce la risposta direttamente all'edge, senza bisogno di un server di origine. Puoi creare automaticamente lo scheletro del Worker con `npx jamdesk deploy-proxy cloudflare` oppure configurarlo manualmente come descritto di seguito.

## Come funziona

Il Worker inoltra le richieste al tuo sottodominio Jamdesk e invia il tuo dominio nell'header `X-Jamdesk-Forwarded-Host`, che Jamdesk usa per verificare il dominio e applicare le relative impostazioni. È una **configurazione una tantum**: se in seguito modifichi il dominio o la configurazione nel dashboard, non è necessario aggiornare il Worker.

## Prerequisiti

- Un account Cloudflare con il dominio configurato
- [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/install-and-update/) v3.0 o superiore installato
- Il tuo sottodominio Jamdesk (disponibile nelle impostazioni del dashboard)
- Il tuo dominio personalizzato aggiunto al progetto nel dashboard Jamdesk (il Worker restituisce 403 finché il dominio non è registrato e verificato)
- Un record DNS **proxied** (cloud arancione) sull'hostname che serve la documentazione. I Worker vengono eseguiti solo sui record proxied, quindi anche un dominio che non ospita altro deve averne uno: aggiungi un record `AAAA` segnaposto che punti a `100::` e impostalo come proxied.

## Configurazione rapida con CLI

Il modo più veloce per configurare il tuo Cloudflare Worker:

```bash
npx jamdesk deploy-proxy cloudflare
```

Questo comando interattivo:
1. Verifica che wrangler 3.0 o superiore sia installato
2. Verifica il tuo account Cloudflare e mostra i domini disponibili
3. Risolve il sottodominio Jamdesk dal progetto collegato in `docs.json`
4. Ti consente di selezionare il dominio di destinazione dalle tue zone Cloudflare
5. Genera tutti i file necessari
6. Esegue facoltativamente il deploy su Cloudflare

Se hai accesso a più account Cloudflare, cosa comune per agenzie o team, la CLI ti chiede di sceglierne uno prima della selezione della zona. Seleziona l'account proprietario del dominio su cui stai eseguendo il deploy: le route dei Worker possono essere create solo per i domini dell'account selezionato.

### Configurazione non interattiva

Per eseguire il comando senza prompt, ad esempio in CI o da uno script, passa le risposte come flag:

```bash
jamdesk deploy-proxy cloudflare --slug myproject --domain example.com --yes
```

`--yes` genera i file del Worker e termina. Non esegue mai il deploy: la zona viene dedotta dal dominio invece di essere verificata rispetto al tuo account Cloudflare, quindi rendere attiva questa configurazione resta un passaggio esplicito. Completa con:

```bash
cd cloudflare-worker
npx wrangler deploy
```

Con `--yes` la CLI non può mostrare prompt, quindi deve conoscere il tuo sottodominio. Lo legge dal progetto collegato in `docs.json`; se il collegamento manca, esegui una volta `jamdesk deploy` per aggiungerlo, passa `--slug` esplicitamente oppure il comando terminerà senza fare supposizioni.

Se la directory di output esiste già, `--yes` termina senza sostituirla. Aggiungi `--force` per sovrascriverla oppure `--output-dir` per scrivere in un'altra posizione.

| Opzione | Descrizione |
|--------|-------------|
| `--slug` | Il tuo sottodominio Jamdesk, la `X` in `X.jamdesk.app` (salta il rilevamento automatico) |
| `--domain` | Dominio di destinazione (ad esempio, yoursite.com) |
| `--path` | Prefisso del percorso; deve corrispondere esattamente al sottopercorso del dashboard (predefinito: /docs) |
| `--output-dir` | Directory di output (predefinita: cloudflare-worker/) |
| `--skip-deploy` | Salta il prompt "deploy now?" durante un'esecuzione interattiva (`--yes` non esegue mai il deploy) |
| `--force` | Sovrascrive la directory di output se esiste già |
| `--yes` | Risponde a ogni prompt con il valore predefinito (modalità CI). Non esegue mai il deploy e non sovrascrive mai una directory esistente: combina con `--force` per farlo |

Se preferisci una configurazione manuale, continua con i passaggi seguenti.

---

## Configurazione manuale

### Passaggio 1: crea un Worker

Crea una nuova directory per il Worker e inizializzala:

```bash
mkdir docs-proxy && cd docs-proxy
npm init -y
```

### Passaggio 2: aggiungi il codice del Worker

Crea `index.js` con il seguente codice:

```javascript index.js
/**
 * Jamdesk Documentation Proxy Worker
 *
 * Generated by: jamdesk deploy-proxy cloudflare
 * Proxies /docs/* requests AND their assets to YOUR_SLUG.jamdesk.app
 *
 * Assets under /_jd/* (images, fonts, branding, analytics) must also be proxied
 * since they use absolute paths in the HTML.
 */

const JAMDESK_HOST = "YOUR_SLUG.jamdesk.app";

// Paths that are always proxied to Jamdesk
const PROXY_PATHS = [
  "/docs",  // Documentation pages
  "/_jd/",  // All Jamdesk assets (images, fonts, branding, analytics)
];

function shouldProxy(pathname) {
  return PROXY_PATHS.some(prefix => {
    // For the docs path, require exact match or prefix with slash (not /docs.json)
    if (prefix === "/docs") {
      return pathname === "/docs" || pathname.startsWith("/docs/");
    }
    return pathname.startsWith(prefix);
  });
}

function proxyToJamdesk(request, url) {
  // Rewrite the request to Jamdesk
  const proxyUrl = new URL(request.url);
  proxyUrl.hostname = JAMDESK_HOST;
  // Pin the scheme: an http:// visitor proxied as http:// gets a 308 from
  // Vercel's edge pointing at JAMDESK_HOST, and redirect:"manual" hands that
  // redirect straight to the browser — bouncing the visitor off this domain.
  proxyUrl.protocol = "https:";
  // Setting .protocol leaves a non-default .port in place, so :8787 (wrangler
  // dev) or Cloudflare's alternate http ports (8080, 8880, 2052…) would follow
  // us to the https upstream and fail there.
  proxyUrl.port = "";

  // Clone headers and add proxy headers
  const headers = new Headers(request.headers);
  headers.set("Host", JAMDESK_HOST);
  headers.set("X-Forwarded-Host", url.hostname);
  headers.set("X-Forwarded-Proto", "https");
  // Custom header for domain verification (Vercel strips standard forwarding headers)
  headers.set("X-Jamdesk-Forwarded-Host", url.hostname);

  // Don't follow redirects — let the browser handle them so the URL updates.
  // Without this, redirects happen internally and the browser URL doesn't change,
  // which causes the sidebar to mis-highlight the active page.
  const proxyRequest = new Request(proxyUrl, {
    method: request.method,
    headers,
    body: request.body,
    redirect: "manual",
  });

  // Cache all content types at Cloudflare edge (CF doesn't cache HTML by default).
  // Cache duration is controlled by upstream Cache-Control headers.
  // Never cache redirects or errors — they must always hit origin.
  return fetch(proxyRequest, {
    cf: {
      cacheEverything: true,
      cacheTtlByStatus: { "300-399": 0, "400-499": 0, "500-599": 0 },
    },
  });
}

export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (shouldProxy(url.pathname)) {
      return proxyToJamdesk(request, url);
    }

    // /_next/ is ambiguous: the customer's root site may itself be a Next.js app
    // serving its own /_next/ assets. Try the origin first and fall back to
    // Jamdesk when the origin doesn't have it (404) or can't answer at all
    // (5xx — a docs-only domain has no real origin, so Cloudflare returns 522).
    // Hashed asset filenames never collide between the two apps.
    if (url.pathname.startsWith("/_next/")) {
      let originResponse;
      try {
        originResponse = await fetch(request);
      } catch (err) {
        // Log rather than swallow: a genuine platform fault and a domain with
        // no origin at all are indistinguishable in `wrangler tail` otherwise.
        console.warn("origin fetch threw, serving from Jamdesk:", err);
        return proxyToJamdesk(request, url);
      }
      if (originResponse.status !== 404 && originResponse.status < 500) {
        return originResponse;
      }
      return proxyToJamdesk(request, url);
    }

    return fetch(request);
  },
};
```

<Note>
Sostituisci `YOUR_SLUG` con il tuo sottodominio Jamdesk effettivo, ad esempio `acme` se la documentazione è disponibile all'indirizzo `acme.jamdesk.app`.
</Note>

<Note>
Se usi un sottopercorso personalizzato dal dashboard invece del valore predefinito `/docs`, sostituisci `"/docs"` con il tuo sottopercorso in `PROXY_PATHS` e nel controllo di corrispondenza esatta all'interno di `shouldProxy()`. Il flag `--path` della CLI esegue questa operazione quando genera il file, ma solo su un template **non modificato**; la rigenerazione sovrascrive le voci personalizzate aggiunte manualmente a `PROXY_PATHS`. Se hai personalizzato questo Worker, modifica direttamente le voci `/docs`.
</Note>

<Warning>
L'header `X-Jamdesk-Forwarded-Host` è **obbligatorio** e un header mancante causa un errore silenzioso: le richieste continuano ad avere esito positivo, ma le pagine vengono servite con `noindex` e link canonici che puntano a `YOUR_SLUG.jamdesk.app` invece che al tuo dominio, impedendo ai motori di ricerca di indicizzare la documentazione. Un **403** indica il problema opposto: l'header è presente, ma specifica un dominio non registrato e attivo per questo progetto.
</Warning>

### Passaggio 3: configura wrangler.toml

Crea `wrangler.toml` per configurare il Worker:

```toml wrangler.toml
name = "docs-proxy"
main = "index.js"
compatibility_date = "2024-01-01"

# Serve only via the routes below, not on the public <name>.workers.dev URL —
# that URL is a second way into the same proxy and is worth closing.
workers_dev = false

# Single catch-all route; the worker handles path filtering internally
routes = [
  { pattern = "yoursite.com/*", zone_name = "yoursite.com" },
]
```

<Note>
Se il tuo accesso Cloudflare comprende più di un account, aggiungi anche `account_id = "<your account id>"`: in caso contrario `wrangler deploy` termina invece di scegliere l'account di destinazione. `npx wrangler whoami` elenca gli ID dei tuoi account.
</Note>

<Tip>
Se il tuo sito riceve traffico anche su `www.yoursite.com`, aggiungi una seconda route per fare in modo che il Worker gestisca entrambi:

```toml
routes = [
  { pattern = "yoursite.com/*", zone_name = "yoursite.com" },
  { pattern = "www.yoursite.com/*", zone_name = "yoursite.com" },
]
```
</Tip>

### Passaggio 4: esegui il deploy

Esegui il deploy del Worker su Cloudflare:

```bash
npx wrangler deploy
```

### Passaggio 5: verifica

Visita `https://yoursite.com/docs` per verificare che la documentazione venga servita correttamente.

## Risoluzione dei problemi

<Accordion title="404 del nuovo sottopercorso dopo la ridenominazione nel dashboard">
Se hai rinominato il sottopercorso nel dashboard, ad esempio da `/docs` a `/help`, ma `PROXY_PATHS` del Worker contiene ancora solo `/docs`, le richieste a `/help/*` non raggiungono mai Jamdesk: passano a `fetch(request)` e restituiscono 404 dalla tua origine. Nel frattempo `/docs/*` continua a funzionare, perché Jamdesk serve entrambi i prefissi: proprio per questo il problema è facile da non notare.

**Soluzione:** aggiungi il nuovo sottopercorso a `PROXY_PATHS`. Esegui nuovamente `jamdesk deploy-proxy cloudflare --path <subpath>` se il Worker è ancora un template non modificato, oppure modifica manualmente l'array se lo hai personalizzato.
</Accordion>

<Accordion title="“You are logged in with an API Token. Unset the CLOUDFLARE_API_TOKEN…”">
Wrangler preferisce `CLOUDFLARE_API_TOKEN` al login OAuth e non può avviare un login OAuth mentre il token è impostato. Questo comando richiede OAuth per elencare le zone del tuo account, quindi termina mostrando la posizione del token invece di fallire all'interno di wrangler.

Wrangler legge anche `.env` dalla directory da cui lo esegui, quindi il token può essere impostato per wrangler senza trovarsi nella shell: se `echo $CLOUDFLARE_API_TOKEN` non stampa nulla, il token potrebbe comunque essere presente. Controlla anche la presenza di un `.env` nella directory corrente.

**Soluzione:** concedi al token i permessi `account:read` e `zone:read` ed esegui nuovamente il comando, oppure eseguilo senza il token:

```bash
env -u CLOUDFLARE_API_TOKEN jamdesk deploy-proxy cloudflare
```

Se il token proviene da un `.env`, `env -u` non sarà sufficiente: esegui il comando da una directory priva di tale `.env` oppure sposta temporaneamente il file.
</Accordion>

<Accordion title="Nessun dominio trovato in questo account">
La CLI mostra i domini disponibili prima della selezione della zona. Se visualizzi "No domains found":
1. Verifica di aver effettuato l'accesso all'account Cloudflare corretto
2. Controlla che il dominio sia stato aggiunto e sia attivo nel dashboard Cloudflare
3. Esegui nuovamente la CLI e seleziona "No" quando ti viene chiesto se vuoi continuare con l'account corrente, per cambiare account
</Accordion>

<Accordion title="Account Cloudflare errato">
Se hai più account Cloudflare:
1. Esegui `jamdesk deploy-proxy cloudflare`
2. Quando ti viene chiesto di selezionare un account, scegli quello che contiene il tuo dominio
3. Se hai bisogno di un login completamente diverso, seleziona **"Switch to different login"**
4. La CLI eseguirà il logout e ti chiederà di accedere con le credenziali corrette
</Accordion>

<Accordion title="Zona non trovata durante il deploy">
Questo errore indica che la zona selezionata non corrisponde al tuo account Cloudflare. Potresti:
- aver selezionato una zona appartenente a un altro account
- aver rimosso la zona da Cloudflare

**Soluzione:** esegui nuovamente la CLI e seleziona la zona corretta dall'elenco, oppure passa all'account proprietario della zona.
</Accordion>

<Accordion title="Errori 404 nelle pagine della documentazione">
Assicurati che il pattern della route usi un catch-all: `yoursite.com/*`, non solo `yoursite.com/docs*`. La funzione interna `shouldProxy()` del Worker gestisce il filtraggio dei percorsi.
</Accordion>

<Accordion title="Gli asset non vengono caricati correttamente">
Due cause comuni:

1. **Il Worker non è in esecuzione.** Assicurati che il record DNS sia impostato su **Proxied** (cloud arancione) in Cloudflare. I Worker vengono eseguiti solo sui record proxied.
2. **Header `X-Forwarded-Host` mancante.** Il Worker deve impostare questo header affinché Jamdesk generi URL corretti per gli asset.
</Accordion>

<Accordion title="Errore 403: dominio non autorizzato">
Se visualizzi "Domain is not authorized to serve this content":

1. Verifica che il dominio sia registrato nel dashboard Jamdesk
2. Completa la verifica DNS (record TXT) del dominio
3. Assicurati che l'header `X-Jamdesk-Forwarded-Host` sia impostato nel codice del Worker
4. Controlla che il dominio sia associato al progetto corretto

Il dominio deve essere verificato prima che il Worker possa servire la documentazione.
</Accordion>

<Accordion title="Il Worker non si attiva sul dominio root (apex)">
I Worker vengono eseguiti solo sui record DNS **proxied** (cloud arancione). Se il record A è impostato su "DNS only" (cloud grigio), le richieste passano direttamente all'origine e ignorano completamente il Worker.

**Soluzione:** imposta il record A come proxied (cloud arancione) nel DNS Cloudflare. Lo stesso vale per i sottodomini: qualsiasi record con una route Worker deve essere proxied.
</Accordion>

<Accordion title="La verifica del dominio è bloccata su Pending">
Jamdesk verifica la proprietà leggendo direttamente i valori del record DNS. Il proxy Cloudflare (cloud arancione) nasconde questi valori, quindi la verifica non può essere completata.

**Soluzione:**
1. Imposta il record DNS su **DNS only** (cloud grigio)
2. Attendi il completamento della verifica, quando lo stato diventa **active** nel dashboard
3. Imposta nuovamente il record su **Proxied** (cloud arancione) affinché il Worker venga eseguito

In breve: **cloud grigio** per verificare → **cloud arancione** per servire.
</Accordion>

<Accordion title="Come funziona la cache">
Jamdesk serve l'HTML della documentazione con `Cache-Control: no-store`, quindi Cloudflare non memorizza le pagine nella cache all'edge (`cf-cache-status: BYPASS`). Ogni richiesta esegue il rendering della versione corrente e le modifiche pubblicate diventano immediatamente visibili, senza ritardi dovuti alla cache.

Gli asset statici in `/_next/` e `/_jd/` (JavaScript, CSS, font, immagini) vengono serviti con header di cache `immutable` di lunga durata, quindi Cloudflare li memorizza nella cache all'edge. I nomi dei file contengono un hash del contenuto, quindi ogni build produce nuovi URL e gli asset aggiornati vengono recuperati automaticamente. Non è necessario eseguire il purge.

`cacheEverything: true` consente a Cloudflare di memorizzare nella cache questi asset statici sulla route proxied; non sovrascrive `no-store` per l'HTML. Per cancellare manualmente la cache all'edge, usa **Purge Cache** di Cloudflare (Caching → Configuration → Purge Everything).
</Accordion>

<Accordion title="Versione di Wrangler troppo vecchia">
La CLI richiede wrangler 3.0 o superiore. Aggiorna con:

```bash
npm install -g wrangler@latest
```
</Accordion>

## Qual è il prossimo passo?

<Columns cols={3}>
  <Card title="Solo dominio personalizzato" icon="eye-slash" href="/it/deploy/custom-domain-only">
    Impedisci al tuo sottodominio di rispondere direttamente
  </Card>
  <Card title="Domini personalizzati" icon="globe" href="/it/deploy/custom-domains">
    Verifica il DNS e risolvi i problemi
  </Card>
  <Card title="Hosting su sottopercorso" icon="folder-tree" href="/it/deploy/subpath-hosting">
    Servi la documentazione su /docs
  </Card>
</Columns>