Skip to content

IcelandicIcecream/aphex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

715 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

AphexCMS Logo

AphexCMS

A Sanity-inspired, database-agnostic CMS built with SvelteKit V2 (Svelte 5)

AphexCMS Responsive Demo

License: MIT SvelteKit TypeScript

✨ Features

  • 🎨 Sanity-inspired admin - Responsive 3-panel editor with mobile navigation, auto-save, validation, version history, and visual preview
  • πŸ”Œ Database adapters - PostgreSQL, embedded Postgres via PGlite, and SQLite/libsql with a shared DatabaseAdapter contract
  • ☁️ Storage flexible - Local filesystem or S3-compatible storage (R2, AWS S3, MinIO)
  • πŸ” Auth agnostic - Bring your own auth; Better Auth integration ships with sessions, organizations, invitations, and API keys
  • πŸ“ Type-safe schemas - Define content models in TypeScript and generate strongly typed Local API collections
  • ✍️ Portable Text rich content - TipTap-backed block editor with custom blocks, inline objects, marks, and annotations
  • πŸ”„ Draft/publish workflow - Auto-save, hash-based change detection, publish/unpublish, and rolling version history
  • πŸ‘οΈ Visual editing - Live preview with stega-encoded click-to-edit overlays via @aphexcms/visual-editing
  • 🏒 Multi-tenancy - Organizations, parent/child hierarchy, capability RBAC, field-level access, and Postgres RLS
  • πŸ”‘ API keys - Org-scoped programmatic access with rate limiting, read/write scopes, and fine-grained capability allowlists
  • πŸš€ Built-in APIs - Local API, Zod-validated HTTP API, generated GraphQL, and Streamable HTTP MCP server
  • πŸ“š Reference resolution - Nested depth control, circular protection, and publish guards for referenced content

πŸ“¦ Packages

Package Description
@aphexcms/cms-core Database-agnostic core engine with admin UI, API handlers, and built-in GraphQL
@aphexcms/postgresql-adapter PostgreSQL implementation with Drizzle ORM
@aphexcms/sqlite-adapter SQLite/libsql implementation (local file: databases and Turso)
@aphexcms/storage-s3 S3-compatible storage (R2, AWS S3, MinIO, etc.)
@aphexcms/nodemailer-adapter Nodemailer/SMTP email adapter (with Mailpit helper for local dev)
@aphexcms/resend-adapter Resend API email adapter for production
@aphexcms/ui Shared shadcn-svelte component library
@aphexcms/visual-editing Live preview overlay, stega helpers, and click-to-edit frontend integration
@aphexcms/base Starter template scaffolded by create-aphex
@aphexcms/blog Blog template with public frontend and visual editing examples
@aphexcms/studio Reference implementation app (drives the template)
create-aphex Scaffolder invoked by pnpm create aphex / npm create aphex@latest

πŸ’‘ Architecture deep-dive: See ARCHITECTURE.md for detailed design patterns and internals.

πŸ’‘ Adding UI components: Run pnpm shadcn <component-name> to add shadcn-svelte components to @aphexcms/ui

πŸš€ Quick Start

Using create-aphex (Recommended)

The fastest way to get started:

pnpm create aphex my-app
# or
npm create aphex my-app
# or
npx create-aphex my-app

This will:

  • Prompt you for a project name
  • Scaffold a full Aphex CMS project
  • Generate a .env file with all required environment variables
  • Provide next steps for starting your project

Then:

cd your-project-name
pnpm install
pnpm db:start      # Start PostgreSQL via Docker
pnpm db:push       # Push database schema
pnpm dev           # Start development server

Prefer no Docker for local development? Use APHEX_DATABASE=sqlite for a local libsql file database, or APHEX_DATABASE=pglite for embedded Postgres semantics.

πŸŽ‰ Admin UI: http://localhost:5173/admin

Manual Installation (Development)

If you want to contribute to Aphex or work with the monorepo:

git clone https://github.com/IcelandicIcecream/aphex.git
cd aphex
pnpm install

Then pick a database.

