← Todas as notícias
ARTIGO
27 de setembro de 2026 Atualizado em 24 de setembro de 2026 4 min de leitura

Porque criámos o Osprey, o nosso CMS headless

O Osprey mantém os esquemas de conteúdo em TypeScript, entrega o conteúdo publicado em tempo de build e devolve um 404, não um erro de permissão, para tudo o que é privado.

Neste artigo
  1. Os esquemas são código, não um blob de base de dados
  2. O conteúdo é entregue em tempo de build, não a cada pedido
  3. Privado por padrão, invisível quando negado
  4. Os metadados de SEO viajam com cada entrada
  5. Um único deployment, vários tenants
  6. Mecânica de RGPD, não apenas uma promessa
  7. Headless por conceção
  8. O que fazer

A maioria dos CMS headless obriga a uma escolha: uma ferramenta com editor visual que trata o esquema como um blob de base de dados gerado uma vez, ou uma solução caseira em que cada carregamento de página chama o CMS em tempo real. Criámos o Osprey, o nosso CMS headless, para eliminar essa escolha: um esquema de conteúdo versionado como código e um site publicado como ficheiros estáticos. Eis o que o código faz de facto, não apenas o que a apresentação promete.

Filas de altas estantes cheias de livros no interior de uma biblioteca
Foto: Szeronine (CC BY 4.0), Wikimedia Commons.

Os esquemas são código, não um blob de base de dados

No Osprey, uma coleção é definida em TypeScript e vive no mesmo repositório do resto da aplicação. Isso significa o mesmo controlo de versões, a mesma revisão de código e os mesmos tipos ponta a ponta que uma equipa já aplica ao código da aplicação, agora também ao modelo de conteúdo. A interface de administração é uma comodidade para editar entradas; nunca é a fonte de verdade do esquema.

O conteúdo é entregue em tempo de build, não a cada pedido

O loader @osprey/astro obtém as entradas publicadas a partir do endpoint REST público do Osprey durante o build e entrega-as às content collections do Astro, sem necessitar de uma chave de API para essa leitura pública. O site publicado é HTML estático puro: o Osprey é uma dependência de build, não de runtime. Se um build correr enquanto o CMS está lento ou inacessível, o loader mantém as entradas já em cache em vez de falhar.

Privado por padrão, invisível quando negado

Uma coleção só é exposta na API pública quando a sua própria regra access.read admite explicitamente um chamador anónimo; tudo o resto permanece privado. Um pedido a uma coleção privada, ou a um documento não publicado, devolve um 404 em vez de um erro de permissão, pelo que a API nunca confirma que uma coleção privada exista.

Os metadados de SEO viajam com cada entrada

Cada entrada devolvida pela API pública transporta um objeto de SEO combinado: o título, a descrição, as tags Open Graph e Twitter e o URL canónico próprios da entrada têm prioridade, e os valores predefinidos ao nível do workspace preenchem o que falta. O mesmo payload inclui a diretiva robots resolvida e as ligações hreflang para cada tradução publicada dessa página, para que um frontend possa gerar as suas meta tags sem reconstruir essa lógica.

Um único deployment, vários tenants

O Osprey é multi-tenant: um único deployment pode servir mais do que um site, cada um limitado ao seu próprio tenant. Nas rotas de conteúdo público, o tenant a partir do qual se lê é determinado pelo cabeçalho host do próprio pedido, e não por um valor fornecido pelo cliente, pelo que um pedido anónimo não consegue ler o conteúdo de outro tenant enviando um id diferente. Cada consulta à base de dados executada pela API é limitada internamente ao tenant, sem depender da memória de cada handler.

Mecânica de RGPD, não apenas uma promessa

O Osprey inclui um endpoint de direito ao esquecimento que oculta dados pessoais — submissões de formulários, autores no registo de auditoria, contas de utilizador — para um e-mail ou id indicado, limitado a um tenant. Um endpoint de exportação separado gera um manifesto completo do conteúdo de um tenant para pedidos de portabilidade de dados. O gestor de consentimento de cookies incorporado trata apenas os cookies estritamente necessários como sempre ativos e define todas as outras categorias como recusadas por defeito até o visitante dar consentimento, com «recusar tudo» com o mesmo peso visual que «aceitar tudo». Como o Osprey é autoalojado, uma equipa também pode executá-lo inteiramente em infraestrutura europeia; garantias dedicadas de residência de dados na UE fazem parte do plano enterprise do produto, não de qualquer instalação por defeito.

Headless por conceção

O Osprey guarda o conteúdo e serve-o como JSON; não tem opinião sobre o aspeto de um site. Uma equipa pode construir o frontend em Astro, Next.js ou qualquer gerador de sites estáticos capaz de chamar uma API REST, e usar o Osprey apenas como camada de conteúdo por baixo. Os planos atuais, incluindo as versões autoalojada e enterprise, estão listados na página do produto Osprey.

O que fazer

  • Defina o seu modelo de conteúdo como coleções TypeScript e faça o versionamento junto com o código da aplicação.
  • Defina uma regra access.read explícita em cada coleção que quiser servir através da API pública; deixe-a por definir para manter a coleção privada.
  • Adicione o loader @osprey/astro, ou chame diretamente a API REST, para que o conteúdo seja obtido em tempo de build em vez de a cada pedido.
  • Defina campos de SEO por entrada apenas onde precisam de diferir dos valores predefinidos do site, e deixe estes preencherem o resto.
  • Use os endpoints incorporados de exportação e direito ao esquecimento para pedidos de portabilidade e apagamento de dados, em vez de construir os seus próprios.
  • Se o alojamento exclusivamente na UE for importante para a sua conformidade, aloje o Osprey em infraestrutura europeia ou pergunte pelas garantias de residência do plano enterprise.

Fontes: página do produto Osprey, getosprey.dev.