Skip to main content

Themes

Theme Development in Peak

Peak framework provides a flexible and straightforward way to develop, register, and manage frontend themes. Themes allow you to customize the entire look and feel of your application without changing the core logic.

This guide covers everything you need to know to build your own theme, register it properly, and integrate it into the Peak admin and frontend system.

1. Overview β€” Why Themes in Peak?​

Themes help you:

  • Separate frontend UI from backend logic cleanly.
  • Create reusable and shareable UI designs.
  • Quickly swap between different UI designs without affecting business logic.
  • Build multiple frontends (e.g., public site, admin area) using the same backend.

Peak’s architecture uses Vue + Inertia.js for frontend views, making it easy to build interactive SPAs. Themes are essentially Vue components and layouts organized per theme.

2. Reference Theme β€” Breeze​

Peak ships with a default theme called Breeze. This is a fully functional, production-ready theme that you can:

  • Inspect to understand structure, coding style, and organization.
  • Use as a baseline for your custom themes.
  • Extend or customize as needed.

Breeze demonstrates how to set up routes, pages, layouts, components, and more.

3. Theme Folder Structure​

All themes live under this folder inside your Peak installation:

resources/js/Themes/

Each theme gets its own folder by name. For example:

resources/js/Themes/Breeze/
resources/js/Themes/CustomTheme/

Within each theme folder, the structure looks like this:

+---Components
| | ActionMessage.vue
| | ActionSection.vue
| | ApplicationLogo.vue
| | ApplicationMark.vue
| | AuthenticationCard.vue
| | AuthenticationCardLogo.vue
| | Banner.vue
| | Card.vue
| | Cards.vue
| | Checkbox.vue
| | ConfirmationModal.vue
| | ConfirmsPassword.vue
| | CookieConsent.vue
| | DangerButton.vue
| | DataSearchForm.vue
| | DialogModal.vue
| | Dropdown.vue
| | DropdownLink.vue
| | DynamicLucideIcon.vue
| | FormSection.vue
| | InputError.vue
| | InputLabel.vue
| | LimitDropDown.vue
| | MarketingBanner.vue
| | Modal.vue
| | NavLink.vue
| | NotificationsDropDown.vue
| | Pagination.vue
| | PrimaryButton.vue
| | ResponsiveNavLink.vue
| | SecondaryButton.vue
| | SectionBorder.vue
| | SectionTitle.vue
| | SelectInput.vue
| | SortableTableHead.vue
| | StatsWidget.vue
| | TextArea.vue
| | TextInput.vue
| | TinymceEditor.vue
| | ToggleFullScreen.vue
| |
| +---Alerts
| | AlertInfo.vue
| | ErrorAlert.vue
| | InfoAlert.vue
| | SuccessAlert.vue
| | WarningAlert.vue
| |
| +---Billing
| | Button.vue
| | CursorPaginator.vue
| | ErrorMessages.vue
| | InfoMessages.vue
| | IntervalSelector.vue
| | InvoiceList.vue
| | Modal.vue
| | PaddleInvoiceList.vue
| | Paginator.vue
| | Plan.vue
| | PlanList.vue
| | PlanSectionHeading.vue
| | SecondaryButton.vue
| | SectionHeading.vue
| | SuccessMessage.vue
| |
| +---Dashboard
| | HeaderWidgets.vue
| |
| +---Docs
| | | EditorBody.vue
| | |
| | \---Blocks
| | AlertBlock.vue
| | CodeBlock.vue
| | DelimiterBlock.vue
| | HeaderBlock.vue
| | ImageBlock.vue
| | InlineCodeBlock.vue
| | LinkBlock.vue
| | ListBlock.vue
| | ParagraphBlock.vue
| | QuoteBlock.vue
| | TableBlock.vue
| |
| +---Roadmap
| | RoadmapToggleVote.vue
| |
| \---UserPage
| \---Blocks
| \---Form
| FormTypeForm.vue
|
+---Includes
| AnnouncementBanner.vue
| Banner.vue
| CookieConsent.vue
| Cta.vue
| Errors.vue
| Faqs.vue
| Features.vue
| FlashBanner.vue
| Footer.vue
| FromBlog.vue
| Header.vue
| Hero.vue
| ImpersonationBanner.vue
| LogoClouds.vue
| NewsletterForm.vue
| NewsletterSubscribe.vue
| Pricing.vue
| SocialAuth.vue
| Testimonials.vue
|
+---Layouts
| +---Dashboard
| | DashboardAccountLayout.vue
| | DashboardLayout.vue
| | Logo.vue
| | MobileLogo.vue
| | MobileNavigation.vue
| | Navigation.vue
| | SearchForm.vue
| | Sidebar.vue
| | UserAccountDropdown.vue
| |
| +---Docs
| | DocContent.vue
| | DocLayout.vue
| | DocsHeading.vue
| | DocsMobileSidebar.vue
| | DocsSearch.vue
| | DocsSidebar.vue
| | MenuItems.vue
| | MenuLinks.vue
| |
| \---Main
| Layout.vue
| PageLayout.vue
|
+---Modals
| NewFeatureRequest.vue
|
\---Pages
| About.vue
| Blog.vue
| Changelog.vue
| Contact.vue
| Docs.vue
| Index.vue
| Page.vue
| Roadmap.vue
| Support.vue
|
+---Auth
| ConfirmPassword.vue
| ForgotPassword.vue
| Login.vue
| Register.vue
| ResetPassword.vue
| TwoFactorChallenge.vue
| VerifyEmail.vue
|
+---Blog
| Show.vue
|
+---Dashboard
| | Index.vue
| |
| +---Account
| | | Notifications.vue
| | | Profile.vue
| | | Security.vue
| | |
| | +---API
| | | | Index.vue
| | | |
| | | \---Partials
| | | ApiTokenManager.vue
| | |
| | +---Billing
| | | Index.vue
| | | Manage.vue
| | |
| | \---Referrals
| | Index.vue
| |
| +---Partials
| | DeleteUserForm.vue
| | LogoutOtherBrowserSessionsForm.vue
| | ReferralLink.vue
| | TwoFactorAuthenticationForm.vue
| | UpdatePasswordForm.vue
| | UpdateProfileInformationForm.vue
| |
| \---Support
| Create.vue
| Edit.vue
| Index.vue
| Show.vue
| TicketComment.vue
|
+---Roadmap
| Show.vue
|
\---Teams
| Create.vue
| Show.vue
|
\---Partials
CreateTeamForm.vue
DeleteTeamForm.vue
TeamMemberManager.vue
UpdateTeamNameForm.vue

