Quick start
Install Orbiter and run the admin in under 5 minutes.
Requirements
- Node.js 20+
- npm 10+
- An existing Astro 6 project, or start fresh with
orbiter init
Option A — Scaffold a new project
npm install -g @a83/orbiter-cli orbiter init my-site cd my-site npm install
This creates a complete Astro + Orbiter project with sample collections, pages, and a pre-configured content.pod.
Option B — Add to an existing Astro site
1. Install the packages
npm install @a83/orbiter-integration @a83/orbiter-admin @astrojs/node
Note:
@astrojs/node@^10 targets Astro 6. Use @astrojs/node@^9 for Astro 5.2. Configure Astro
// astro.config.mjs
import { defineConfig } from 'astro/config';
import orbiter from '@a83/orbiter-integration';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
integrations: [
orbiter({ pod: './content.pod' }),
],
}); 3. Create the pod and first user
npx @a83/orbiter-cli init --pod-only ./content.pod
Or manually:
node --input-type=module << 'EOF'
import { createPod, hashPassword } from '@a83/orbiter-core';
import { randomUUID } from 'node:crypto';
const db = createPod('./content.pod', { site: { name: 'My Site' } });
const hash = await hashPassword('change-me');
db.insertUser(randomUUID(), 'admin', hash, 'admin');
db.close();
console.log('Pod created.');
EOF Start the admin
ORBITER_POD=$(pwd)/content.pod npx @a83/orbiter-admin
Open http://localhost:4322 and log in with your credentials.
Always use an absolute path for
ORBITER_POD. The server changes its working directory internally, so relative paths break.Start the Astro dev server
In a second terminal:
npm run dev
Both processes share the same content.pod. Changes saved in the admin appear in the Astro site after a browser reload (Astro re-reads the pod on each dev-server request).
Read content in a page
---
// src/pages/blog/[slug].astro
import { getCollection, getEntry } from 'orbiter:collections';
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);
---
<article>
<h1>{post.data.title}</h1>
<div set:html={post.data.body} />
</article> Demo (monorepo)
If you cloned the Orbiter repo:
git clone https://github.com/aeon022/orbiter.git cd orbiter npm install npm run seed ORBITER_POD=$(pwd)/apps/demo/demo.pod npm run dev --workspace=packages/admin
Admin at http://localhost:4322 — login: admin / admin