Page Storage
File-native pages via `ContentDriver`, with JSON or SQLite page indexing options.
VelvetCMS Core keeps page content file-native. The storage contract is VelvetCMS\Contracts\ContentDriver; the maintained implementation is VelvetCMS\Drivers\Content\FileDriver (content.driver).
How pages are stored #
By default:
- page files live in
user/content/pages - pages can be written as
.mdor.vlt - the CLI writes new pages as
.vlt - frontmatter carries metadata like title, status, layout, excerpt, and publish timestamps
- a page index stores query-friendly metadata so Core does not need to fully parse every page on every listing call
.md and .vlt #
Both extensions are supported by the file driver:
.mdis a straightforward Markdown page with frontmatter..vltis useful when you want block-mode content and template-friendly structure.
When loading a slug, Core checks for .vlt first and then .md. When saving a new page, Core writes .vlt by default.
The page index #
The index is what makes file-native pages practical at scale. It stores metadata extracted from frontmatter, including:
- slug
- title
- status
- layout
- excerpt
- trusted flag
- created, updated, and published timestamps
- custom meta fields
The shipped index backends are:
- JSON, stored in
storage/index/page-index.json - SQLite, stored in
storage/index/page-index.sqlite
See Page Indexing for configuration and rebuild details.
Custom drivers #
Core ships only the file driver, but the page layer still depends on VelvetCMS\Contracts\ContentDriver. If you need a custom implementation, you can override the binding in your bootstrap or module code.
use VelvetCMS\Contracts\ContentDriver;
$app->singleton('content.driver', fn () => new MyCustomContentDriver(...));
$app->alias('content.driver', ContentDriver::class);
That keeps PageService and the rest of the app working against the contract instead of a hard-coded class.
Why Core is file-native now #
Core removed the older database, hybrid, and auto page storage story because it added complexity in the wrong layer. In 2.x, page content stays versionable and inspectable on disk, while the index handles fast lookups and ordering.
If you need relational editorial data, that belongs in your own application layer or the full CMS package, not the Core page driver abstraction.