@nohead/astro brings Nohead into Astro 5.9 or later: a content loader for content collections, and an image service that resizes Nohead’s images through their URLs. It reads the API through the TypeScript SDK, which comes with it, and has releases of its own.
Content collections
noheadLoader loads collections into Astro’s content collections (Astro 5.9 or later), so pages read them with getCollection, getEntry, reference() and render(). Each published record becomes an entry whose id is the record ID and whose data is its fields, when the site builds and when astro dev starts:
- Rich text reads as HTML, for
<Fragment set:html={post.data.summary} />.bodynames one rich text field that moves out ofdataforrender(entry)to render as<Content />. WithrichText: "markdown", rich text reads as Markdown and that field goes through Astro’s own Markdown pipeline (your plugins, syntax highlighting, headings). - Assets named in
expandreplace their ID with the asset: itsimage_url,width,height,altand the rest, ready for<Image>with the image service. - Relations stay record IDs, for
reference()andgetEntry, to the Astro collection named like the related one. If you load it under another name, say so:references: { people: "authors" }. - The record’s own times are in
datatoo:published_at(when it was published; publishing again moves it),created_atandupdated_at, for feeds and a sitemap’slastmod. A date readers see, such as a post’s, is better a date field of its own: Content modelling explains why. - Empty fields are left out of
data, so.optional()fits them. Dates are strings:z.coerce.date()makes themDates. - Dates without a time become
Dates at midnight UTC, as Astro makes front-matter dates. Format them in UTC,date.toLocaleDateString("en-GB", { timeZone: "UTC" }), or west of Greenwich they show as the day before. - Order: Astro keeps no order for a collection, so sort entries in the page:
posts.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()). - Published records are the ones that load, so a published-only key is enough.
filteradds conditions, such as{ featured: true }, andfilter: { published_at: undefined }loads every record, for a key that reads unpublished ones.
schema is only needed to change them. That needs a key with the schema:read scope.
Images
Name the image service in astro.config,image: { service: { entrypoint: "@nohead/astro/image-service" } }, then <Image src={asset.image_url} width={asset.width} height={asset.height} alt={asset.alt ?? ""} />. Images has the details.