With SQLite β€” no Docker, no migrations

The fastest path. The schema is pushed on boot, so there's nothing to run but the dev server:

cd apps/studio
cp .env.example .env
echo 'APHEX_DATABASE=sqlite' >> .env
cd ../..

pnpm dev

That's it. The database is created at apps/studio/.aphex/studio.db (gitignored). Email verification is off by default, so the first account you create can sign in immediately β€” no SMTP server needed.

With PostgreSQL

Needs Docker, and an explicit migration step:

cd apps/studio
cp .env.example .env   # default connection string works locally
cd ../..

pnpm db:start          # Postgres + Mailpit via Docker
pnpm db:migrate
pnpm dev

Prefer Postgres semantics without Docker? Set APHEX_DATABASE=pglite for an embedded Postgres persisted to a local folder, then run aphex migrate once before pnpm dev.

πŸŽ‰ Admin UI: http://localhost:5173/admin β€” the first user to sign up becomes super admin.

Storage Configuration (Optional)

By default, uses local filesystem. For cloud storage:

pnpm add @aphexcms/storage-s3
// apps/studio/src/lib/server/storage/index.ts
import { s3Storage } from '@aphexcms/storage-s3';

export const storageAdapter = s3Storage({
	bucket: env.R2_BUCKET,
	endpoint: env.R2_ENDPOINT,
	accessKeyId: env.R2_ACCESS_KEY_ID,
	secretAccessKey: env.R2_SECRET_ACCESS_KEY,
	publicUrl: env.R2_PUBLIC_URL
}).adapter;
// aphex.config.ts
import { storageAdapter } from './src/lib/server/storage';

export default createCMSConfig({
	storage: storageAdapter // Pass your adapter
});

πŸ“– Defining Content Schemas

Content models live in your app as TypeScript objects:

// apps/studio/src/lib/schemaTypes/page.ts
export const page: SchemaType = {
	name: 'page',
	type: 'document',
	title: 'Page',
	fields: [
		{
			name: 'title',
			type: 'string',
			title: 'Title',
			validation: (Rule) => Rule.required().max(100)
		},
		{
			name: 'slug',
			type: 'slug',
			title: 'URL Slug',
			source: 'title', // Auto-generate from title
			validation: (Rule) => Rule.required()
		},
		{
			name: 'content',
			type: 'array',
			title: 'Content Blocks',
			of: [{ type: 'textBlock' }, { type: 'imageBlock' }, { type: 'catalogBlock' }]
		},
		{
			name: 'author',
			type: 'reference',
			title: 'Author',
			to: [{ type: 'author' }] // Reference to other documents
		}
	]
};

Register schemas in your config:

// aphex.config.ts
import { page, author, textBlock } from './src/lib/schemaTypes';

export default createCMSConfig({
	schemaTypes: [page, author, textBlock]
	// ...
});

Available field types: string, text, number, boolean, slug, url, date, datetime, image, file, array, object, reference. Rich text uses Portable Text block arrays: { type: 'array', of: [{ type: 'block' }] }.

πŸ› οΈ Tech Stack

🎨 Admin Interface

The admin UI is a responsive 3-panel layout inspired by Sanity Studio:

  • Desktop: Side-by-side panels (types β†’ documents β†’ editor)
  • Mobile: Stack navigation with breadcrumbs
  • Real-time validation with inline error messages
  • Auto-save every 2 seconds (never lose work!)
  • Draft/publish/version history with preview and restore
  • Visual editing when a schema defines previewUrl
  • Nested reference editing via modal overlays
  • Drag-and-drop array field reordering

πŸ” API Features

Reference Resolution with Depth Control

# Just IDs (default)
GET /api/documents/123

# Resolve first-level references
GET /api/documents/123?depth=1

# Resolve nested references
GET /api/documents/123?depth=2

Circular reference protection prevents infinite loops. Max depth: 5.

GraphQL API

GraphQL is built into cms-core and enabled by default. To customize:

export default createCMSConfig({
	graphql: {
		path: '/api/graphql',
		enableGraphiQL: true
	}
});

