Docs

orbiter:collections

A Vite virtual module that gives you typed access to your published content in Astro pages. Works in both static (build-time snapshot) and SSR (live queries at request time) output modes.

Setup

The module is available automatically after adding @a83/orbiter-integration to your Astro config. No additional imports needed.

Static output (default)

Content is snapshotted when astro build runs. Pages reflect the pod state at build time — republish to pick up new content.

// astro.config.mjs
import orbiter from '@a83/orbiter-integration';
export default defineConfig({
  integrations: [orbiter({ pod: './content.pod' })],
});

SSR / hybrid output

When output is 'server' or 'hybrid', getCollection and friends query the POD at request time. Content changes are reflected immediately — no rebuild needed.

import node from '@astrojs/node';
import orbiter from '@a83/orbiter-integration';
export default defineConfig({
  output: 'server',
  adapter: node({ mode: 'standalone' }),
  integrations: [orbiter({ pod: './content.pod' })],
});
In SSR mode the POD must be readable at runtime (i.e. on the server). The API surface is identical — only when queries run changes.

API

import { getCollection, getEntry, getLocaleCollection, getLocaleEntry, locale, locales } from 'orbiter:collections';

getCollection(name)

Returns all published entries in a collection, sorted by updated_at descending.

const posts = await getCollection('posts');
// → Entry[]

getEntry(collection, slug)

Returns a single entry by slug, or null if not found or not published.

const post = await getEntry('posts', 'my-first-post');
// → Entry | null

getLocaleCollection(name, locale?)

Returns published entries for a specific locale. The default locale (first entry in Settings → Locales) is stored as locale = '' in the database — pass its code and it maps correctly.

const dePosts = await getLocaleCollection('posts', 'de');
// → Entry[] with locale 'de'

getLocaleEntry(collection, baseSlug, locale)

Returns a locale variant of an entry. Falls back to the default locale if the translation doesn't exist yet.

const post = await getLocaleEntry('posts', 'my-post', 'de');
// → German variant if it exists, otherwise default locale

locale and locales

import { locale, locales } from 'orbiter:collections';
// locale  → 'en'          (default locale from Settings)
// locales → ['en', 'de']  (all configured locales)

Entry shape

{
  id:         string,        // UUID
  slug:       string,        // URL-safe identifier
  status:     'published',
  created_at: string,        // ISO datetime
  updated_at: string,        // ISO datetime
  data: {
    // all fields from your schema, e.g.:
    title:    string,
    body:     string,        // richtext → rendered HTML
    image:    string,        // media field → UUID
    tags:     string[],      // array field
    author:   Entry,         // relation → resolved Entry object
  }
}

Static paths

---
export async function getStaticPaths() {
  const posts = await getCollection('posts');
  return posts.map(post => ({ params: { slug: post.slug } }));
}

const post = await getEntry('posts', Astro.params.slug);
---

Multilingual static paths

---
import { getCollection, locales } from 'orbiter:collections';

export async function getStaticPaths() {
  const posts = await getCollection('posts'); // default locale only
  return posts.flatMap(post =>
    locales.map(loc => ({
      params: { slug: post.slug, lang: loc }
    }))
  );
}
---

Media URLs

<img src={`/orbiter/media/${post.data.image}`} alt="" />

Works regardless of which media backend is configured. For external backends, /orbiter/media/[id] issues a 302 redirect to the CDN or original URL.

orbiter:db

A second virtual module that exposes the resolved pod path for use in your own Astro server routes or API endpoints.

import { podPath } from 'orbiter:db';
import { openPod } from '@a83/orbiter-core';

// src/pages/api/my-endpoint.js
export async function GET() {
  const db      = openPod(podPath);
  const entries = db.getEntries('posts');
  db.close();
  return new Response(JSON.stringify(entries), {
    headers: { 'Content-Type': 'application/json' }
  });
}
orbiter:db only works in server-rendered routes (output: 'server' or 'hybrid'). In static output there is no runtime to open the pod.

Relation fields

Relation fields are resolved automatically — at build time in static mode, at request time in SSR mode. The raw UUID reference is replaced with the full Entry object of the related entry.

{posts.map(post => (
  <div>
    <h2>{post.data.title}</h2>
    <p>by {post.data.author?.data?.name}</p>
    {post.data.categories?.map(cat => (
      <span>{cat.data.name}</span>
    ))}
  </div>
))}