Skip to content

Use Relationship Blocks

Pull data from any Eloquent model — Latest Posts, Team Members, Products — and display it on a page using the Relationship block. You configure it once, and editors curate the content from the admin without touching code again.

Step 1: Register a Query Source

Before you can use the block, tell Kompass which models are available.

  1. Allow-list the model in config/kompass.php:
    php
    'query_source_models' => [
        'posts' => \Secondnetwork\Kompass\Models\Post::class,
        'team'  => \App\Models\TeamMember::class,
    ],
  2. Navigate to Admin > Query Sources.
  3. Click Add Source and select your model. Configure the sorting and the Item View (the Blade component that renders each record).

Step 2: Add the Relationship Block

  1. Open a page in the Block Editor.
  2. Add a Relationship block.
  3. In the block's settings panel, select your Source (e.g., "Posts").

Step 3: Choose a Mode

You can display items in two ways:

  • Automatic: Show the "Latest 5 items" based on a sort field (e.g., created_at). Perfect for blog feeds or news that should always reflect the newest records.
  • Manual: Hand-pick specific records from a search list and drag them into your preferred order. Ideal when the order matters — team hierarchies, featured products, or curated collections.

Step 4: Create the Item View

Each record in the list is rendered using a small Blade component. If you set the "Item View" to relations.post-card, create the file at resources/views/components/relations/post-card.blade.php.

blade
@props(['record', 'url' => null])

<div class="border p-4 rounded shadow">
    @if($record->thumbnails)
        <x-image :id="$record->thumbnails" class="w-full h-32 object-cover" />
    @endif
    <h3 class="font-bold mt-2">{{ $record->title }}</h3>
    <a href="{{ $url }}" class="text-blue-600 underline">Read More</a>
</div>

Item View Naming

The relations.post-card identifier maps to the relations/post-card Blade component path. Use dot notation when configuring the Item View in the admin.

Step 5: Render on the Frontend

Ensure your page template renders the blocks. The Relationship block automatically loops through the records and renders your post-card component for each one.


Example: A Team Members Section

Let's put it all together with a real-world case — a "Meet the Team" grid on an "About Us" page, driven by a custom TeamMember model. This is the complete end-to-end path: migration, model, allow-list, source, and item view.

1. Create the migration

bash
php artisan make:migration create_team_members_table
php
Schema::create('team_members', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->unsignedBigInteger('photo')->nullable(); // medialibrary file id
    $table->string('role')->nullable();
    $table->string('phone')->nullable();
    $table->string('email')->nullable();
    $table->text('description')->nullable();
    $table->integer('order')->default(0);
    $table->boolean('is_active')->default(true);
    $table->timestamps();
});

2. Create the model

Add an active scope so the source can filter out hidden members, and a relation to resolve the Media Library photo.

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Secondnetwork\Kompass\Models\File;
use Illuminate\Database\Eloquent\Builder;

class TeamMember extends Model
{
    protected $guarded = [];

    public function photoFile()
    {
        return $this->belongsTo(File::class, 'photo');
    }

    public function scopeActive(Builder $query): void
    {
        $query->where('is_active', true);
    }
}

3. Allow-list the model

As in Step 1, register the model in config/kompass.php:

php
'query_source_models' => [
    'teams' => \App\Models\TeamMember::class,
],

4. Create the source

Under Admin → Query sources, click Add and configure:

FieldValue
LabelTeam
Keyteam
Modelteams
Display fieldsname, role
Order fieldsorder, name
Scopeactive
Item viewrelations.team
Wrapper classgrid gap-8 sm:grid-cols-2 lg:grid-cols-3

The Wrapper class wraps the whole list, so a single Tailwind grid here turns your cards into a responsive layout. The Scope maps to the active scope you defined on the model.

5. Create the item view

resources/views/components/relations/team.blade.php:

blade
@props(['record', 'url' => null, 'modelKey' => null])

<div class="card bg-base-100 text-center p-6">
    @if ($record->photo)
        <x-image :id="$record->photo" class="w-32 h-32 rounded-full mx-auto object-cover" />
    @endif

    <h3 class="mt-4 text-lg font-semibold">{{ $record->name }}</h3>
    @if ($record->role)
        <p class="text-sm text-primary">{{ $record->role }}</p>
    @endif

    @if ($record->description)
        <p class="mt-2 text-sm text-base-content/70">{{ $record->description }}</p>
    @endif
</div>

6. Add the block and curate the team

Open your "About Us" page and add a Relationship block. Set the Source to Team. Now pick a mode:

  • Automatic — Order by order and let the grid stay in sync with the database.
  • Manual — Search for members, click (+) to select them, and drag the handles (⋮⋮) to arrange them by hierarchy (e.g., CEO first).

Save the page and you have a responsive team grid that editors can update at any time, without touching code.

Manual mode is best for teams

Manual mode gives you absolute control over who appears and in what order — ideal for board members, departments, or project-specific team pages.

Need a backend screen where editors can add and edit those members in the first place? See Build a Backend Table View.

Released under the MIT License.