# AstroBaaS as a platform
AstroBaaS is built so theme and plugin authors have **stable contracts** to build
against. This doc summarizes the extensibility surface and what's intentionally
deferred. For the stability guarantee see [STABILITY.md](./STABILITY.md); for
hands-on plugin docs see [PLUGIN_DEVELOPMENT.md](./PLUGIN_DEVELOPMENT.md).
## Architecture seams
The codebase is layered so the expensive-to-change parts are isolated behind
interfaces:
```
astrobaas/core (public barrel) ← authors import only this
│
├── models pure domain types (Post, User, Theme, ...)
├── Storage storage contract; LocalDB implements it
├── PluginManager filters/actions + PLUGIN_HOOKS catalog
├── content-types registerContentType() for custom collections
├── sanitizeHtml allow-list HTML sanitizer
└── validate schema validation
│
src/lib/* (internal: lowdb engine, middleware, routes — may change)
```
- **Models are storage-independent** (`src/core/models.ts`) — the data model
doesn't depend on the database engine.
- **`Storage` is an interface** (`src/core/storage.ts`); `LocalDB` conforms via
a compile-time check. A different backend is a drop-in.
- **Plugins/themes import from `astrobaas/core`**, never internal paths.
## What authors can do today
| Capability | Mechanism |
| --- | --- |
| Transform post content/title/list | `POST_CONTENT`, `POST_TITLE`, `API_POSTS_GET` filters |
| Validate/mutate posts before save | `BEFORE_POST_SAVE` filter |
| React to post create/update/delete | `AFTER_POST_SAVE`, `AFTER_POST_DELETE` actions |
| Inject `
` markup | `HEAD_TAGS` filter (sanitized) |
| Add custom content types | `registerContentType()` → generic `/api/content/` CRUD |
| Customize theme tokens | `defineTheme()` + the `ThemeConfig` model (SSR-applied) |
| Reuse core utilities | `sanitizeHtml`, `validate`, `slugify`, `ApiResponseBuilder`, `api` client |
Persisted plugin activation survives restarts; the model is single-node,
trusted, in-process (no sandbox) — appropriate for self-hosting.
## Deferred (planned, contracts not yet frozen)
These are intentionally **not** in the alpha — documented so the boundary is
clear, not hidden:
1. **Installable npm package / Astro integration.** Today AstroBaaS is a repo you
clone and run. Becoming `npm i astrobaas` that drops into an existing Astro
project (injectable routes, adapter-agnostic middleware) is a larger change
gated on real-world usage.
2. **Field-rich content types** — relations, media fields, repeatable groups,
and an admin UI for custom types. The current `registerContentType()` proves
the primitive (scalar fields + generic CRUD API); richer schemas layer on
without changing the registration contract.
3. **Theme/plugin marketplace + dynamic loading from npm.** The static bundled
registry (`src/plugins/index.ts`) is the alpha model: explicit, reviewable,
safe.
4. **Multi-process / clustered deployment.** Partly there: the scheduler and
the migrations run in one process at a time under a database lease, and
settings, redirect and plugin changes reach every process within seconds
(UPGRADE.md U-19). Still single-node on the DEFAULTS: the lowdb file and
the in-memory rate limiter, both replaceable (`DATABASE_URL`,
`RATE_LIMIT_STORE=libsql`), and local-disk uploads, which are not (see
SECURITY.md, STORAGE.md).
## Stability promise (short version)
Everything exported from `astrobaas/core` is the public API. Pre-1.0 it may
change, but breaking changes are always called out under **Breaking** in
[CHANGELOG.md](./CHANGELOG.md), and hook names are never silently renamed.