4. The theme.json File β€” Register Your Theme​

To be recognized and selectable inside the Peak admin panel under Frontend β†’ Themes, each theme must contain a theme.json file in its root folder.

This JSON file holds metadata about the theme:

Example theme.json​

{
"name": "Breeze",
"uri": "https://larapeak.com/",
"image_uri": "https://example.com/screenshot.jpg",
"author": "Qoraiche",
"author_uri": "https://qoraiche.me",
"description": "Breeze is a clean, simple, and responsive theme designed to give your Peak app a fresh and modern UI.",
"version": "v1.0.0"
}

Fields explained:​

| Field | Description | | - | | | name | The display name of the theme in the admin panel. | | uri | URL pointing to theme homepage or documentation. | | image_uri | URL to a preview image or screenshot of the theme. | | author | The theme author or organization name. | | author_uri | Link to author’s website or profile. | | description | A short summary describing the theme’s style and purpose. | | version | Current theme version, useful for updates and management. |

5. Activating a Theme​

Once your theme folder and theme.json file are set up correctly:

  • Go to Admin Panel β†’ Frontend β†’ Themes.
  • Your theme will appear as an option.
  • Click Activate to set it as the current frontend theme.

Peak will then start loading your theme’s Vue pages and components for all user-facing routes.

6. Theme Pages β€” The Heart of the Theme​

Where are pages located?​

Every theme must have a Pages folder containing all Vue components representing the pages of your frontend UI:

resources/js/Themes/YourTheme/Pages/

How are pages rendered?​

In your Laravel backend controllers, you use Inertia.js to render pages by referencing them by name:

use Inertia\Inertia;

class FrontendController extends Controller
{
public function showHome()
{
return Inertia::render('Home', [
'someData' => 'value'
]);
}

public function showProfile()
{
return Inertia::render('Profile', [
'user' => auth()->user()
]);
}
}

These calls correspond to Vue components in:

resources/js/Themes/YourTheme/Pages/Home.vue
resources/js/Themes/YourTheme/Pages/Profile.vue

7. Required Pages & Routing Setup​

To ensure your theme works properly with Peak’s routing and functionality, your theme should include the core pages needed by your app.

For reference, examine the Breeze theme β€” it includes:

  • Home.vue β€” landing page.
  • Dashboard.vue β€” user dashboard.
  • Profile.vue β€” user profile.
  • Login.vue / Register.vue β€” authentication pages.
  • Other functional pages based on your app needs.

Your backend routing should correctly map URLs to these pages via Inertia.

8. Additional Theme Components & Layouts​

Themes can also include reusable Vue components and layout wrappers in the:

  • Components/ folder β€” for buttons, cards, modals, etc.
  • Layouts/ folder β€” for master page layouts wrapping pages (header, footer, sidebar)

This modularity lets you keep your UI clean and DRY (Don’t Repeat Yourself).

9. Assets & Styling​

Put your theme-specific CSS, images, fonts, and other assets in the theme’s assets/ folder, which you can import in your Vue components or layouts.

Example:

// resources/js/Themes/YourTheme/Layouts/MainLayout.vue
import './assets/styles.css';

10. Tips for Developing Themes​

  • Start by cloning the Breeze theme as a boilerplate.
  • Focus on Vue components and Inertia page rendering.
  • Use scoped styles to avoid CSS bleeding.
  • Leverage Vue slots for flexible layouts.
  • Keep theme.json updated with correct metadata.
  • Test activation/deactivation via the admin panel.
  • Document your theme for future maintainers.

Summary​

| Step | What to do | | | - | | Create theme folder | resources/js/Themes/YourTheme | | Add theme.json | Fill in theme metadata | | Add Pages folder | Add Vue components for all pages | | Optional: Components & Layouts | Add reusable UI pieces and layouts | | Add assets | CSS, images, fonts | | Activate theme in admin panel | Make it live and test | | Use Breeze as example | Follow its structure and coding patterns |

If you want, I can also help you generate a sample theme starter template with all these pieces ready for you to customize. Would you like that?