statamic-rad-pack/runway
Runway lets you use Eloquent models as content sources in Statamic. Register your models as collections, browse and edit records in the control panel, and query them with familiar Eloquent syntax—no custom code or external APIs required.
Runway lets you use Eloquent models as a content source in Statamic — the same blueprints, augmentation, routing, and CP editing you get for entries, but backed by your own database tables.
Minimal setup:
composer require statamic-rad-pack/runway
php artisan vendor:publish --tag=runway-config
Everything starts in config/runway.php. Add a resource under resources:
'resources' => [
'products' => [
'name' => 'Products',
'model' => \App\Models\Product::class,
'blueprint' => 'products',
'title_field' => 'name',
'order_by' => 'name',
],
],
Then:
php artisan config:clear, php please stache:clear if you cached the config).{{ runway:products limit="5" }}{{ title }}{{ /runway:products }}.The model should be a standard Illuminate\Database\Eloquent\Model with $fillable set for anything you want editable in the CP. Make sure to look at the two things people usually miss first: title_field (drives CP labels and search) and the route/template keys (turn a resource into a full front-end detail page rather than just a list).
First use case that pays off fastest: a small lookup table (categories, authors, locations, FAQs) that editors need to manage but that doesn't belong in the content tree — you get CRUD, blueprints, and Antler access in ~20 lines of config.
Eloquent-first querying. Reach for the Runway tag for simple lists, but drop into the model for anything non-trivial:
$products = Product::query()
->where('active', true)
->with(['category', 'images']) // always eager load relationships
->paginate(12);
Then augment via the package's helpers (Runway::augment($model) / $model->augmentedValue('field')) so field formatting, Markdown, assets, and Bard all behave the same as in Antlers.
Relationships as the glue. The most common real-world pattern is Eloquent relationship → Statamic entry, or Statamic entry → Runway resource. Expose the relation in the blueprint as a belongs_to/has_many field or simply let Antlers walk it: {{ runway:products }}{{ category:title }}{{ /runway:products }}. Eager loading is the difference between a fast page and a 300-query page.
Detail pages via routes. Configure route + template on the resource and Runway registers front-end routing for /products/{slug}-style URLs. Static caching warms those URIs — in 9.7 you can now disable that warming per resource/config if you have a large table or a deploy pipeline that already handles warming.
CP as a lightweight admin. With read_only off, Runway gives editors a full listing + edit UI driven by your blueprint. Good for tables with tens to a few thousand rows; see gotchas below for scale.
Ordering (new in 9.7). Resources can now be marked orderable, giving you drag-and-drop reordering in the CP that persists to a sort column — useful for things like FAQs, team members, or navigation fragments where editors care about sequence.
GraphQL & REST. Enable graphql on a resource to expose it to Statamic's GraphQL schema; useful when the front end is decoupled but content still lives in the legacy DB.
Testing. Standard Laravel: factories + RefreshDatabase. Assert against the Antler output or the model query, not the CP, unless you're specifically testing blueprint save behaviour.
with in the resource config, and use ->with() in any manual query. Augmentation of a relation triggers a lookup per item if you don't.title_field / title_format and JSON columns. Nested JSON paths in title_field and title_format were broken before 9.7 (#844). If you're on an earlier 9.x and titles render blank for JSON-backed columns, upgrade rather than working around it with accessors.$fillable / casts. CP edits silently fail (or throw mass-assignment errors) if columns aren't fillable. Dates and JSON need casts, or blueprint field types will mismatch on save.runway.php looks like a no-op until you clear it. A frequent "why isn't my new resource showing up" cause.read_only and manage data elsewhere.composer.json constraints before jumping a major; if you're on an older Statamic, pin to the matching Runway major rather than forcing the constraint.How can I help you explore Laravel packages today?