Visit /api/graphql for GraphiQL interface with auto-generated schema.

MCP Server

Aphex ships a Streamable HTTP MCP server for AI clients such as Claude Code and Cursor. Scaffolded apps expose it at /mcp with a one-line route re-export:

export { POST, GET, DELETE } from '@aphexcms/cms-core/routes/mcp';

Authenticate with an org-scoped API key:

claude mcp add --transport http aphex http://localhost:5173/mcp \
  --header "x-api-key: your-api-key-here"

Current tools cover schema inspection, validation, document query/create/update/publish, singleton reads/writes, and asset listing.

πŸ› οΈ Development Commands

# Development
pnpm dev              # Start all packages in watch mode
pnpm dev:studio       # Start studio app only
pnpm dev:package      # Start cms-core package only
pnpm dev:docs         # Start dev server

# Building
pnpm build            # Build all packages (Turborepo)
pnpm preview          # Preview production build

# Database
pnpm db:start         # Start PostgreSQL (Docker)
pnpm db:push          # Push schema changes (dev)
pnpm db:generate      # Generate migrations
pnpm db:migrate       # Run migrations (prod)
pnpm db:studio        # Open Drizzle Studio

# Code Quality
pnpm lint             # Prettier + ESLint check
pnpm format           # Format code with Prettier
pnpm check            # Type-check all packages

# UI Components (shadcn-svelte β†’ @aphexcms/ui)
pnpm shadcn button    # Add button component
pnpm shadcn dialog    # Add dialog component
# Components shared between cms-core & studio

πŸ” Authentication

Batteries included with Better Auth:

  • βœ… Session-based auth (email/password)
  • βœ… API keys with rate limiting (10k requests/day)
  • βœ… Multi-tenancy with organizations
  • βœ… Row-Level Security (RLS)

API Key Usage

curl http://localhost:5173/api/documents?docType=page \
  -H "x-api-key: your-api-key-here"

Generate keys from /admin/settings.

Bring your own auth: Implement the AuthProvider interface to use Auth.js, Lucia, or custom solutions.

🀝 Contributing

Code Standards

  • βœ… Format before committing: pnpm format
  • βœ… Type-check: pnpm check
  • βœ… Use Svelte 5 runes ($state, $derived, $effect)
  • βœ… Follow Conventional Commits

Adding Features

  • Database Adapters: Implement DatabaseAdapter interface in a new package + AuthProvider
  • Storage Adapters: Implement StorageAdapter interface
  • Field Types: Add Svelte component + TypeScript type
  • Custom API routes: Register Hono routes/middleware through the api(app) config hook
  • Plugins: A first-class plugin API is planned; today, use schemas, custom routes, adapters, and app-level Svelte components

See ARCHITECTURE.md for detailed extension guides.

Reporting Issues

Include:

  • OS, Node version, pnpm version
  • Steps to reproduce
  • Expected vs actual behavior
  • Error logs (browser console + terminal)

πŸ“š Documentation

🎯 Roadmap

