Skip to content

Blog

Siteman CMS includes a powerful blogging system built on top of the hierarchical page structure. Create blog indexes and posts with support for tags, featured images, and RSS feeds.

Understanding the Blog System

The blog system in Siteman uses a parent-child page relationship:

  • Blog Index Page: A parent page with the BlogIndex type that displays a paginated list of posts
  • Blog Posts: Child pages of the Blog Index that represent individual articles

This hierarchical structure allows you to:

  • Organize posts under different blog sections
  • Create multiple blogs (e.g., "News", "Updates", "Company Blog")
  • Maintain a clear content hierarchy
  • Generate automatic navigation and breadcrumbs

Creating a Blog

Step 1: Create the Blog Index Page

  1. Navigate to Content > Pages in the admin panel
  2. Click New Page
  3. Configure the blog index:
    • Title: "Blog" (or "News", "Articles", etc.)
    • Slug: "/blog"
    • Type: Select "Blog Index"
    • Published At: Select current date/time
  4. Click Create

The Blog Index page will automatically display all published posts (child pages) in reverse chronological order with pagination.

Step 2: Create Blog Posts

  1. Navigate to Content > Pages
  2. Click New Page
  3. Configure the post:
    • Title: Your post title
    • Slug: "/your-post-slug" (will become /blog/your-post-slug)
    • Parent Page: Select your "Blog" page
    • Type: "Page" (default)
    • Published At: When you want the post to go live
    • Featured Image: Upload an image (optional)
    • Tags: Add relevant tags (optional)
  4. Add content using blocks (Markdown, images, etc.)
  5. Click Create

Blog Index Configuration

The BlogIndex page type automatically:

  • Displays child pages (posts) in reverse chronological order
  • Shows only published posts (published_at in the past)
  • Paginates results (10 posts per page by default)
  • Provides post metadata (title, excerpt, featured image, author, date)

Customizing the Blog Index View

Create a custom view for your blog index in your theme:

resources/views/siteman/themes/my-theme/posts/index.blade.php

Example blog index template:

blade
<x-my-theme::layout :page="$page">
    <div class="blog-index">
        <h1>{{ $page->title }}</h1>

        <div class="posts">
            @foreach($posts as $post)
                <article class="post-preview">
                    @if($post->hasMedia('featured_image'))
                        <img src="{{ $post->getFirstMediaUrl('featured_image', 'thumb') }}"
                             alt="{{ $post->title }}">
                    @endif

                    <h2>
                        <a href="{{ $post->computed_slug }}">
                            {{ $post->title }}
                        </a>
                    </h2>

                    <div class="meta">
                        <span class="author">By {{ $post->author->name }}</span>
                        <span class="date">{{ $post->published_at->format('F j, Y') }}</span>
                    </div>

                    @if($post->tags->isNotEmpty())
                        <div class="tags">
                            @foreach($post->tags as $tag)
                                <a href="/tags/{{ $tag->slug }}">{{ $tag->name }}</a>
                            @endforeach
                        </div>
                    @endif

                    <div class="excerpt">
                        {{ $post->getMeta('description', Str::limit(strip_tags($post->content), 150)) }}
                    </div>

                    <a href="{{ $post->computed_slug }}" class="read-more">Read more →</a>
                </article>
            @endforeach
        </div>

        {{ $posts->links() }}
    </div>
</x-my-theme::layout>

Blog Post Templates

Create custom templates for individual blog posts:

resources/views/siteman/themes/my-theme/pages/show.blade.php

Example blog post template:

blade
<x-my-theme::layout :page="$page">
    <article class="blog-post">
        @if($page->hasMedia('featured_image'))
            <img src="{{ $page->getFirstMediaUrl('featured_image', 'featured_image') }}"
                 alt="{{ $page->title }}"
                 class="featured-image">
        @endif

        <header>
            <h1>{{ $page->title }}</h1>

            <div class="meta">
                <span class="author">By {{ $page->author->name }}</span>
                <span class="date">{{ $page->published_at->format('F j, Y') }}</span>
                <span class="reading-time">{{ $page->getMeta('reading_time', '5 min read') }}</span>
            </div>

            @if($page->tags->isNotEmpty())
                <div class="tags">
                    @foreach($page->tags as $tag)
                        <a href="/tags/{{ $tag->slug }}" class="tag">{{ $tag->name }}</a>
                    @endforeach
                </div>
            @endif
        </header>

        <div class="content">
            @foreach($page->blocks as $block)
                @include("siteman::blocks.{$block['type']}", ['block' => $block])
            @endforeach
        </div>

        <footer>
            @if($page->parent)
                <a href="{{ $page->parent->computed_slug }}" class="back-to-index">
                    ← Back to {{ $page->parent->title }}
                </a>
            @endif
        </footer>
    </article>
