Views Organization Guide
Last Updated: 2026-01-22 Status: Active Audience: Developers
This guide defines the standard organization for all files in resources/views/. Follow these conventions when creating new views or refactoring existing ones.
Table of Contents
- Directory Structure
- Top-Level Directories
- Components Organization
- Naming Conventions
- File Placement Rules
- Layouts
- Partials vs Components
- Examples
Directory Structure
resources/views/
├── admin/ # Admin portal views (admin.scopeforged.com)
├── api/ # API documentation views
├── auth/ # Authentication views (login, register, etc.)
├── components/ # Reusable Blade components
├── emails/ # Email templates
├── errors/ # Error pages (404, 500, etc.)
├── layouts/ # Page layout templates
├── marketing/ # Marketing site views (scopeforged.com)
├── pdf/ # PDF generation templates
├── portal/ # Client portal views (portal.scopeforged.com)
├── settings/ # User settings views
└── shared/ # Views shared across domains
Top-Level Directories
admin/
Views for the admin portal (admin.scopeforged.com). Organize by feature/resource.
admin/
├── clients/ # Client management
│ ├── index.blade.php
│ ├── create.blade.php
│ ├── edit.blade.php
│ ├── show.blade.php
│ └── _form.blade.php # Shared form partial
├── invoices/
├── projects/
├── analytics/
├── notifications/
│ ├── templates/ # Nested resource
│ └── analytics/
└── settings/
portal/
Views for the client portal (portal.scopeforged.com). Simpler structure focused on client-facing features.
portal/
├── dashboard.blade.php
├── projects/
├── invoices/
├── files/
├── messages/
└── settings/
marketing/
Views for the public marketing site (scopeforged.com).
marketing/
├── home.blade.php
├── about.blade.php
├── contact.blade.php
├── pricing.blade.php
├── blog/
│ ├── index.blade.php
│ └── show.blade.php
├── case-studies/
└── legal/
├── privacy.blade.php
└── terms.blade.php
layouts/
Base layout templates. Keep minimal - most views should use one of these.
layouts/
├── app.blade.php # Main authenticated layout (admin/portal)
├── guest.blade.php # Unauthenticated layout
├── marketing.blade.php # Marketing site layout
├── pdf.blade.php # PDF generation layout
└── navigation.blade.php # Main navigation partial
emails/
Email templates using Laravel's markdown mail format.
emails/
├── invoices/
│ ├── sent.blade.php
│ └── reminder.blade.php
├── projects/
│ └── status-update.blade.php
├── auth/
│ └── welcome.blade.php
└── notifications/
└── generic.blade.php
errors/
Custom error pages.
errors/
├── 401.blade.php
├── 403.blade.php
├── 404.blade.php
├── 419.blade.php
├── 429.blade.php
├── 500.blade.php
└── 503.blade.php
Components Organization
Components live in resources/views/components/ and are organized by purpose, not by where they're used.
Component Categories
| Directory | Purpose | Examples |
|---|---|---|
actions/ | User action controls | bulk-actions, filter-panel, search |
analytics/ | Charts, metrics, dashboards | analytics-chart, trend, widget |
collaboration/ | Multi-user interaction | comments, notes, mentions |
dashboard/ | Dashboard-specific widgets | grid, section, widgets/* |
data-table/ | Table sub-components | sortable-header, pagination, filter |
display/ | Data presentation | stat-card, badge, avatar, progress-bar |
feedback/ | User feedback/alerts | modal, toast, flash-messages, tooltip |
files/ | File handling | upload, preview, versions |
form/ | Form inputs | input, select, checkbox, textarea |
marketing/ | Marketing-specific | testimonial, team-card, pricing |
navigation/ | Navigation elements | dropdown, nav-link, breadcrumb |
portal/ | Portal-specific components | timeline, mobile-nav |
realtime/ | Real-time/WebSocket | presence, typing-indicator, notifications |
skeletons/ | Loading placeholders | card, table-row, avatar |
state/ | State indicators | empty-state, spinner, loading |
ui/ | Generic UI primitives | button, card, badge, accordion |
utility/ | Utility/helper components | logo, theme-toggle, banner |
Root-Level Components
Only high-usage primitive components stay at the root level:
| Component | Reason |
|---|---|
icon.blade.php | Fundamental - used everywhere |
date.blade.php | Fundamental date formatter |
datetime.blade.php | Fundamental datetime formatter |
data-table.blade.php | Core table component |
Rule: If a component has fewer than 100 usages, it belongs in a subdirectory.
Component Directory Structure
components/
├── icon.blade.php # Root - high usage primitive
├── date.blade.php # Root - high usage primitive
├── datetime.blade.php # Root - high usage primitive
├── data-table.blade.php # Root - high usage primitive
│
├── actions/
│ ├── accessible-search.blade.php
│ ├── bulk-actions.blade.php
│ ├── bulk-checkbox.blade.php
│ └── filter-panel.blade.php
│
├── dashboard/
│ ├── grid.blade.php
│ ├── section.blade.php
│ └── widgets/
│ ├── base.blade.php
│ ├── loading.blade.php
│ ├── error.blade.php
│ └── empty.blade.php
│
├── display/
│ ├── stat-card.blade.php
│ ├── status-badge.blade.php
│ ├── progress-bar.blade.php
│ └── user-avatar.blade.php
│
├── feedback/
│ ├── modal.blade.php
│ ├── confirm-modal.blade.php
│ ├── flash-messages.blade.php
│ ├── toast-notifications.blade.php
│ └── tooltip.blade.php
│
├── form/
│ ├── input.blade.php
│ ├── textarea.blade.php
│ ├── select.blade.php
│ ├── checkbox.blade.php
│ ├── radio.blade.php
│ ├── toggle.blade.php
│ └── group.blade.php
│
├── navigation/
│ ├── dropdown.blade.php
│ ├── dropdown-link.blade.php
│ ├── nav-link.blade.php
│ ├── breadcrumb.blade.php
│ └── settings-nav.blade.php
│
├── state/
│ ├── spinner.blade.php
│ ├── loading-dots.blade.php
│ ├── loading-overlay.blade.php
│ ├── empty-state.blade.php
│ └── upload-progress.blade.php
│
└── ui/
├── button.blade.php
├── card.blade.php
├── badge.blade.php
├── accordion.blade.php
└── table.blade.php
Naming Conventions
Files
| Type | Convention | Example |
|---|---|---|
| Views | kebab-case | project-details.blade.php |
| Components | kebab-case | status-badge.blade.php |
| Partials | underscore prefix | _form.blade.php |
| Layouts | kebab-case | app.blade.php |
Component Usage
{{-- Root-level components --}}
<x-icon name="check" />
<x-date :value="$createdAt" />
<x-data-table :items="$clients" />
{{-- Categorized components (dot notation) --}}
<x-ui.button variant="primary">Save</x-ui.button>
<x-form.input name="email" label="Email" />
<x-feedback.modal name="confirm-delete" />
<x-state.spinner />
<x-display.stat-card title="Revenue" :value="$revenue" />
<x-navigation.dropdown />
CRUD Views
Standard naming for resource views:
{resource}/
├── index.blade.php # List all
├── create.blade.php # Create form
├── edit.blade.php # Edit form
├── show.blade.php # View single
└── _form.blade.php # Shared form partial (optional)
File Placement Rules
Decision Tree: Where Does This View Go?
Is it a reusable UI element?
├── YES → components/{category}/
└── NO ↓
Is it for email?
├── YES → emails/{feature}/
└── NO ↓
Is it a PDF template?
├── YES → pdf/{feature}/
└── NO ↓
Is it an error page?
├── YES → errors/
└── NO ↓
Is it for the admin portal?
├── YES → admin/{feature}/
└── NO ↓
Is it for the client portal?
├── YES → portal/{feature}/
└── NO ↓
Is it for the marketing site?
├── YES → marketing/{feature}/
└── NO ↓
Is it shared across domains?
└── YES → shared/{feature}/
Decision Tree: Which Component Category?
Does it handle user input?
├── YES → form/
└── NO ↓
Does it display data/status?
├── YES → display/
└── NO ↓
Does it provide user feedback?
├── YES → feedback/
└── NO ↓
Does it handle navigation?
├── YES → navigation/
└── NO ↓
Is it a loading/empty state?
├── YES → state/
└── NO ↓
Is it for file operations?
├── YES → files/
└── NO ↓
Is it for real-time features?
├── YES → realtime/
└── NO ↓
Is it for dashboards/analytics?
├── YES → dashboard/ or analytics/
└── NO ↓
Is it a generic UI primitive?
└── YES → ui/
Layouts
Available Layouts
| Layout | Use For |
|---|---|
layouts.app | Authenticated admin/portal pages |
layouts.guest | Unauthenticated pages (login, register) |
marketing-layout | Marketing site pages |
settings-layout | Settings pages with sidebar |
error-layout | Error pages |
Layout Usage
{{-- Standard authenticated page --}}
<x-app-layout>
<x-slot name="header">
<h2>Page Title</h2>
</x-slot>
{{-- Page content --}}
</x-app-layout>
{{-- Marketing page --}}
<x-marketing-layout>
{{-- Page content --}}
</x-marketing-layout>
{{-- Settings page --}}
<x-settings-layout>
{{-- Settings content --}}
</x-settings-layout>
Partials vs Components
When to Use Partials (_filename.blade.php)
- Feature-specific markup not reused elsewhere
- Form fragments shared between create/edit views
- Section fragments for very long views
- Livewire partial updates (rows for HTMX/Livewire)
{{-- admin/clients/_form.blade.php --}}
{{-- Only used in admin/clients/create.blade.php and edit.blade.php --}}
@include('admin.clients._form', ['client' => $client])
When to Use Components
- Reusable across multiple features
- Configurable via props
- Self-contained with own styling/logic
- UI patterns that should be consistent
{{-- Reusable, configurable, consistent --}}
<x-form.input name="email" label="Email" type="email" required />
Partial Naming
- Prefix with underscore:
_form.blade.php,_filters.blade.php - Keep in same directory as parent view
- Never put partials in
components/
Examples
Creating a New Admin Feature
Adding a "Reports" feature to admin:
admin/
└── reports/
├── index.blade.php # List all reports
├── create.blade.php # Create report form
├── show.blade.php # View single report
└── _filters.blade.php # Filter partial (if complex)
Creating a New Component
Adding a "rating" display component:
- Determine category: Displays data →
display/ - Create file:
components/display/rating.blade.php - Usage:
<x-display.rating :value="4.5" :max="5" />
{{-- components/display/rating.blade.php --}}
@props(['value', 'max' => 5])
<div class="flex items-center gap-1">
@for ($i = 1; $i <= $max; $i++)
<x-icon
name="{{ $i <= $value ? 'star-filled' : 'star' }}"
class="{{ $i <= $value ? 'text-yellow-400' : 'text-gray-300' }}"
/>
@endfor
<span class="ml-2 text-sm text-gray-600">{{ $value }}/{{ $max }}</span>
</div>
Form Component Standard API
All form components should follow this prop pattern:
@props([
'name', # Required: field name
'label' => null, # Optional: label text
'hint' => null, # Optional: help text
'error' => null, # Optional: override error message
'required' => false, # Optional: mark as required
'disabled' => false, # Optional: disable input
])
Usage:
<x-form.input
name="company_name"
label="Company Name"
hint="Enter the legal business name"
required
/>
Button Component Variants
Use x-ui.button with variants instead of separate button components:
{{-- Correct --}}
<x-ui.button variant="primary">Save</x-ui.button>
<x-ui.button variant="secondary">Cancel</x-ui.button>
<x-ui.button variant="danger">Delete</x-ui.button>
<x-ui.button variant="ghost">More Options</x-ui.button>
<x-ui.button variant="link" href="/docs">Learn More</x-ui.button>
{{-- Deprecated - do not use --}}
<x-primary-button>Save</x-primary-button>
<x-secondary-button>Cancel</x-secondary-button>
<x-danger-button>Delete</x-danger-button>
Best Practices
Do
- Place components in the appropriate category directory
- Use dot notation for categorized components (
x-form.input) - Follow the standard form component API
- Use layouts consistently
- Keep partials with their parent views
- Name files descriptively using kebab-case
Don't
- Create components at the root level (unless >100 usages)
- Mix concerns in component categories
- Use
@includefor reusable UI (use components) - Create feature-specific components in generic categories
- Duplicate component functionality
Related Documentation
- BLADE_COMPONENTS.md - Component patterns and syntax
- NAMING_CONVENTIONS.md - General naming standards
- CONTRIBUTING.md - Development workflow