Available Now

The Framework for
Content Applications

VelvetCMS Core is a lightweight, explicit PHP framework built for content-driven applications. Four runtime dependencies. Sub-millisecond boot. No magic, no facades, no surprises.

$ composer create-project velvetcms/core my-app $ git clone https://github.com/VelvetCMS/core.git

Measured, Not Marketed

Real benchmarks against real frameworks. Same machine, same tests, same conditions.

Hello World

Framework overhead, no DB, no template

Core 0.43ms 2,321 req/s
Symfony 1.13ms 2.6× slower
Laravel 6.53ms 15.2× slower

Database Query

Route → query → JSON response

Core 0.85ms 1,173 req/s
Symfony 4.48ms 5.3× slower
Laravel 6.12ms 7.2× slower

Template Render

Route → data → compiled template → HTML

Core 0.49ms 2,028 req/s
Symfony 4.31ms 8.7× slower
Laravel 6.01ms 12.2× slower

Full Page

Route → DB → template → middleware → response

Core 0.62ms 1,601 req/s
Symfony 4.94ms 7.9× slower
Laravel 7.03ms 11.3× slower

Hello World

Framework overhead, OPcache warm

Core 0.21ms 4,761 req/s
Symfony 0.72ms 3.4× slower
Laravel 3.96ms 18.9× slower

Database Query

Route → cached query → JSON

Core 0.38ms 2,631 req/s
Symfony 2.14ms 5.6× slower
Laravel 5.00ms 13.2× slower

Template Render

Route → data → cached template → HTML

Core 0.26ms 3,846 req/s
Symfony 1.93ms 7.4× slower
Laravel 4.64ms 17.8× slower

Full Page

Route → cached DB → cached template → middleware → response

Core 0.31ms 3,225 req/s
Symfony 2.47ms 8.0× slower
Laravel 5.77ms 18.6× slower

Framework Laptop 16 · Fedora Linux 43 · PHP 8.4.18 · OPcache enabled · SQLite

Benchmarking tools on GitHub — run them yourself

Explicit by Design

Build with primitives you know, optimized for content.

🛤️ Expressive Routing Map URLs to closures or controllers with middleware, groups, and rate limiting.
  • GET, POST, PUT, DELETE, PATCH methods
  • Named routes with programmatic URL generation
  • Required, optional, and wildcard parameters
  • Per-route and global middleware pipelines
PHP
$router->get('/posts/{slug}', [PostController::class, 'show'], 'posts.show');
$router->post('/contact', [ContactController::class, 'submit']);

// Optional parameters
$router->get('/archive/{year?}', function (Request $request, ?string $year = null) {
    return "Archive for " . ($year ?? date('Y'));
});

// Wildcard — captures everything including slashes
$router->get('/docs/{path*}', [DocsController::class, 'render']);
💉 Dependency Injection Explicit core wiring for speed. Autowiring available for your classes when you want it.
  • Core services manually wired for maximum performance
  • Autowiring available as a pragmatic fallback
  • No static proxies or facades
  • Standard injection patterns
PHP
class PageController
{
    public function __construct(
        private PageService $pages,
        private CacheInterface $cache,
    ) {}

    public function show(Request $req, string $slug): Response
    {
        $page = $this->cache->remember(
            "page:{$slug}", 3600,
            fn() => $this->pages->findBySlug($slug)
        );

        return view('pages.show', ['page' => $page]);
    }
}
🔍 Fluent Query Builder Expressive SQL generation with joins, subqueries, and automatic query caching.
  • Chainable query API with prepared statements
  • Joins, subqueries, and aggregates
  • find(), first(), pluck(), paginate() helpers
  • Automatic query caching via cache driver
PHP
$posts = $db->table('posts')
    ->where('status', 'published')
    ->where('published_at', '<=', now())
    ->orderBy('published_at', 'desc')
    ->limit(10)
    ->get();

// Shorthand lookups
$post = $db->table('posts')->find(42);
$titles = $db->table('posts')->pluck('title');
📦 Module System PSR-4 autoloading, dependency resolution, manifest-based loading.
  • Self-contained packages with routes, views, migrations
  • Version constraints and dependency resolution
  • Conflict detection and load-order management
  • module.json manifest for declarative config
JSON
{
    "name": "velvetcms/blog",
    "version": "1.0.0",
    "requires": {
        "velvetcms/core": "^1.0"
    },
    "providers": ["VelvetCMS\\Blog\\BlogModule"]
}
🎨 View Engine Blade-like syntax with layouts, partials, inheritance, and module namespaces.
  • Familiar template syntax with @directives
  • Layout inheritance and section blocks
  • Namespaced views for module isolation
  • Global data sharing via share()
