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
| Field | Recommended length | Description |
|---|---|---|
| Meta title | 30–60 characters | Overrides the entry title in search results. Leave empty to use the entry title as a fallback in your template. |
| Description | 120–160 characters | Meta description shown in search snippets and social previews. |
| OG Image | 1200×630 px recommended | Open 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.
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.