View Pages System
Flute CMS provides a powerful view pages system that automatically registers routes for Blade templates placed in the Resources/pages/ directory of your module. This system eliminates the need for manually defining routes for simple pages and ensures automatic URL generation.
The base route prefix is determined by the module name in kebab-case (e.g., Blog → /blog). The loadViewPages() method is called inside bootstrapModule().
How View Pages Work
When you call loadViewPages() or bootstrapModule() in your module provider, the system automatically:
Directory Scanning
Scans the Resources/pages/ directory of the module.
Route Registration
Registers routes for all .blade.php files.
Nested Directories
Supports nested directories for organized routing.
Name Conversion
Uses kebab-case conversion for route prefixes.
Directory Structure and Route Mapping
- index.blade.php
- about.blade.php
- contact.blade.php
- index.blade.php
- create.blade.php
File to URL Mapping:
| File | URL |
|---|---|
index.blade.php | /your-module |
about.blade.php | /your-module/about |
contact.blade.php | /your-module/contact |
blog/index.blade.php | /your-module/blog |
blog/create.blade.php | /your-module/blog/create |
blog/categories/index.blade.php | /your-module/blog/categories |
blog/tags/index.blade.php | /your-module/blog/tags |
blog/tags/show.blade.php | /your-module/blog/tags/show |
Configuring View Pages
Provider Configuration
<?php
namespace Flute\Modules\YourModule\Providers;
use Flute\Core\Support\ModuleServiceProvider;
class YourModuleProvider extends ModuleServiceProvider
{
public function boot(\DI\Container $container): void
{
// Automatic setup - calls loadViewPages() internally
$this->bootstrapModule();
// Load view namespace for components and layouts
$this->loadViews('Resources/views', 'yourmodule');
}
}Manual Setup (if needed)
<?php
class YourModuleProvider extends ModuleServiceProvider
{
public function boot(\DI\Container $container): void
{
// First load view namespace
$this->loadViews('Resources/views', 'yourmodule');
// Explicitly load view pages
$this->loadViewPages();
// Other module resources
$this->loadTranslations();
$this->loadScss('Resources/assets/scss/main.scss');
}
}Creating Page Templates
Basic Page Template
{{-- Resources/pages/index.blade.php --}}
@extends('flute::layouts.app')
@section('title', __('yourmodule.home_title'))
@section('content')
<div class="container">
<div class="hero-section">
<h1>{{ __('yourmodule.welcome_message') }}</h1>
<p class="lead">{{ __('yourmodule.description') }}</p>
</div>
</div>
@endsectionNested Page Template
{{-- Resources/pages/blog/index.blade.php --}}
@extends('flute::layouts.app')
@section('title', __('blog.articles'))
@section('content')
<div class="container">
<div class="blog-header">
<h1>{{ __('blog.latest_articles') }}</h1>
</div>
<div class="articles-grid">
@foreach($articles ?? [] as $article)
<article class="article-card">
<h3>{{ $article->title }}</h3>
<p>{{ $article->excerpt }}</p>
</article>
@endforeach
</div>
</div>
@endsectionPage with Dynamic Content
{{-- Resources/pages/blog/show.blade.php --}}
@extends('flute::layouts.app')
@section('title', $article->title ?? __('blog.article'))
@section('content')
<div class="container">
@if($article)
<article class="blog-post">
<header class="post-header">
<h1>{{ $article->title }}</h1>
<div class="post-meta">
<span>{{ __('blog.by') }} {{ $article->author->name }}</span>
<span>{{ $article->created_at->format('M j, Y') }}</span>
</div>
</header>
<div class="post-content">
{!! $article->content !!}
</div>
</article>
@else
<div class="error-page">
<h1>{{ __('blog.article_not_found') }}</h1>
</div>
@endif
</div>
@endsectionReal World Examples from Existing Modules
News Module Implementation
The News module uses view pages in its structure:
- index.blade.php
- view.blade.php
- view.blade.php
News Provider:
<?php
namespace Flute\Modules\News\Providers;
use Flute\Core\Support\ModuleServiceProvider;
class NewsProvider extends ModuleServiceProvider
{
public function boot(\DI\Container $container): void
{
$this->bootstrapModule(); // includes loadViewPages()
$this->loadViews('Resources/views', 'news');
$this->loadScss('Resources/assets/scss/news.scss');
}
}News Index Page:
{{-- app/Modules/News/Resources/pages/news/index.blade.php --}}
@extends('flute::layouts.app')
@push('content')
<div class="container">
<div class="news-page" hx-boost="true" hx-target="#main" hx-swap="outerHTML transition:true">
<header class="news-page-header">
<h1>News</h1>
<p class="news-page-subtitle">Latest materials about technology, science, and development</p>
</header>
<div class="news-list-grid">
@for ($i = 0; $i < 8; $i++)
<a href="{{ url('/news/view') }}" class="news-card">
<div class="news-card-image" aria-hidden="true"></div>
<div class="news-card-content">
<span class="news-chip">Technology</span>
<h3>New Technologies in Web Development 2024</h3>
<p>Brief overview of promising frameworks and tools.</p>
<div class="news-meta">
<span class="news-author">
<x-icon path="ph.regular.user" /> Ivan Petrov
</span>
<span class="news-time">
<x-icon path="ph.regular.clock" /> 5 min
</span>
<span class="news-date">
<x-icon path="ph.regular.calendar" /> 15.01.2024
</span>
</div>
</div>
</a>
@endfor
</div>
</div>
</div>
@endpushFAQ Module Implementation
The FAQ module uses view pages to display widgets:
- faq.blade.php
- settings.blade.php
FAQ Provider:
<?php
namespace Flute\Modules\FAQ\Providers;
use Flute\Core\Support\ModuleServiceProvider;
class FAQProvider extends ModuleServiceProvider
{
public function boot(\DI\Container $container): void
{
$this->bootstrapModule(); // Automatically loads view pages
$this->loadViews('Resources/views', 'faq');
$this->loadScss('Resources/assets/scss/faq.scss');
}
}Full Module Example
Here is a complete example of a Blog module using view pages:
Module Structure
- module.json
- index.blade.php
- create.blade.php
Provider Implementation
<?php
namespace Flute\Modules\Blog\Providers;
use Flute\Core\Support\ModuleServiceProvider;
class BlogProvider extends ModuleServiceProvider
{
public function boot(\DI\Container $container): void
{
// This enables view pages automatically
$this->bootstrapModule();
// Load additional view namespace
$this->loadViews('Resources/views', 'blog');
// Load styles
$this->loadScss('Resources/assets/scss/blog.scss');
}
}Page Templates
Blog Index Page:
{{-- Resources/pages/index.blade.php --}}
@extends('flute::layouts.app')
@section('title', __('blog.articles'))
@section('content')
<div class="blog-container">
<div class="blog-header">
<h1>{{ __('blog.latest_articles') }}</h1>
<p>{{ __('blog.discover_content') }}</p>
</div>
<div class="articles-grid">
@foreach($articles ?? [] as $article)
<article class="article-card">
<h3>{{ $article->title }}</h3>
<p>{{ $article->excerpt }}</p>
<a href="{{ route('blog.show', ['id' => $article->id]) }}">
{{ __('blog.read_more') }}
</a>
</article>
@endforeach
</div>
</div>
@endsectionCategories Page:
{{-- Resources/pages/categories/index.blade.php --}}
@extends('flute::layouts.app')
@section('title', __('blog.categories'))
@section('content')
<div class="categories-container">
<h1>{{ __('blog.all_categories') }}</h1>
<div class="categories-grid">
@foreach($categories ?? [] as $category)
<div class="category-card">
<h3>{{ $category->name }}</h3>
<p>{{ $category->description }}</p>
<span class="article-count">
{{ $category->articles_count }} {{ __('blog.articles') }}
</span>
</div>
@endforeach
</div>
</div>
@endsectionBest Practices
1. Directory Organization
- Use clear, descriptive directory names
- Group related pages in subdirectories
- Keep structure as flat as possible
2. Template Structure
- Always extend a base layout
- Use proper section organization
- Include meaningful page titles
3. Route Naming
- Filenames become URL segments
- Use kebab-case for multi-word files
- Keep URLs clean and SEO-friendly
4. Content Management
- Use translation functions for all text
- Handle missing data gracefully
- Provide fallback content
Advantages of View Pages System
Key Benefits:
- Automatic Routing — no need to manually define routes
- Organized Structure — files organized by URL paths
- SEO-Friendly URLs — automatic conversion to kebab-case
- Nesting — support for any depth of directory nesting
- Simplicity — just create a Blade template and it becomes a page
Summary
The view pages system provides a simple and effective way to create pages in Flute CMS without manually defining routes. Simply create Blade templates in the Resources/pages/ directory and they automatically become accessible URLs!
Key Points:
- Files in
Resources/pages/automatically become routes - Module name is converted to URL prefix (kebab-case)
index.blade.phpbecomes the root route of the directory- Nested directories create nested URL paths
bootstrapModule()automatically loads view pages