</x-my-theme::layout>

Blog posts support featured images using Spatie's Media Library:

php
// In your controller or Livewire component
$post->addMedia($file)
    ->toMediaCollection('featured_image');

// Retrieve the image
$post->getFirstMediaUrl('featured_image'); // Full size
$post->getFirstMediaUrl('featured_image', 'thumb'); // Thumbnail (368x232)
$post->getFirstMediaUrl('featured_image', 'featured_image'); // Responsive

In Blade templates:

blade
@if($post->hasMedia('featured_image'))
    <img src="{{ $post->getFirstMediaUrl('featured_image', 'thumb') }}"
         alt="{{ $post->title }}">
@endif

Post Metadata

Store additional metadata on blog posts using the meta attribute:

php
// Set metadata
$post->update([
    'meta' => [
        'description' => 'A brief description for social sharing',
        'reading_time' => '8 min read',
        'subtitle' => 'An optional subtitle',
    ],
]);

// Retrieve metadata
$post->getMeta('description', 'Default value');

Working with Tags

Add tags to organize and categorize posts:

php
// Attach tags
$post->attachTags(['laravel', 'php', 'tutorial']);

// Sync tags
$post->syncTags(['laravel', 'filament']);

// In Blade
@foreach($post->tags as $tag)
    <a href="/tags/{{ $tag->slug }}">{{ $tag->name }}</a>
@endforeach

Learn more: Tags Documentation

Querying Blog Posts

Retrieve blog posts programmatically:

php
use Siteman\Cms\Models\Page;

// Get all published posts from a blog
$posts = Page::where('parent_id', $blogId)
    ->published()
    ->get();

// Get posts with a specific tag
$posts = Page::withAnyTags(['laravel', 'php'])
    ->published()
    ->get();

// Get recent posts
$recentPosts = Page::where('parent_id', $blogId)
    ->published()
    ->take(5)
    ->get();

// Get posts by author
$authorPosts = Page::where('author_id', $authorId)
    ->published()
    ->get();

Pagination

Customize pagination in your theme or controller:

php
// In BlogIndex page type
$posts = $page->children()->published()->paginate(15); // 15 per page

// In your template
{{ $posts->links() }} // Laravel pagination links

Custom pagination view:

blade
{{ $posts->links('my-theme::pagination') }}

Multiple Blogs

Create multiple blog sections with different purposes:

  1. News Blog (/news) - Company announcements
  2. Technical Blog (/blog) - Technical tutorials
  3. Updates Blog (/updates) - Product updates

Each can have its own:

  • Custom template
  • Tag taxonomy
  • Author restrictions
  • RSS feed

RSS Feeds

Generate RSS feeds for your blog:

Learn more: RSS Feed Documentation

Quick example:

  1. Create a page with type "RSS Feed"
  2. Slug: /blog/feed
  3. Configure feed settings

SEO Optimization

Siteman includes SEO support for blog posts:

php
// SEO data is automatically generated from:
// - Page title
// - Meta description
// - Author name
// - Published date
// - Featured image (for og:image)

Customize SEO per post:

php
$post->update([
    'meta' => [
        'description' => 'Custom meta description for SEO',
        'og_title' => 'Custom Open Graph title',
        'og_description' => 'Custom OG description',
    ],
]);

Best Practices

  1. Consistent Publishing: Use the published_at field to schedule posts
  2. Featured Images: Add featured images for better visual appeal
  3. Tags: Use tags consistently for better organization
  4. Excerpts: Store custom excerpts in meta.description for previews
  5. Hierarchical Structure: Keep posts organized under appropriate blog indexes
  6. Versioning: Siteman tracks versions of your posts automatically
  • Tags - Organize posts with tags
  • Page Types - Understanding different page types
  • Themes - Customize blog appearance
  • RSS Feeds - Syndicate your blog content

Released under the MIT License.