PHP
// Render a view with data
return view('posts.show', ['post' => $post]);

// Namespaced module views
return view('blog::posts.index');

// Share data with all views
$view->share('siteName', 'My Site');
Task Scheduler Fluent cron-style scheduling. Commands or closures, any frequency.
  • Fluent API: hourly(), dailyAt(), everyMinute()
  • Schedule commands or inline closures
  • Overlap prevention and run-on-one-server
  • Output logging and failure notifications
PHP
$schedule->command('sitemap:generate')->dailyAt('03:00');
$schedule->command('cache:prune')->hourly();

$schedule->call(function () {
    $this->analytics->aggregate();
})->everyMinute()->withoutOverlapping();
Smart Caching APCu, File, or Redis. Cache queries, pages, routes, and templates.
  • Three drivers: APCu, File, Redis
  • Query result caching with automatic invalidation
  • Route and compiled view caching
  • remember() pattern for lazy population
PHP
$cache->set('key', $value, 3600);
$value = $cache->get('key');

// Lazy population — only computes if not cached
$stats = $cache->remember('dashboard:stats', 900, function () {
    return $this->analytics->computeStats();
});
📝 Markdown Engine Pluggable drivers with frontmatter extraction, tables, and task lists.
  • Frontmatter extraction (YAML metadata)
  • GFM tables, task lists, strikethrough
  • Pluggable driver architecture
  • Syntax highlighting for code fences
Markdown
---
title: "Getting Started"
author: "Anvyr"
tags: [guide, tutorial]
---

# Welcome to Core

Build something **great** with:

- [x] Routing
- [x] Query builder
- [ ] Your imagination
Validation Service Standalone validator for controllers, CLI, API, and imports.
  • Fluent rule definitions
  • Works in any context: HTTP, CLI, API
  • Custom rules and error messages
  • Request-level validation shorthand
PHP
$v = Validator::make($data, [
    'title'  => 'required|string|max:200',
    'email'  => 'required|email',
    'status' => 'in:draft,published,archived',
]);

if ($v->fails()) {
    $errors = $v->errors();
}
🏗️ Schema Builder Database-agnostic migrations for SQLite, MySQL, PostgreSQL.
  • Blueprint API for table definitions
  • Up/down migrations with rollback
  • Index, foreign key, and constraint support
  • SQLite, MySQL, PostgreSQL drivers
PHP
Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title', 200);
    $table->string('slug')->unique();
    $table->text('content');
    $table->enum('status', ['draft', 'published'])->default('draft');
    $table->timestamps();
});
🌐 Multi-Tenancy Single config switch. Host, path, or custom resolvers with full isolation.
  • Host-based, path-based, or custom resolvers
  • Per-tenant databases, storage, and config
  • Single config switch to enable
  • Tenant-aware paths and URL generation
PHP
// config/tenancy.php
return [
    'enabled'  => true,
    'resolver' => 'host',  // 'host', 'path', or custom class
    'isolate'  => ['database', 'storage', 'cache'],
];
🔬 No Magic No facades, no global state, no hidden behavior.

Every dependency is injected. Every side-effect is explicit. When something breaks, Ctrl+Click takes you directly to the source — no facade resolution, no service container magic, no hidden boot sequence.

4 Runtime dependencies
0 Facades or proxies
0 Global state

Scale with Your Content

Start with files. Evolve to a database. Never rewrite your frontend.

📄

File Driver

Markdown files with frontmatter. Perfect for docs, blogs, small sites.

  • Human-readable, Git-friendly
  • Zero database setup
  • Easy migration from static generators

Hybrid Driver

Files for editing, SQL for metadata. Best of both worlds.

  • Edit as Markdown, metadata indexed in SQL
  • Scales to thousands of pages
  • Automatic sync between file and DB
🗄️

Database Driver

Full SQL storage for high-volume content applications.

  • Everything in DB with full query capabilities
  • Ideal for CMS admin panels
  • SQLite, MySQL, PostgreSQL
🔄

Auto Driver

Automatically selects the best driver based on content type and volume.

  • Recommended default for new projects
  • Switches strategy per content type
  • Zero configuration required

Security by Default

Every layer is hardened. You have to opt OUT of protection.

CSRF Protection

Automatic token validation on all state-changing requests. No opt-in required.

XSS Auto-Escaping

{{ }} escapes by default. Raw output via {!! !!} — explicit, intentional, auditable.

SQL Injection Prevention

Prepared statements everywhere. The query builder never concatenates user input.

Secure Sessions

HTTP-only cookies, SameSite strict, automatic regeneration on authentication changes.

Start Building

One command to get started.

$ composer create-project velvetcms/core my-app $ git clone https://github.com/VelvetCMS/core.git