SonicJS AI v2.0.0 is a modern, TypeScript-first headless CMS built for Cloudflare's edge platform. This comprehensive guide will help you set up, configure, and start building with SonicJS.
- Prerequisites
- Quick Start
- Development Setup
- Project Structure
- Core Concepts
- First Steps
- Available Scripts
- Troubleshooting
Before you begin, ensure you have the following installed:
- Node.js (version 18 or higher)
- npm or pnpm
- Git
- Cloudflare account (for deployment and production use)
- TypeScript knowledge (project is fully typed)
- Visual Studio Code (for best TypeScript experience)
- Wrangler CLI (installed automatically with dependencies)
Get started in under 60 seconds with the official CLI:
# Create a new SonicJS project
npx create-sonicjs my-cms
# Navigate to project
cd my-cms
# Run database migrations
npm run db:migrate
# Start development server
npm run devYour SonicJS instance will be available at http://localhost:8787
For contributing or developing SonicJS itself:
# Clone the repository
git clone https://github.com/lane711/sonicjs-ai.git
cd sonicjs-ai
# Install dependencies
npm install
# Run database migrations
npm run db:migrate
# Start development server
npm run devgit clone https://github.com/lane711/sonicjs-ai.git
cd sonicjs-ainpm installThis will install all required dependencies including:
- Hono - Ultra-fast web framework
- Drizzle ORM - Type-safe database queries
- Wrangler - Cloudflare Workers CLI
- Vitest - Unit testing framework
- Playwright - E2E testing framework
SonicJS uses Cloudflare D1 (SQLite) for local development and production.
Run migrations locally:
npm run db:migrateThis command applies all database migrations and creates the initial schema including:
- User authentication tables
- Content and collections
- Media library
- Plugin system
- Workflow and automation
- Email templates
Available database commands:
# Generate new migration files (if you modify schema)
npm run db:generate
# Apply migrations to local database
npm run db:migrate
# Apply migrations to production
npm run db:migrate:prod
# Open interactive database studio (Drizzle Studio)
npm run db:studioSonicJS is configured via wrangler.toml instead of .env files.
wrangler.toml (automatically configured):
name = "sonicjs-ai"
main = "src/index.ts"
compatibility_date = "2024-06-01"
[vars]
ENVIRONMENT = "development"
[[d1_databases]]
binding = "DB"
database_name = "sonicjs-dev"
database_id = "your-database-id"
[[r2_buckets]]
binding = "MEDIA_BUCKET"
bucket_name = "sonicjs-media-dev"
[[kv_namespaces]]
binding = "CACHE_KV"
id = "your-kv-id"Key Bindings:
- DB - D1 Database for all data storage
- MEDIA_BUCKET - R2 bucket for media files
- CACHE_KV - KV namespace for caching layer
- ASSETS - Static asset serving
npm run devWhat happens on startup:
-
Bootstrap Phase:
- Runs database migrations
- Syncs collection configurations
- Bootstraps core plugins (auth, media, cache, database-tools, seed-data)
- Installs demo plugins (workflow, FAQ, demo-login)
-
Server Ready:
- Admin interface: http://localhost:8787/admin
- API documentation: http://localhost:8787/api
- Health check: http://localhost:8787/health
sonicjs-ai/
├── docs/ # Documentation (you are here!)
├── src/
│ ├── index.ts # Application entry point
│ ├── middleware/ # Request middleware
│ │ ├── auth.ts # JWT authentication
│ │ ├── bootstrap.ts # App initialization
│ │ ├── logging.ts # Request/security logging
│ │ ├── performance.ts # Cache headers & optimization
│ │ ├── permissions.ts # RBAC authorization
│ │ └── plugin-middleware.ts
│ ├── routes/ # HTTP routes
│ │ ├── admin.ts # Admin dashboard
│ │ ├── api.ts # Public API
│ │ ├── auth.ts # Authentication
│ │ ├── content.ts # Content endpoints
│ │ ├── media.ts # Media upload/management
│ │ └── ...
│ ├── services/ # Business logic
│ │ ├── plugin-service.ts
│ │ ├── plugin-bootstrap.ts
│ │ ├── collection-loader.ts
│ │ ├── collection-sync.ts
│ │ ├── migrations.ts
│ │ ├── logger.ts
│ │ └── ...
│ ├── templates/ # HTML templates
│ │ ├── layouts/ # Page layouts
│ │ ├── pages/ # Full page templates
│ │ └── components/ # Reusable UI components
│ ├── plugins/ # Plugin system
│ │ ├── core/ # Plugin architecture
│ │ ├── core-plugins/ # Built-in plugins
│ │ ├── cache/ # Caching plugin
│ │ └── available/ # Optional plugins
│ ├── collections/ # Collection definitions
│ │ ├── blog-posts.collection.ts
│ │ ├── pages.collection.ts
│ │ └── products.collection.ts
│ ├── types/ # TypeScript types
│ └── cli/ # CLI tools
├── migrations/ # D1 database migrations
├── tests/
│ ├── unit/ # Vitest unit tests
│ └── e2e/ # Playwright E2E tests
├── public/ # Static assets
├── wrangler.toml # Cloudflare Workers config
└── package.json
src/middleware/ - Request processing pipeline:
- Bootstrap → Logging → Auth → Permissions → Routes
src/routes/ - Route handlers organized by domain:
- Public routes (content, auth)
- Admin routes (dashboard, management)
- API routes (RESTful endpoints)
src/services/ - Business logic layer:
- Database operations
- Plugin management
- Collection handling
- Logging and monitoring
src/templates/ - HTMX-powered templates:
- Layouts with navigation/sidebar
- Page templates for admin UI
- Reusable components
src/plugins/ - Extensibility system:
- Core plugin architecture
- Built-in core plugins
- Optional/demo plugins
src/collections/ - Content type definitions:
- TypeScript-based schemas
- Auto-synced to database
- Type-safe content modeling
SonicJS runs on Cloudflare's edge network using V8 isolates (not containers):
- Instant cold starts (< 5ms)
- Global deployment (300+ cities)
- Automatic scaling (unlimited concurrency)
- Zero DevOps (no servers to manage)
Bindings provide access to:
- D1 - Edge-native SQLite database
- KV - Global key-value store
- R2 - S3-compatible object storage
- Queues - Async task processing
SonicJS is built on a powerful plugin architecture:
Core Plugins (auto-installed):
core-auth- Authentication & user managementcore-media- Media upload & R2 storagecore-cache- Three-tiered caching systemdatabase-tools- DB management utilitiesseed-data- Test data generation
Demo Plugins (optional):
workflow- Content workflow & schedulingfaq-plugin- FAQ managementdemo-login-plugin- Pre-filled login credentials
Plugin Lifecycle:
// Plugins can hook into application events
install() -> activate() -> [running] -> deactivate() -> uninstall()Collections define your content types using TypeScript schemas:
// src/collections/blog-posts.collection.ts
export const blogPostsCollection: CollectionConfig = {
name: 'blog_posts',
displayName: 'Blog Posts',
schema: {
type: 'object',
properties: {
title: { type: 'string', required: true },
slug: { type: 'slug' },
content: { type: 'richtext' },
author: { type: 'reference', collection: 'users' },
publishDate: { type: 'datetime' }
}
},
managed: true, // Config-managed (read-only in UI)
isActive: true
}Automatic Syncing:
- Collections are TypeScript files in
src/collections/ - Automatically synced to database on startup
- Type-safe content operations
SonicJS implements intelligent caching across three tiers:
Tier 1: In-Memory Cache
- Fastest access (< 1ms)
- 50MB size limit per worker
- LRU eviction policy
Tier 2: Cloudflare KV
- Global distribution
- Eventually consistent
- 5-60 minute TTLs
Tier 3: D1 Database
- Source of truth
- Strong consistency
- Full query capabilities
Cache Flow:
Request → Memory → KV → Database → Populate KV → Populate Memory → Response
JWT-based Authentication:
- 24-hour token expiration
- Cookie and header support
- KV-based token caching (5-min TTL)
Role-Based Access Control (RBAC):
// Require authentication
requireAuth()
// Require specific role
requireRole(['admin', 'editor'])
// Require permission
requirePermission('manage:content')
// Optional authentication
optionalAuth()User Roles:
admin- Full system accesseditor- Content managementauthor- Content creationviewer- Read-only access
Navigate to http://localhost:8787/admin
Default Credentials (if seed data is loaded):
- Email: admin@sonicjs.com
- Password: sonicjs!
Note: The demo-login-plugin auto-fills these credentials in development.
The admin interface provides:
System Overview:
- Real-time health checks (D1, KV, R2, Webserver)
- Recent activity feed
- Quick actions
Content Management:
- Create/edit/delete content
- Collection-based organization
- Rich text editing with TinyMCE
- Version history
- Workflow states (draft, review, published)
Media Library:
- Drag-and-drop upload
- R2 bucket storage
- Cloudflare Images optimization
- Folder organization
- Bulk operations
User Management:
- User accounts and roles
- Permission assignment
- Activity logging
- API token generation
Plugin Management:
- Install/activate/deactivate plugins
- Plugin settings configuration
- Dependency management
- Activity monitoring
Cache Dashboard:
- Real-time statistics
- Hit rate monitoring
- Manual invalidation
- Pattern-based clearing
Via Admin UI:
- Navigate to Content → New Content
- Select a collection (e.g., "Blog Posts")
- Fill in the fields:
- Title: "My First Post"
- Slug: "my-first-post" (auto-generated)
- Content: Write your content
- Status: "published"
- Click Save
Via API:
# Get auth token
curl -X POST http://localhost:8787/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@sonicjs.com","password":"sonicjs!"}'
# Create content
curl -X POST http://localhost:8787/admin/content \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"collection": "blog_posts",
"title": "My First Post",
"data": {
"slug": "my-first-post",
"content": "<p>Hello World!</p>",
"status": "published"
}
}'Via Admin UI:
- Navigate to Media
- Click Upload Files or drag files into the upload zone
- Select folder destination (optional)
- Add alt text and captions
- Files are automatically uploaded to R2
Via API:
curl -X POST http://localhost:8787/media/upload \
-H "Authorization: Bearer YOUR_TOKEN" \
-F "files=@image.jpg" \
-F "folder=blog-images" \
-F "alt=My Image"Supported Formats:
- Images: JPG, PNG, GIF, WebP, SVG
- Documents: PDF, DOC, DOCX
- Videos: MP4, WebM
- Audio: MP3, WAV
API Documentation: Visit http://localhost:8787/api for interactive OpenAPI docs.
Key Endpoints:
# Health check
GET /health
# List collections
GET /api/collections
# Get all content (paginated)
GET /api/content?limit=50
# Get collection content
GET /api/collections/blog_posts/content
# Get single content item
GET /api/content/:id
# Search content
GET /api/content?search=keywordResponse Format:
{
"data": [...],
"meta": {
"count": 10,
"timestamp": "2025-10-06T...",
"cache": {
"hit": true,
"source": "memory",
"ttl": 3598
},
"timing": {
"total": 15,
"execution": 12,
"unit": "ms"
}
}
}Create a new collection file:
// src/collections/products.collection.ts
import { CollectionConfig } from '../types/collection-config'
export const productsCollection: CollectionConfig = {
name: 'products',
displayName: 'Products',
description: 'E-commerce product catalog',
schema: {
type: 'object',
properties: {
name: {
type: 'string',
required: true,
minLength: 3,
maxLength: 200
},
sku: {
type: 'string',
required: true,
pattern: '^[A-Z0-9-]+$'
},
price: {
type: 'number',
required: true,
minimum: 0
},
description: {
type: 'richtext'
},
images: {
type: 'array',
items: {
type: 'media',
accept: 'image/*'
}
},
category: {
type: 'select',
enum: ['electronics', 'clothing', 'home', 'sports']
},
inStock: {
type: 'boolean',
default: true
},
tags: {
type: 'array',
items: { type: 'string' }
}
}
},
icon: '🛍️',
color: 'blue',
managed: true,
isActive: true,
defaultSort: 'created_at',
defaultSortOrder: 'desc',
listFields: ['name', 'sku', 'price', 'inStock'],
searchFields: ['name', 'sku', 'description']
}Sync the collection:
# Collections are auto-synced on server restart
npm run devThese are the scripts available in your SonicJS application.
| Command | Description |
|---|---|
npm run dev |
Start development server with Wrangler |
npm run deploy |
Deploy to Cloudflare Workers |
npm run type-check |
Run TypeScript type checking |
| Command | Description |
|---|---|
npm run db:migrate:local |
Apply migrations to local D1 database |
npm run db:migrate |
Apply migrations to remote D1 database |
npm run db:reset |
Reset and reinitialize local database |
npm run db:studio |
Open Drizzle Studio (database GUI) |
| Command | Description |
|---|---|
npm test |
Run Vitest unit tests |
npm run test:watch |
Run tests in watch mode |
| Command | Description |
|---|---|
npm run update |
Update @sonicjs-cms/core to latest version |
npm run update:beta |
Update to latest beta version |
If you're contributing to SonicJS and working in the monorepo, these additional scripts are available at the root level.
| Command | Description |
|---|---|
npm run workspace |
Fresh workspace setup (install deps + reset database) |
npm run db:reset |
Reset the local development database |
npm run kill |
Kill workerd process and restart dev server |
| Command | Description |
|---|---|
npm run dev |
Run the demo app (my-sonicjs-app) |
npm run dev:www |
Run the documentation website locally |
npm run build |
Build core package and demo app |
npm run build:core |
Build only the core package |
npm run build:www |
Build the documentation website |
| Command | Description |
|---|---|
npm test |
Run unit tests |
npm run test:watch |
Run tests in watch mode |
npm run test:cov |
Run tests with coverage report |
npm run e2e |
Run Playwright E2E tests |
npm run e2e:ui |
Run E2E tests with UI mode |
npm run e2e:smoke |
Run smoke tests |
npm run type-check |
Run TypeScript type checking |
npm run lint |
Run linting (alias for type-check) |
| Command | Description |
|---|---|
npm run version:patch |
Bump patch version |
npm run version:minor |
Bump minor version |
npm run version:major |
Bump major version |
npm run publish:core |
Build and publish core package |
npm run publish:create-app |
Publish create-sonicjs CLI |
npm run publish:all |
Publish all packages |
npm run release:patch |
Version bump + publish + announce |
npm run release:minor |
Version bump + publish + announce |
npm run release:major |
Version bump + publish + announce |
| Command | Description |
|---|---|
npm run deploy |
Deploy demo app to Cloudflare Workers |
npm run deploy:www |
Deploy documentation website |
Error: Error: no such table: users
Solution:
# Run migrations
npm run db:migrate
# Verify migration status
wrangler d1 migrations list DB --localError: Error: listen EADDRINUSE: address already in use :::8787
Solution:
# Find and kill the process using port 8787
lsof -ti:8787 | xargs kill -9
# Or specify a different port in wrangler.toml
# [dev]
# port = 3000Error: Cannot find module 'hono'
Solution:
# Clear and reinstall dependencies
rm -rf node_modules package-lock.json
npm install
# Clear TypeScript build cache
rm -rf .wranglerError: Cache plugin not showing in admin
Solution:
- Check plugin is in
CORE_PLUGINSarray (src/services/plugin-bootstrap.ts) - Verify plugin manifest exists (
src/plugins/cache/manifest.json) - Restart dev server to trigger bootstrap
- Check bootstrap logs for errors
# Check bootstrap logs
npm run dev 2>&1 | grep -i "bootstrap\|plugin"Issue: Cache statistics show all misses
Solution:
- Verify cache plugin is activated in
/admin/plugins - Check KV binding is configured in
wrangler.toml - Ensure routes have caching enabled
- Review cache configuration in plugin settings
# Test cache directly
curl http://localhost:8787/api/content
# Check response headers for X-Cache-StatusError: Failed to upload to R2
Solution:
- Verify R2 bucket exists and binding is correct in
wrangler.toml - Check bucket permissions
- Ensure file size is under limits (10MB default for images)
- Verify MIME type is allowed
# Test R2 bucket
wrangler r2 bucket list
# Check specific bucket
wrangler r2 bucket info sonicjs-media-devError: Type 'D1Database' is not assignable to...
Solution:
# Update Cloudflare Workers types
npm install --save-dev @cloudflare/workers-types@latest
# Regenerate TypeScript definitions
npx tsc --noEmitError: Build failed: Could not resolve...
Solution:
- Ensure
compatibility_flags = ["nodejs_compat"]is inwrangler.toml - Check for incompatible Node.js modules
- Verify all imports use explicit extensions for TypeScript
# wrangler.toml
compatibility_flags = ["nodejs_compat"]
compatibility_date = "2024-06-01"Hot Reload Issues:
If changes aren't reflected:
- Stop dev server (Ctrl+C)
- Clear Wrangler cache:
rm -rf .wrangler - Restart:
npm run dev
Database Schema Changes:
When modifying the database schema:
- Update migration files in
migrations/ - Run
npm run db:migrate - Update TypeScript types if needed
- Restart dev server
Collection Changes:
When modifying collections:
- Edit collection file in
src/collections/ - Run
npm run sync-collections - Or restart dev server (auto-syncs)
Plugin Development:
When creating new plugins:
- Add plugin to appropriate directory
- Register in plugin registry
- Create manifest.json
- Restart to trigger bootstrap
- Activate in
/admin/plugins
Resources:
Report Bugs:
# Include this information
1. SonicJS version (check package.json)
2. Node.js version (node --version)
3. Operating system
4. Error message and stack trace
5. Steps to reproduceNow that you have SonicJS running, explore these guides:
- Architecture Overview - Understand the system design
- Plugin Development - Build custom plugins
- Collection Configuration - Define content types
- API Reference - Integrate with your frontend
- Caching System - Optimize performance
- Authentication - Secure your application
- Templating - Customize the admin UI
- Deployment - Deploy to production
- Testing - Write unit and E2E tests
- Database Management - Work with D1 and migrations
- Media Management - Handle uploads and R2 storage
- Workflow System - Implement content workflows
Ready to build something amazing? 🚀
Start with Creating Your First Plugin or explore the API Documentation.