React

Registry privati: token, namespace e installazioni in CI

Come funziona un registry shadcn privato: autenticazione, namespace, scope del token e installazione ripetibile in CI. Con gli errori che si vedono davvero.

In sintesi

  • Un registry privato è un URL più un token: il CLI non conosce il concetto di team.
  • Il namespace separa le fonti nel `components.json` e rende leggibile l’origine di ogni componente.
  • Il token va in CI come secret, con scope minimo e rotazione: mai nel repository.

Un registry privato risponde a una domanda semplice: come installo un componente che non è pubblico, senza copiarlo a mano? La risposta è un endpoint JSON protetto e un token con permessi limitati.

Il protocollo, in breve

Il CLI chiede un item a un URL, riceve un JSON con file, dipendenze e metadati, poi scrive i file nel progetto. Non c’è magia: se l’endpoint risponde 401 o 403, il CLI si ferma.

{
  "registries": {
    "@eneui": {
      "url": "https://ui.eneawork.it/registry/{name}",
      "headers": {
        "Authorization": "Bearer ${ENEUI_TOKEN}"
      }
    }
  }
}

Il namespace `@eneui` è ciò che rende leggibile il comando: `npx shadcn@latest add @eneui/hero`. Senza namespace, due registry con lo stesso nome di blocco diventano ambigui.

Dove mettere il token

ContestoDove vive il tokenCosa evitare
LocaleVariabile d’ambiente della shellFile `.env` committato
CISecret del providerEcho del token nei log
ProduzioneSecret managerToken nel bundle client
TeamPassword manager o vaultToken condiviso via chat

Gli errori che si vedono davvero

SintomoCausa probabileVerifica
401 UnauthorizedHeader assente o token scaduto`curl` con lo stesso header
403 ForbiddenToken valido ma senza accesso all’itemPiano o scope del token
404 Not FoundNome o namespace sbagliatoURL esatto dell’item
402 Payment RequiredItem a pagamento senza accessoStato dell’abbonamento
File scritti ma import rottiDipendenza registry mancante`dependencies` dell’item

Su EneUI il codice dei blocchi Pro è protetto lato server: la preview è pubblica, l’item del registry risponde con un errore esplicito finché non c’è accesso. Il client non riceve il codice prima del pagamento, quindi non c’è nulla da aggirare nel browser.

Installazione ripetibile in CI

# .github/workflows/ui.yml
- name: Install UI blocks
  run: npx shadcn@latest add @eneui/hero @eneui/pricing --yes
  env:
    ENEUI_TOKEN: ${{ secrets.ENEUI_TOKEN }}
  • Fissa la versione del CLI, non usare `latest` in CI.
  • Salva i file generati: l’installazione è deterministica ma la revisione umana no.
  • Fai fallire la pipeline sugli errori 401/402/403: sono configurazione, non rumore.
  • Rigenera il token con una scadenza e conserva solo l’ultimo.

Namespace e provenienza

Con 1.556 blocchi da 28 registry (31 ottobre 2026) lo stesso nome può esistere in più fonti. Il namespace non è decorazione: è la parte del nome che dice da dove arriva il codice e quale licenza si applica.

La pagina /blocks mostra fonte, licenza, file e dipendenze di ogni blocco prima dell’installazione.

Domande frequenti

Un registry privato richiede un server?

No, serve solo un endpoint che restituisca JSON nel formato registry. Può essere statico se non ci sono dati sensibili.

Il token può stare nel `components.json`?

Meglio di no: il file finisce nel repository. Usa una variabile d’ambiente e lascia il segreto fuori.

Perché serve un namespace?

Per distinguere registry diversi con lo stesso nome di item e per rendere esplicita la provenienza nel comando di install.

Cosa significa 402 Payment Required?

Che l’item esiste ma richiede un accesso a pagamento. È diverso da 403: il token è valido, manca il diritto.

Come ruoto un token senza rompere la CI?

Aggiungi il nuovo token come secret, verifica la pipeline, poi revoca il vecchio. Mai revocare prima del deploy.