Todo lo que hace, en una página.
Verificado en el código que lo ejecuta, el 2 de septiembre de 2026. Nada aquí está planificado o por llegar.
El admin existe en inglés e italiano, así que estas capturas son el conjunto en inglés.
El esquema es el formulario.
Lo que escribes a la izquierda es lo que los editores reciben a la derecha.
fields.text()fields.textarea()fields.richText()fields.number()fields.boolean()fields.datetime()fields.slug()fields.select()fields.relation()fields.media()fields.group()fields.array()fields.json()fields.blocks()
- Flags, no pantallas
- required y localized son dos booleanos en el campo.
- Slug desde el título
- fields.slug({ from: 'title' }) se rellena solo; select lleva opciones fijas.
- También desde el admin
- Las colecciones personalizadas se crean en el admin y se guardan en la base de datos.
Un contenido, cuatro formas de leerlo.
Elige la que tu stack ya habla.
Las entradas públicas no piden clave. Los documentos de back-office piden una clave API o un bearer token.
curl 'https://cms.altovar.net/api/v1/collections/blog-post/entries?locale=en'
{ "data": [ { "id": "fdoc_16d9i3ef", "locale": "en",
"data": { "title": "EU-first content infrastructure", … },
"seo": { "metaTitle": …, "metaDescription": …, "robots": "index,follow" } } ],
"pagination": { "page": 1, "limit": 20, "total": 3, "totalPages": 1 } }
# The back-office route is the same shape, with a key:
curl -H 'x-api-key: sk_…' \
'https://cms.altovar.net/api/v1/collections/blog-post/documents?limit=10' Un cliente tipado con el mismo sobre: data y pagination.
import { OspreyClient } from '@osprey/client'
const osprey = new OspreyClient({
baseUrl: 'https://cms.altovar.net',
tenantId: 'altovar',
})
const { data, pagination } = await osprey
.collection('blog-post')
.listEntries({ locale: 'en', limit: 10 }) Solo consultas, por POST. GraphiQL está disponible en desarrollo.
POST /api/v1/graphql
x-api-key: sk_…
query Posts($limit: Int) {
documents(collectionSlug: "blog-post", status: "published", limit: $limit) {
data { id status data }
pagination { total }
}
} Las entradas llegan a las content collections de Astro al construir. Sin clave en el edge.
---
import { getCollection } from 'astro:content'
const posts = (await getCollection('blog'))
.filter((p) => p.data.locale === 'en')
.sort((a, b) => b.data.publishedAt.localeCompare(a.data.publishedAt))
---
{posts.map((p) => (
<article>
<a href={'/' + p.data.slug}>{p.data.title}</a>
<p>{p.data.excerpt}</p>
</article>
))} Publicas aquí, aparece allí.
Los borradores siguen privados. Una entrada publicada llega al endpoint público en un minuto, y un webhook puede reconstruir el sitio.
- Tres estados
- draft, published, archived. Las páginas añaden revisión, aprobación y programación.
- Webhook firmado
- HMAC-SHA256 sobre el cuerpo en x-osprey-signature. Nueve eventos, secreto cifrado en reposo.
- Cabeceras de caché
- Las lecturas públicas llevan max-age=60 con stale-while-revalidate, listas para cualquier caché delante.
Diez idiomas, una matriz.
Cada campo localizado, cada idioma, contados.
- Idiomas de contenido
- en, it, es, de, fr, nl, pl, sv, pt, ro, definidos por workspace.
- Admin
- Inglés e italiano, se cambian desde la barra superior.
- Cobertura
- Una matriz por página e idioma, y las cadenas que faltan en un CSV.
- Entrega
- Un parámetro de consulta elige el idioma; los alternates hreflang viajan con cada entrada.
Tu dominio, en cuatro pasos.
Hoy por API. La página de ajustes está en camino, y esta página lo dice.
- Reclama Haz POST del host al endpoint de dominios. Queda pendiente.
- Demuestra Añade el registro TXT _osprey-verify.<host> con el token recibido.
- Verifica Haz POST otra vez con verify: true. El host pasa al workspace.
- Apunta CNAME hacia la plataforma. El certificado se emite en la primera petición.
POST /api/v1/admin/domains
Authorization: Bearer <jwt>
{ "host": "www.example.com" }
{ "status": "pending",
"verification": { "type": "TXT",
"name": "_osprey-verify.www.example.com",
"value": "osprey-verify=…" } } Los dominios personalizados dependen del plan o del add-on de hosting.
Un control que muestra su trabajo.
Cada línea de abajo es una ruta y una pantalla, no una hoja de ruta.
- Roles
- admin, editor, author, contributor, viewer
- Claves API
- hash, mostradas una vez, flag de solo lectura, caducidad
- Registro de auditoría
- quién, qué, cuándo y desde dónde, por cada cambio de estado
- Revisiones
- historial de páginas con diff y restauración
- Papelera
- las páginas borradas esperan; las restauras o las borras del todo
- Juntos
- presencia y edición compartida de páginas, campo a campo
- Consentimiento
- banner de cookies y registro de consentimientos con IP en hash
- Supresión y exportación
- una llamada anonimiza a un interesado; exporta desde el admin o la CLI
- Acceso
- OpenID Connect por workspace, o contraseña local
- Límites de tráfico
- un bucket por familia de rutas, límites en las cabeceras de respuesta
Las piezas de alrededor.
Dos paquetes publicados, una CLI, un servidor MCP y un stack self-host.
- @osprey/client
- SDK tipado, renderizador de bloques React, gestor de consentimiento
- @osprey/astro
- loader de contenido, head SEO, sincronización de traducciones
- CLI
- setup, init, dev, build, generate-types, link, export
- Servidor MCP
- dieciséis herramientas por stdio, para el agente de IA que ya usas
- Self-host
- un archivo compose y un asistente de primer arranque en /setup
- Asistente de IA
- traduce huecos, completa el SEO, escribe los alt; apagado hasta que lo enciendes
Tu contenido. Tu servidor. Hoy.
Plan gratuito, sin tarjeta. Alojado en la UE, o en tus propias máquinas.