SonicJS
The edge-native headless CMS for Cloudflare Workers. Sub-100ms response times globally. Zero cold starts. TypeScript-first.
๐ฆ Get Started
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.
๐ Features
Core Platform
- โก Edge-First: Built specifically for Cloudflare Workers with global performance
- ๐ง Developer-Centric: Configuration over UI, TypeScript-first approach
- ๐ค AI-Friendly: Structured codebase designed for AI-assisted development
- ๐ Plugin System: Extensible architecture without core modifications
- ๐ฑ Modern Stack: Hono.js, TypeScript, D1, R2, and HTMX
- ๐ Fast & Lightweight: Optimized for edge computing performance
Advanced Content Management (Stage 5)
- ๐ Rich Text Editor: TinyMCE integration with customizable toolbars
- ๐๏ธ Dynamic Fields: Custom field types (text, number, date, boolean, select, media)
- ๐ Content Versioning: Complete revision history with restore functionality
- โฐ Content Scheduling: Publish/unpublish automation with date controls
- ๐ Workflow System: Draft โ Review โ Published โ Archived with role-based permissions
- ๐พ Auto-Save: Automatic content saving every 30 seconds
- ๐๏ธ Live Preview: Real-time content preview before publishing
- ๐ Content Duplication: One-click content copying and templates
- ๐ก๏ธ XSS Protection: Comprehensive input validation and HTML escaping
๐ How SonicJS Compares
| 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.
๐ Why SonicJS?
Edge Performance
- Global distribution via Cloudflare's network
- Sub-100ms response times worldwide
- Automatic scaling and DDoS protection
- No cold starts - instant responses
Developer Experience
- TypeScript-first with full type safety
- Hot reload development environment
create-sonicjsCLI for instant setup- Comprehensive documentation
AI-Friendly Architecture
- Clean, structured codebase
- TypeScript types for autocomplete
- Clear conventions and patterns
- Built for AI-assisted development
- 12 specialized Claude Code agents for development (View all agents)
๐ Technology Stack
Core Framework
- Hono.js - Ultrafast web framework for Cloudflare Workers
- TypeScript - Strict type safety throughout
- HTMX - Enhanced HTML for dynamic interfaces
Cloudflare Services
- D1 - SQLite database at the edge
- R2 - Object storage for media
- Workers - Serverless compute runtime
- KV - Key-value storage for caching
- Images API - Image optimization and transformation
Development Tools
- Vitest - Fast unit testing
- Playwright - End-to-end testing
- Wrangler - Local development and deployment
- Drizzle ORM - Type-safe database queries
๐ Quick Start
For Application Developers (Using SonicJS)
If 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
For Package Developers (Contributing to SonicJS)
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
Setting Up a Fresh Database
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:resetThis will:
- Create a new D1 database named
sonicjs-worktree-<branch-name> - Apply all migrations
- Update
wrangler.tomlwith the new database ID
Working with Database Migrations
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.tomlpoints 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.
- Create a new migration file in
packages/core/migrations/following the naming pattern:NNN_description.sql(e.g.,027_add_user_preferences.sql) - Write your migration SQL (use
CREATE TABLE IF NOT EXISTSandINSERT OR IGNOREfor idempotency) - Regenerate the migrations bundle:
cd packages/core && npm run generate:migrations - Rebuild the core package:
npm run build:core(or justnpm run buildfrom packages/core - the bundle generation runs automatically as a prebuild step) - Apply to your test database:
cd my-sonicjs-app && wrangler d1 migrations apply DB --local
Important: 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.
Common Commands (For Apps)
# 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
๐ Project Structure
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
โโโ drizzle/ # Database migrations
Important Notes
@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)- No root
src/- Application code lives inpackages/core/or test apps likemy-sonicjs-app/
๐ง Content Management
Creating Collections
SonicJS uses a dynamic field system. Create collections through the admin interface or define them in the database:
-- Example: Blog Posts collection with custom fields INSERT INTO collections (id, name, display_name, description, schema) VALUES ( 'blog-posts', 'blog_posts', 'Blog Posts', 'Article content collection', '{"type":"object","properties":{"title":{"type":"string","required":true}}}' ); -- Add dynamic fields INSERT INTO content_fields (collection_id, field_name, field_type, field_label, field_options) VALUES ('blog-posts', 'title', 'text', 'Title', '{"maxLength": 200, "required": true}'), ('blog-posts', 'content', 'richtext', 'Content', '{"toolbar": "full", "height": 400}'), ('blog-posts', 'excerpt', 'text', 'Excerpt', '{"maxLength": 500, "rows": 3}'), ('blog-posts', 'featured_image', 'media', 'Featured Image', '{"accept": "image/*"}'), ('blog-posts', 'publish_date', 'date', 'Publish Date', '{"defaultToday": true}'), ('blog-posts', 'is_featured', 'boolean', 'Featured Post', '{"default": false}');
Field Types
- text: Single-line text with validation
- richtext: WYSIWYG editor with TinyMCE
- number: Numeric input with min/max constraints
- boolean: Checkbox with custom labels
- date: Date picker with format options
- select: Dropdown with single/multi-select
- media: File picker with preview
๐ API Endpoints
Content Management
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 content
Advanced Features
POST /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 version
Public API
GET /api/content- Get published content (paginated)GET /api/collections/:collection/content- Get content by collectionGET /api/collections- List all collections
๐ Deployment
Deploying Your SonicJS Application
After 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
Environment Configuration
# 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"
๐งช Testing
# Run unit tests npm test # Run tests in watch mode npm run test:watch # Run E2E tests npm run test:e2e # Run E2E tests with UI npm run test:e2e:ui
๐ Documentation
- Project Plan - Development roadmap and stages
- AI Instructions - Comprehensive development guidelines
- Development Guidelines - Development workflow and principles
๐ Plugin Development
Create plugins for extending SonicJS functionality:
// src/plugins/my-plugin/index.ts import { Plugin } from '@sonicjs-cms/core' export default { name: 'my-plugin', hooks: { 'content:beforeCreate': async (content) => { // Plugin logic here return content } } } as Plugin
๐ License
MIT License - see LICENSE file for details.
๐ค Contributing
We welcome contributions! Please see our contributing guidelines for more details.
โค๏ธ Sponsor
SonicJS is 100% open source and free forever. If you find it useful, please consider sponsoring:
100% of sponsorship funds go to marketing - spreading the word about SonicJS to help grow our community. The more developers who know about us, the stronger we become!
SonicJS is a member of Open Source Collective, a 501(c)(3) nonprofit. Donations are tax-deductible for US contributors.
Thank You to Our Sponsors
๐ Support
Built with โค๏ธ for the Cloudflare ecosystem
