Skip to content

Astro — quickstart

@ghostwritr/astro is a keyless Content Layer loader for Astro 5+. It syncs your published articles into a collection at build time — then you render them with the normal getCollection / render / <Content /> flow.

  1. Install the loader.

    npm install @ghostwritr/astro
  2. Add your site ID to .env. It’s the only key you need — see Your site ID.

    .env
    GHOSTWRITR_SITE_ID=your-site-id
  3. Define the collection. Pass ghostwritr({ siteId }) as the loader. The loader ships a default schema covering the full article — author, tags, language, canonical, timestamps — so you don’t redefine it:

    src/content.config.ts
    import { defineCollection } from "astro:content";
    import { ghostwritr } from "@ghostwritr/astro";
    export const collections = {
    articles: defineCollection({
    loader: ghostwritr({ siteId: import.meta.env.GHOSTWRITR_SITE_ID }),
    }),
    };
  4. Render an article page. The entry id is the slug, so it’s your route param. render(p) hands back <Content /> from the pre-compiled body:

    src/pages/blog/[slug].astro
    ---
    import { getCollection, render } from "astro:content";
    export const getStaticPaths = async () =>
    (await getCollection("articles")).map((p) => ({
    params: { slug: p.id },
    props: { p },
    }));
    const { p } = Astro.props;
    const { Content } = await render(p);
    const { title, seoTitle, seoDescription, author, publishedAt } = p.data;
    ---
    <title>{seoTitle}</title>
    <meta name="description" content={seoDescription ?? ""} />
    <article>
    <h1>{title}</h1>
    <p>By {author.name} · {publishedAt.toLocaleDateString()}</p>
    <Content />
    </article>
  5. Render the index, newest first. The loader stores articles newest-first, so iterate the collection as-is:

    src/pages/blog/index.astro
    ---
    import { getCollection } from "astro:content";
    const posts = await getCollection("articles");
    ---
    <ul>
    {posts.map((p) => (
    <li><a href={`/blog/${p.id}`}>{p.data.title}</a></li>
    ))}
    </ul>

That’s a complete, statically-generated blog reading from the keyless feed. Run astro dev and open /blog.

  • Collection schema — the default entry.data fields, and how your own schema overrides them. See Collection schema.
  • Publish without a manual rebuild — wire a deploy hook to the feed.updated webhook. See Redeploy on publish and Instant updates.
  • SEO — drive head tags and JSON-LD from the article fields. See SEO & JSON-LD.