The edge-native headless CMS for Cloudflare Workers. Sub-100ms response times globally. Zero cold starts. TypeScript-first.
npx create-sonicjs@latest my-app
⚠️ Note: This repository is for developing the SonicJS core package. To build an application with SonicJS, use the command above to create a new project.
No Cloudflare account? Run SonicJS on any server with Docker and SQLite:
docker build -t sonicjs .
docker run -d --name sonicjs -p 3000:3000 \
-v $(pwd)/data:/app/data \
-e JWT_SECRET=$(openssl rand -base64 32) \
-e BETTER_AUTH_SECRET=$(openssl rand -base64 32) \
sonicjs
# Create the first admin user
docker exec sonicjs npm run reset
# → admin@sonicjs.com / sonicjs! (change after first login)
See the Self-Hosting guide for Docker Compose, Node.js, backup strategy, and production hardening.
| SonicJS | Strapi | Payload | |
|---|---|---|---|
| Edge-native | Yes | No | No |
| Cloudflare Workers | Yes | No | Limited |
| Cold starts | None | 2-5s | 1-3s |
| Response time | <100ms | 200-500ms | 150-400ms |
| Database | D1 (SQLite at edge) | PostgreSQL/MySQL | MongoDB/PostgreSQL |
| Global distribution | Built-in | Requires setup | Requires setup |
SonicJS is the only production-ready CMS built specifically for edge computing. We have 46x more development activity per GitHub star than Strapi.
create-sonicjs CLI for instant setupIf you want to build an application with SonicJS:
# Create a new SonicJS application
npx create-sonicjs@latest my-app
# Navigate to your app
cd my-app
# Start development server
npm run dev
# Visit http://localhost:8787
Your app will be created with:
- ✅ SonicJS CMS pre-configured
- ✅ Database migrations ready
- ✅ Example content collections
- ✅ Admin interface at /admin
- ✅ Ready to deploy to Cloudflare
If you want to contribute to the SonicJS core package:
# Clone this repository
git clone https://github.com/lane711/sonicjs-ai.git
cd sonicjs-ai
# Install dependencies
npm install
# Build the core package
npm run build:core
# Create a test app to validate changes
npx create-sonicjs@latest my-sonicjs-app
# Run tests
npm test
When working in a new worktree or wanting to reset your local database, run from the project root:
# Create a fresh D1 database for your branch
npm run db:reset
This will:
- Create a new D1 database named sonicjs-worktree-<branch-name>
- Apply all migrations
- Update wrangler.toml with the new database ID
When developing the core package, migrations are located in packages/core/migrations/. Your test app will reference these migrations through the npm workspace symlink.
From your test app directory (e.g., my-sonicjs-app/):
# Check migration status (local D1 database)
wrangler d1 migrations list DB --local
# Apply pending migrations to local database
wrangler d1 migrations apply DB --local
# Apply migrations to production database
wrangler d1 migrations apply DB --remote
Important Notes:
- The test app's wrangler.toml points to: migrations_dir = "./node_modules/@sonicjs-cms/core/migrations"
- Since the core package is symlinked via npm workspaces, changes to migrations are immediately available
- After creating new migrations in packages/core/migrations/, rebuild the core package: npm run build:core
- Always apply migrations to your test database before running the dev server or tests
Creating New Migrations:
SonicJS uses a build-time migration bundler because Cloudflare Workers cannot access the filesystem at runtime. All migration SQL must be bundled into the application code.
packages/core/migrations/ following the naming pattern: NNN_description.sql (e.g., 027_add_user_preferences.sql)CREATE TABLE IF NOT EXISTS and INSERT OR IGNORE for idempotency)cd packages/core && npm run generate:migrationsnpm run build:core (or just npm run build from packages/core - the bundle generation runs automatically as a prebuild step)cd my-sonicjs-app && wrangler d1 migrations apply DB --localImportant: After modifying any .sql files in migrations/, you must rebuild the package. The SQL files are not used at runtime - only the generated migrations-bundle.ts file is included in the build.
# Start development server
npm run dev
# Deploy to Cloudflare
npm run deploy
# Database operations
npm run db:migrate # Apply migrations
npm run db:studio # Open database studio
# Run tests
npm test
This is a package development monorepo for building and maintaining the SonicJS CMS npm package.
sonicjs-ai/
├── packages/
│ ├── core/ # 📦 Main CMS package (published as @sonicjs-cms/core)
│ │ ├── src/
│ │ │ ├── routes/ # All route handlers (admin, API, auth)
│ │ │ ├── templates/ # HTML templates & components
│ │ │ ├── middleware/# Authentication & middleware
│ │ │ ├── utils/ # Utility functions
│ │ │ └── db/ # Database schemas & migrations
│ │ └── package.json # @sonicjs-cms/core
│ ├── templates/ # Template system package
│ └── scripts/ # Build scripts & generators
│
├── my-sonicjs-app/ # 🧪 Test application (gitignored)
│ └── ... # Created with: npx create-sonicjs@latest
│ # Used for testing the published package
│
├── www/ # 🌐 Marketing website
└── tests/e2e/ # End-to-end test suites
⚠️ This is NOT an application repository - it's for developing the @sonicjs-cms/core npm package.
packages/core/ - The main package published to npmmy-sonicjs-app/ - Test installation for validating the published package (can be deleted/recreated)src/ - Application code lives in packages/core/ or test apps like my-sonicjs-app/Collections are TypeScript config objects registered at app startup — no database table required.
// src/collections/blog-posts.collection.ts
import type { CollectionConfig } from '@sonicjs-cms/core'
export default {
name: 'blog_post',
displayName: 'Blog Post',
slug: 'blog-posts',
description: 'Article content collection',
schema: {
type: 'object',
properties: {
title: { type: 'string', title: 'Title', required: true, maxLength: 200 },
content: { type: 'lexical', title: 'Content', required: true },
publishedAt: { type: 'datetime', title: 'Published Date' },
},
required: ['title', 'content'],
},
managed: true,
isActive: true,
} satisfies CollectionConfig
// src/index.ts — register before createSonicJSApp
import { registerCollections, createSonicJSApp } from '@sonicjs-cms/core'
import blogPostsCollection from './collections/blog-posts.collection'
registerCollections([blogPostsCollection])
export default createSonicJSApp({ plugins: { register: [] } })
GET /admin/content/new?collection=id - Create new content formGET /admin/content/:id/edit - Edit content formPOST /admin/content/ - Create content with validationPUT /admin/content/:id - Update content with versioningDELETE /admin/content/:id - Delete contentPOST /admin/content/preview - Preview content before publishingPOST /admin/content/duplicate - Duplicate existing contentGET /admin/content/:id/versions - Get version historyPOST /admin/content/:id/restore/:version - Restore specific versionGET /admin/content/:id/version/:version/preview - Preview historical versionGET /api/content - Get published content (paginated)GET /api/collections/:collection/content - Get content by collectionGET /api/collections - List all collectionsAfter creating your app with npx create-sonicjs@latest:
# 1. Configure your Cloudflare project
# Update wrangler.toml with your project settings
# 2. Create production database
wrangler d1 create my-app-db
# 3. Apply database migrations
npm run db:migrate:prod
# 4. Deploy to Cloudflare Workers
npm run deploy
Your app will be live at: https://your-app.workers.dev
# wrangler.toml
name = "my-sonicjs-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "your-database-id"
[[r2_buckets]]
binding = "MEDIA_BUCKET"
bucket_name = "my-app-media"
```bash
npm test
npm run test:watch
npm run t
$ claude mcp add sonicjs \
-- python -m otcore.mcp_server <graph>