Docs

Built-in SEO

Every entry has a built-in SEO panel — meta title, description, and OG image. No schema changes needed. Values are available via entry.seo in your Astro templates.

Where to find it

Open any entry in the editor. The SEO section is always visible in the right-hand meta panel, below any custom schema fields. It shows a live SERP preview that updates as you type.

Fields

FieldRecommended lengthDescription
Meta title30–60 charactersOverrides the entry title in search results. Leave empty to use the entry title as a fallback in your template.
Description120–160 charactersMeta description shown in search snippets and social previews.
OG Image1200×630 px recommendedOpen Graph image for social sharing. Picked from the media library.

The char counter turns green when you're in the optimal range, yellow when too short, and red when over the limit.

Accessing SEO values in Astro

SEO fields are available as a top-level seo property on every entry returned by getCollection, getEntry, and the locale variants:

---
import { getCollection } from 'orbiter:collections';
const posts = await getCollection('blog');
---

{posts.map(post => (
  <!-- post.seo.title, post.seo.description, post.seo.ogImage -->
))}

Using in <head>

---
import { getEntry } from 'orbiter:collections';
const entry = await getEntry('blog', Astro.params.slug);
const seoTitle = entry.seo.title || entry.data.title;
const seoDesc  = entry.seo.description;
const ogImage  = entry.seo.ogImage
  ? `/orbiter/media/${entry.seo.ogImage}`
  : '/default-og.png';
---
<html>
<head>
  <title>{seoTitle}</title>
  <meta name="description" content={seoDesc} />
  <meta property="og:title"       content={seoTitle} />
  <meta property="og:description" content={seoDesc} />
  <meta property="og:image"       content={ogImage} />
  <meta name="twitter:card"       content="summary_large_image" />
</head>
...

TypeScript type

The OrbiterSeo interface is included in the auto-generated orbiter-env.d.ts:

interface OrbiterSeo {
  title: string;        // empty string if not set
  description: string;  // empty string if not set
  ogImage: string;      // media ID, or empty string if not set
}

All three fields are always strings (never null/undefined), so you can safely use entry.seo.title || fallback without defensive checks.

Storage

SEO values are stored as data._seo inside the entry's JSON data column. They are independent of the collection schema — you don't need to add any fields to your schema to use them.

Schema SEO fields: If you previously added meta_title, seo_title, or meta_description fields to your collection schema, they still work as before and appear in the Fields section. The built-in _seo panel is separate and does not replace them.