aphex Svelte Themes

Aphex

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

AphexCMS Logo

AphexCMS

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

AphexCMS Responsive Demo

āš ļø Early Development: Expect breaking changes and incomplete features. Not recommended for production use yet.

✨ Features

  • šŸŽØ Sanity-inspired UI - Responsive 3-panel admin interface
  • šŸ”Œ Database Agnostic - PostgreSQL included, MongoDB/SQLite via adapters
  • ā˜ļø Storage Flexible - Local filesystem or S3-compatible (R2, AWS S3, MinIO)
  • šŸ” Auth Agnostic - Bring your own auth (Better Auth included by default)
  • šŸ“ Type-Safe Schemas - Define content models with full TypeScript support
  • āœ… Real-time Validation - Field-level validation with Sanity-style fluent API
  • šŸ”„ Auto-Save - Never lose work with smart draft management
  • šŸ“¦ Hash-Based Publishing - Sanity-style change detection with future versioning support
  • šŸ¢ Multi-Tenancy - Built-in organization support with Row-Level Security
  • šŸ”‘ API Keys - Programmatic access with rate limiting
  • šŸš€ GraphQL Plugin - Auto-generated GraphQL API from your schemas
  • šŸ“š Reference Resolution - Nested depth control with circular protection

šŸ“¦ Packages

Package Description
@aphex/cms-core Database-agnostic core engine with admin UI and API handlers
@aphex/postgresql-adapter PostgreSQL implementation with Drizzle ORM
@aphex/storage-s3 S3-compatible storage (R2, AWS S3, MinIO, etc.)
@aphex/graphql-plugin Auto-generated GraphQL API from schemas
@aphex/ui Shared shadcn-svelte component library
@aphex/studio Reference implementation app

šŸ’” 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 @aphex/ui

šŸš€ Quick Start

Prerequisites

  • Node.js 18+ (use nvm for version management)
  • pnpm 9.0+ (package manager)
  • Docker (for PostgreSQL)

Installation

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

# Configure environment
cd apps/studio
cp .env.example .env
# Default values work for local development
cd ../..

# Start database and migrate
pnpm db:start
pnpm db:migrate

# Start dev server
pnpm dev

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

Storage Configuration (Optional)

By default, uses local filesystem. For cloud storage:

pnpm add @aphex/storage-s3
// apps/studio/src/lib/server/storage/index.ts
import { s3Storage } from '@aphex/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, image, array, object, reference

šŸ› ļø 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!)
  • 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

// Install plugin
import { createGraphQLPlugin } from '@aphex/graphql-plugin';

export default createCMSConfig({
  plugins: [
    createGraphQLPlugin({
      endpoint: '/api/graphql',
      enableGraphiQL: true
    })
  ]
});

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

šŸ› ļø 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 → @aphex/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

We welcome contributions! Here's how to get started:

Development Setup

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

# Start database
pnpm db:start
pnpm db:migrate

# Run dev server
pnpm dev

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
  • Storage Adapters: Implement StorageAdapter interface
  • Field Types: Add Svelte component + TypeScript type
  • Plugins: Implement CMSPlugin interface

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

  • Version history with rollback
  • Real-time collaboration
  • Localization (i18n) support
  • Advanced workflows (approval, scheduling)
  • Media library with folders
  • Content preview system

šŸ™ Acknowledgments

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


Questions? Open an issue or start a discussion

Top categories

Loading Svelte Themes