Making singular pages

If you're familiar with WordPress theming, you may know about the concept of a single.php file. WordPress automatically looks for the “single” version of a post type and uses that.

Prodigy does things a little differently – you can use the content defined from a CMS schema, but the routing and templating is up to you.

Suppose you have a CMS schema of team members who need their own detail page. 

Let's make that detail page using Livewire. First, create a component called TeamDetailPage. That component would look like this:

TeamDetailPage.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use ProdigyPHP\Prodigy\Models\Entry;

class TeamPage extends Component
{
    public Entry $team_member;

    public function mount(string $wildcard)
    {
        $this->team_member = Entry::where('type', 'team')->where('content->slug', $wildcard)->first();
    }

    public function render()
    {
        return view('livewire.team-page');
    }
}

Since the content is accessible in the database, all we're doing is using Eloquent to query that information. We haven't used Prodigy at all for this – it's all standard Laravel.

Note: if you're worried about the performance of querying a JSON column, our experience is that it has a negligible impact on perceived performance. 

From there, the template is very simple, and can use all the fields which were defined in the schema.

team-page.blade.php
<div>

    <livewire:prodigy-block block_title="Global Header"/>

    <div class="max-w-[1200px] mx-auto px-4 lg:flex lg:gap-12 mt-20">
        <div class="lg:w-2/5">
            <img src="{{ $team_member->getFirstMediaUrl('prodigy_photos') }}" alt="{{ $team_member->name }}" class="rounded-md shadow-sm">

        </div>
        <div>
            <x-h2 class="text-white mb-4">{{ $team_member->content['name'] }}</x-h2>
            <p class="mb-4 font-bold text-green-200">{{ $team_member->content['title'] }}</p>

            <div class="prose lg:prose-lg text-white">
                {!! $team_member->content['bio'] !!}
            </div>
        </div>
    </div>

    <livewire:prodigy-block block_title="Global Footer"/>
</div>

Finally, define your route in web.php to direct the detail pages to where they need to go…

web.php
Route::get('team/{wildcard}', TeamPage::class);