Shipped

  • CLI scaffolding β€” pnpm create aphex / npm create aphex@latest (published as create-aphex)
  • CI/CD pipeline β€” release.yml + sync-template.yml + Changesets
  • Unified Local/HTTP/GraphQL API β€” one schema, three surfaces, Zod-validated contracts
  • Auto-generated GraphQL β€” queries, mutations, filters, GraphiQL
  • MCP server β€” Streamable HTTP endpoint with schema, validation, content, singleton, publish, and asset tools
  • Draft/published workflow β€” hash-based change detection + auto-save
  • Version history β€” rolling per-document versions with configurable maxVersions (GET /api/documents/{id}/versions)
  • Multi-tenancy β€” organizations with parent/child hierarchy + Postgres RLS
  • Email + invitations β€” Better Auth + Resend/Nodemailer adapters, Mailpit in dev
  • Capability-based access control β€” editable built-in roles, custom per-org roles, schema-level and field-level access rules, policy functions
  • API keys β€” rate-limited, per-organization, with either coarse read/write scopes or a fine-grained capabilities allowlist
  • In-memory caching β€” InMemoryCacheAdapter for published reads + API-key lookups
  • Preview config β€” preview: { select: { title, subtitle } } (with dot-paths) on document + object types; rendered in document list, array item rows, and reference picker
  • Visual editing β€” previewUrl, live preview iframe, stega encoding, click-to-edit overlay, and @aphexcms/visual-editing
  • Rich text / block editor β€” Portable Text model with TipTap editor, built-in image blocks, custom block types, inline objects, marks, and annotations
  • Singletons β€” schemas marked singleton: true expose a SingletonCollection<T> surface with get/update/getSingletonId and hide Create/Delete in admin
  • PostgreSQL, PGlite, and SQLite adapters β€” Docker Postgres, embedded Postgres, local file: SQLite, and Turso/libsql support
  • Base and blog templates β€” full auth/storage/email/cache setup plus a public blog/visual-editing example
  • Standalone build β€” pnpm build works without any .env (server modules guarded with building flag); Dockerfile + Procfile ship in the template for Docker / buildpack deploys
  • One-line Vite config β€” aphex() plugin bundles HMR + dayjs alias + SSR/optimizeDeps tuning so consumers don't copy boilerplate
  • Fast schema HMR β€” schema edits hot-swap the engine config without restarting the Vite dev server (~10Γ— faster than restart-on-change)
  • Documentation site β€” docs.getaphex.com with LLM-friendly llms.txt, per-page markdown, and "Copy / Open in ChatGPT / Open in Claude" actions

Near-term (Priority)

  • Public docs cleanup β€” keep README, docs site, templates, and package exports aligned with shipped capabilities
  • Polish admin UI β€” improve empty states, settings flows, onboarding, global navigation, and rough edges
  • Audit log β€” append-only actor/action/resource log with admin UI for compliance and client handoff
  • Command palette β€” global Cmd+K for document search, creation, settings, media, org switching, and common actions
  • Plugin/module API β€” Sanity-style build-time plugin registration with a declarative permission manifest
  • Image transforms β€” on-the-fly resize / format / crop (see TODO-image-transforms.md)
  • Contributor docs expansion β€” adapter authoring guides, field type authoring guide, plugin/module authoring guide

Mid-term

  • Template library β€” more starters beyond base and blog, including premium vertical templates
  • Migration tools β€” import/export utilities for content portability between instances
  • Webhook system β€” event-driven integrations on publish / unpublish / delete
  • Scheduled publishing β€” publish-at / unpublish-at timestamps
  • Media library enhancements β€” folders, tags, bulk actions
  • Redis-backed cache adapter β€” drop-in replacement for InMemoryCacheAdapter
  • Advanced field types β€” code editor, color picker, geopoint
  • Schema-plane MCP tools β€” validated schema creation/update helpers that write schema files and run type generation in dev

Long-term

  • Business modules β€” first-party CRM, customers, people/staff, products/services, bookings/calendar, payments, reviews, and forms
  • Automation engine β€” event triggers, conditions, actions, retries, logs, and workflow history
  • Capability toggles β€” enable native modules without plugin installation or compatibility drift
  • Localization (i18n) support β€” multi-language content with field-level or document-level translation
  • Real-time collaboration β€” multiplayer editing with presence awareness
  • Approval workflows β€” review β†’ approve β†’ publish with role gating
  • Monitoring & observability β€” built-in analytics, slow-query tracking, audit log UI
  • MySQL adapter β€” additional first-party DatabaseAdapter implementation

πŸ™ Acknowledgments

Inspired by Sanity.io β€’ Built with SvelteKit, Drizzle ORM, Better Auth, and shadcn-svelte


Questions? Open an issue or start a discussion

About

A modern, extensible headless CMS built with SvelteKit, featuring a portable core package, database/storage agnostic adapters, and a Sanity-inspired admin interface.

Topics

Resources

License

Contributing

Stars

174 stars

Watchers

2 watching

Forks

Sponsor this project

 

Packages

 
 
 

Contributors