Tot ce face, pe o singură pagină.

Verificat în codul care îl rulează, pe 2 septembrie 2026. Nimic de aici nu e planificat sau „în curând”.

Adminul există în engleză și italiană, așa că aceste capturi sunt setul englez.

Schema e formularul.

Ce scrii în stânga e ce primesc editorii în dreapta.

  • 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()
Flaguri, nu ecrane
required și localized sunt doi booleeni pe câmp.
Slug din titlu
fields.slug({ from: 'title' }) se completează singur; select poartă opțiuni fixe.
Și din admin
Colecțiile personalizate se creează din admin și stau în baza de date.

Un conținut, patru feluri de a-l citi.

Alege-l pe cel pe care stack-ul tău îl vorbește deja.

Intrările publice nu cer cheie. Documentele de back-office cer o cheie API sau un bearer token.

shellHTTP
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 client tipizat cu același plic: data și pagination.

blog.tsTS
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 })

Doar interogări, prin POST. GraphiQL e disponibil în dezvoltare.

graphqlGQL
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 }
  }
}

Intrările ajung în content collections din Astro la build. Nicio cheie pe edge.

src/pages/index.astroASTRO
---
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>
))}
Citește documentul OpenAPI →

Publici aici, apare acolo.

Ciornele rămân private. O intrare publicată ajunge la endpoint-ul public într-un minut, iar un webhook poate reconstrui site-ul.

Trei stări
draft, published, archived. Paginile adaugă revizuire, aprobare și programare.
Webhook semnat
HMAC-SHA256 peste corp în x-osprey-signature. Nouă evenimente, secret criptat în repaus.
Antete de cache
Citirile publice poartă max-age=60 cu stale-while-revalidate, gata pentru orice cache din față.

Zece limbi, o matrice.

Fiecare câmp localizat, fiecare limbă, numărate.

Limbi de conținut
en, it, es, de, fr, nl, pl, sv, pt, ro, setate per workspace.
Admin
Engleză și italiană, schimbate din bara de sus.
Acoperire
O matrice pe pagină și limbă, iar textele lipsă într-un CSV.
Livrare
Un parametru de query alege limba; alternativele hreflang călătoresc cu fiecare intrare.

Domeniul tău, în patru pași.

Azi prin API. Pagina de setări e pe drum, iar pagina asta o spune.

  1. Revendică Trimite host-ul prin POST la endpoint-ul de domenii. Rămâne în așteptare.
  2. Dovedește Adaugă înregistrarea TXT _osprey-verify.<host> cu tokenul primit.
  3. Verifică Trimite din nou POST cu verify: true. Host-ul trece pe workspace.
  4. Îndreaptă CNAME către platformă. Certificatul e emis la prima cerere.
domainsHTTP
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=…" } }

Domeniile personalizate depind de plan sau de add-on-ul de găzduire.

Un control care își arată munca.

Fiecare rând de mai jos e o rută și un ecran, nu un roadmap.

Roluri
admin, editor, author, contributor, viewer
Chei API
hash, arătate o dată, flag doar-citire, expirare
Jurnal de audit
cine, ce, când și de unde, la fiecare schimbare de stare
Revizii
istoricul paginilor cu diff și restaurare
Coș
paginile șterse așteaptă; le restaurezi sau le ștergi definitiv
Împreună
prezență și editare partajată a paginilor, câmp cu câmp
Consimțământ
banner de cookie-uri și un jurnal al consimțămintelor cu IP în hash
Ștergere și export
un apel anonimizează o persoană vizată; export din admin sau din CLI
Autentificare
OpenID Connect per workspace, sau o parolă locală
Limite de rată
un bucket per familie de rute, limitele în anteturile răspunsului

Piesele din jur.

Două pachete publicate, un CLI, un server MCP și un stack self-host.

@osprey/client
SDK tipizat, renderer de blocuri React, manager de consimțământ
@osprey/astro
loader de conținut, head SEO, sincronizare de traduceri
CLI
setup, init, dev, build, generate-types, link, export
Server MCP
șaisprezece unelte prin stdio, pentru agentul AI pe care îl folosești deja
Self-host
un fișier compose și un asistent la prima pornire pe /setup
Asistent AI
traduce lipsurile, completează SEO, scrie alt-urile; oprit până îl pornești tu

Conținutul tău. Serverul tău. Azi.

Plan gratuit, fără card. Găzduit în UE, sau pe propriile tale mașini.