statamic/cms
Statamic is a flat-file-first CMS for Laravel, powered by Git. Install this core Composer package into an existing Laravel app to build fast, beautiful, easy-to-manage websites with a flexible content model and control panel.
Installation
composer require statamic/cms
Requires Laravel 10+ and PHP 8.1+. Follow the official installation guide for full setup.
Publish Core Config
php artisan vendor:publish --provider="Statamic\Providers\StatamicServiceProvider" --tag="config"
This generates config/statamic.php with default settings.
First Use Case: Create a Collection
php artisan statamic:make collection blog
This creates a blog collection in content/collections/blog/. Edit the YAML file to define fields (e.g., title, body).
Define a Blueprint
Create resources/blueprints/collections/blog/entry.yaml:
title: Blog Post
sections:
main:
display: Main
fields:
- title
- handle
- body
Access the Control Panel
Visit /statamic/cp (or your configured CP URL). Log in with default credentials (email: admin@example.com, password: password).
Collections & Entries
Use Statamic::collections() to fetch collections dynamically:
$blogPosts = Statamic::collections()->find('blog')->entries()->all();
Filter entries with query builder:
$publishedPosts = Statamic::collections()->find('blog')->entries()
->where('status', 'published')
->get();
Field Types
Leverage built-in field types (e.g., title, body, assets) or create custom ones. Example for a replicator:
fields:
- replicator:
display: Features
fields:
- feature_title
- feature_description
Localization
Enable multilingual support in config/statamic.php:
'localization' => [
'enabled' => true,
'locales' => ['en', 'fr'],
],
Access localized content:
$entry->get('title', ['locale' => 'fr']);
Uploading Assets
Use the Assets field type in blueprints or upload via the CP. Access assets programmatically:
$asset = Statamic::assets()->find('path/to/image.jpg');
$url = $asset->url();
Image Manipulation
Use presets defined in config/statamic/asset_containers/your_container/images.php:
$asset->width(800)->height(600)->crop()->url();
Antlers Templating
Use Antlers tags in templates (resources/views/):
{{ entries:blog }}
<h2>{{ title }}</h2>
{{ body }}
{{ /entries }}
Or in partials (resources/views/partials/):
{{ partial:'header' }}
Dynamic Routes
Define routes in routes/web.php:
Route::get('/blog/{entry}', function ($entry) {
return view('blog.post', ['entry' => $entry]);
})->name('blog.post');
form:
fields:
- name
- email
- message
submit_button: Send Message
Handle submissions in a controller:
public function store(Request $request) {
$submission = Form::submit($request);
// Process submission
}
config/statamic/navigation.php:
'main' => [
'items' => [
['url' => '/', 'title' => 'Home'],
['url' => '/blog', 'title' => 'Blog'],
],
],
Display in a view:
{{ nav:'main' }}
Create a Widget Publish the widget stub:
php artisan vendor:publish --provider="Statamic\Providers\StatamicServiceProvider" --tag="widgets"
Extend app/Widgets/YourWidget.php:
namespace App\Widgets;
use Statamic\Widgets\Widget;
class YourWidget extends Widget {
public function getTitle(): string {
return 'Your Widget';
}
public function getContent(): string {
return view('widgets.your-widget')->render();
}
}
Register the Widget
Add to config/statamic/cp/widgets.php:
'dashboard' => [
'widgets' => [
\App\Widgets\YourWidget::class,
],
],
GraphQL Endpoints
Enable in config/statamic.php:
'graphql' => [
'enabled' => true,
],
Query entries via GraphQL:
query {
entries(collection: "blog") {
title
body
}
}
REST API
Use Laravel’s built-in routes or Statamic’s api routes:
Route::get('/api/entries', function () {
return Statamic::entries()->all();
});
$schedule->command('statamic:publish-expired')->daily();
Or listen to Statamic events:
Event::listen(EntryPublished::class, function ($event) {
// Handle published entry
});
Service Providers Extend Statamic’s functionality by binding services:
public function register() {
$this->app->bind(\App\Services\YourService::class, function () {
return new \App\Services\YourService();
});
}
Middleware Use Statamic’s middleware for CP routes:
Route::middleware(['web', 'statamic.cp'])->group(function () {
// CP routes
});
Events & Listeners
Listen to Statamic events (e.g., EntrySaved, AssetUploaded):
Event::listen(EntrySaved::class, function ($event) {
Log::info("Entry saved: {$event->entry->title()}");
});
Caching Cache collections, entries, or assets:
$cachedEntries = Cache::remember('blog.entries', now()->addHours(1), function () {
return Statamic::collections()->find('blog')->entries()->all();
});
Static Site Generation
Use php artisan statamic:static to generate static HTML files.
Permissions Define roles and permissions in the CP under Settings > Users & Permissions. Use middleware to restrict access:
Route::middleware(['auth', 'can:edit-blog'])->group(function () {
// Admin-only routes
});
Field-Level Security Restrict fields in blueprints:
fields:
- secret_field:
display: Secret Info
permissions: admin
validate() method doesn’t return a ValidationRuleCollection.Statamic\Fields\Fieldtype and implements validation properly:
public function validate($value, $field, $errors) {
return Validation::make($value, [
'required' => $field->required(),
]);
}
storage/app/asset_containers/ directory is writable:
chmod -R 775 storage/app/asset_containers/
php artisan storage:link to symlink assets to public.{{ }} in Blade) may not render as expected.How can I help you explore Laravel packages today?