Services First.
Interface Second.
VelvetCMS is a service-oriented CMS. All logic lives in frontend-agnostic services. Three consumers — CLI, REST API, and Web admin — expose them independently. Use all three, two, one, or none.
$ cd velvetcms && php velvet serve
Three Interfaces. One Codebase.
Business logic lives in services. Consumers are thin, optional wrappers. Disable any interface with a single config toggle.
CLI
Automation, cron, CI/CD pipelines
REST API
SPAs, mobile apps, headless frontends
Web Admin
Content editing, media, settings
Content Without Compromise
Not a feature checklist — a coherent content workflow.
Compose with Blocks, Not HTML
Drag-and-drop content blocks with real-time preview. Text, images, code, embeds, custom types. Every block is self-contained with its own schema and rendering. Paste a YouTube or Twitter URL and it resolves to a rich embed automatically via oEmbed.
- Custom block types — define schema, template, CSS
- Multiple editing modes: visual blocks, Markdown, code
- Content locking for concurrent editing
- Reusable content templates across pages
// Register a custom block type
$blocks->register('callout', [
'label' => 'Callout Box',
'icon' => 'megaphone',
'fields' => [
'style' => ['type' => 'select', 'options' => ['info', 'warning', 'tip']],
'title' => ['type' => 'text'],
'content' => ['type' => 'rich-text'],
],
'template' => 'blocks.callout',
]);
Edit Without Fear
Every save creates an automatic revision. Diff any two versions side-by-side with field-level and block-level change highlighting. Restore with one click. For bigger changes, use per-content staging — edit multiple pages, preview the result, then deploy everything atomically.
- Visual side-by-side diff viewer in the admin
- Named snapshots for milestone backups
- Per-content staging, not a full site clone
- Atomic deployment with one-click rollback
// Restore a previous revision
$content->restoreRevision($revisionId);
// Create a staging changeset
$changeset = $staging->createChangeset('Homepage redesign');
$staging->stage($homepage, $changeset);
$staging->stage($aboutPage, $changeset);
// Preview, then deploy
$staging->preview($changeset); // staging URL
$staging->deploy($changeset); // goes live
From Draft to Published — Your Rules
Define review pipelines with approvals, role gates, and automatic transitions. A blog might need just draft to published. An enterprise site could go through legal review, editor approval, and scheduled publication. Shareable draft links let external reviewers see unpublished content without needing a CMS account.
- Custom states and transitions per content type
- Role-based gates with transition comments
- Automatic actions on state change (notify, index, cache)
- Shareable draft links for external reviewers
// Define a workflow
$workflow->define('editorial', [
'states' => ['draft', 'review', 'approved', 'published'],
'transitions' => [
'submit' => ['from' => 'draft', 'to' => 'review'],
'approve' => ['from' => 'review', 'to' => 'approved',
'gate' => 'role:editor'],
'publish' => ['from' => 'approved', 'to' => 'published'],
'reject' => ['from' => 'review', 'to' => 'draft'],
],
]);
Extend Everything
Hooks, a typed extension registry, modular architecture, and a queue system. Built to be extended, not forked.
Hooks System
Filters mutate data as it flows through the system. Actions trigger side effects. If you've used WordPress hooks, you already know the pattern — but typed, testable, and without the global soup.
// Filter: modify content before saving
$hooks->filter('content.before_save', function (Content $content) {
$content->slug = Str::slug($content->title);
return $content;
});
// Action: trigger side effects after publishing
$hooks->action('content.published', function (Content $content) {
$search->index($content);
$cache->invalidate('sitemap');
$webhook->notify('content.published', $content);
});
Extension Registry
Typed registry for UI extension points — sidebar items, settings tabs, dashboard widgets, block types. Validation at registration, duplicate rejection, full discoverability.
Module System
Self-contained packages with routes, views, migrations, and commands. Version constraints, dependency resolution, conflict detection. VelvetCMS itself is a module running on Core.
Queue System
Offload heavy work — media processing, imports, search indexing, webhook delivery. Database-backed with retry logic, failure tracking, and priority lanes.
Built on a Purpose-Built Framework
VelvetCMS runs on Core — a lightweight, explicit PHP framework with no facades, no service locators, no magic. Every dependency is injected. Every call is traceable.
// Explicit. No magic. No surprises.
class PostController
{
public function __construct(
private ContentService $content,
private CacheInterface $cache
) {}
public function show(Request $req, string $slug): Response
{
$post = $this->cache->remember(
"post:{$slug}",
600,
fn() => $this->content->findBySlug($slug)
);
return view('posts.show', ['post' => $post]);
}
}
The Stack
Three layers. Use what you need.
Fleet
Multi-site orchestration, VelvetScore auto-scaling, white-label management.
VelvetCMS
Admin panel, block editor, media library, workflows, SEO, analytics.
Core
Routing, DI, query builder, caching, events, modules, multi-tenancy.
Everything You Need, Built In
19 submodules covering content, media, users, SEO, operations, and more. No plugins required for the basics.
Operations & Monitoring
Know what's happening. Fix it before your users notice.
Health Checks
Database, cache, storage, disk space, queue, scheduler. Reports healthy, degraded, or unhealthy.
VelvetCMS Insight
Local-only metrics: response times, cache hit rates, query counts. Bottleneck detection and actionable configuration recommendations.
Nothing sent externallySnapshots
Full site backups — content, media metadata, menus, settings, redirects, taxonomies. Scheduled daily or weekly. Restore to any point.
Export production, import to stagingRSS & Atom Feeds
Auto-generated feeds for the main site, per content type, per taxonomy term, and per author. Autodiscovery tags included.
Full or excerpt contentComing from WordPress?
Built-in WXR importer handles posts, pages, media, authors, categories, tags, custom fields, and featured images. Everything gets mapped to VelvetCMS equivalents automatically.
- CSV and JSON import formats also supported
- Chunked processing for large sites
- Dry-run mode to preview before committing
- Author mapping via CSV
$ php velvet import:wordpress export.xml \
--author-map=authors.csv \
--dry-run
Parsed 847 posts, 42 pages, 1203 media items.
Mapped 3 authors. 0 conflicts found.
Run without --dry-run to import.
Fair Code. Fair Price.
Core is open source. VelvetCMS is free for non-commercial. Simple.
Core
- Free forever
- Commercial use included
VelvetCMS
- Free for non-commercial
- License for business use
Fleet
- For agencies & scale
- Professional support