Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Theme Laravel Package

yaap/theme

YAAP Theme is a Laravel package for organizing and managing themes with a simple API. It supports theme activation, view and layout resolution, asset handling, and a flexible structure for separating theme resources from application code.

View on GitHub
Deep Wiki
Context7

Getting Started

  • composer require yaap/theme (5.1.0 added Laravel 11 support; auto-discovery covers Laravel 5.5 through 11). On modern Laravel you don't touch config/app.php — the provider and Theme alias are discovered. For legacy apps, add Yaap\Theme\ThemeServiceProvider and the Theme alias (typically Yaap\Theme\Facades\Theme) manually.
  • Publish the config: php artisan vendor:publish --provider="Yaap\Theme\ThemeServiceProvider" then open config/theme.php. This is the file you will live in — it defines the theme base path, the default theme, and any named themes / inheritance entries.
  • Create the first theme by adding a folder under config('theme.path') (usually resources/themes/). Mirror the standard Laravel resources layout inside it: views/ for Blade templates, and an assets/ (or public/) folder for css, js and images.
  • Activate a theme early in the request lifecycle — a service provider or middleware — with Theme::set('mytheme') and verify with Theme::get().
  • First real use case: a two-theme app (public default + admin), where the admin theme extends default and only overrides the files that actually differ.

Where to look first: config/theme.php, then the package's Theme class and facade for the actual runtime API.

Implementation Patterns

Per-request theme selection via middleware

class SetTheme
{
    public function handle($request, Closure $next)
    {
        $theme = $request->user()?->theme
            ?? ($request->is('admin/*') ? 'admin' : config('theme.default'));

        Theme::set($theme);

        return $next($request);
    }
}

Register it globally or on the relevant route group so it runs before any controller renders a view.

Route-group scoped switching

Route::group(['middleware' => SetAdminTheme::class], function () {
    // admin routes
});

Useful when the public site stays on the default theme.

Inheritance for shared layouts

// config/theme.php
'themes' => [
    'default' => ['extends' => null],
    'admin'   => ['extends' => 'default'],
],

Keep base layout partials (header, footer, nav, base css) in the parent theme and let the child theme override only the blade files it changes. This is the primary way to avoid duplicating markup between themes.

Theme-relative asset URLs

Use the package helper instead of the plain asset() helper so the theme prefix is applied correctly:

<link rel="stylesheet" href="{{ Theme::asset('css/app.css') }}">

Custom theme class for setup logic

If a theme needs runtime work (a view composer, shared variables, a menu), subclass the base theme and reference it in config rather than stuffing logic into middleware:

class AdminTheme extends \Yaap\Theme\Theme
{
    public function register()
    {
        view()->share('themeName', 'admin');
    }
}

Fallback lookups

When a view may not exist in the child theme, either rely on inheritance or probe with view()->exists() using a path built from Theme::get(). Prefer inheritance — it keeps the view finder paths predictable.

Testing

In feature tests call Theme::set('default') in setUp() or override config(['theme.default' => 'default']) so view resolution is deterministic across test cases. On Laravel 11's slim skeleton this usually means a RefreshDatabase/config-reset style base test case and $this->withoutExceptionHandling() when debugging theme resolution failures.

Gotchas and Tips

  • Config caching: php artisan config:cache freezes config/theme.php. Switching the active theme at runtime is fine; changing the theme map requires config:clear and a deploy.
  • View cache: after adding/removing theme view folders or renaming views, run php artisan view:clear. Laravel will happily serve the previous theme's compiled blade otherwise.
  • Order of bootstrap matters: setting the theme too late (e.g. inside a controller after the view is being resolved) can leave the view finder pointing at the previous theme. Prefer middleware or AppServiceProvider::boot. On Laravel 11, bootstrap/app.php is the natural place to register global middleware — don't reach for Kernel.php, it's gone.
  • Laravel 11 specifics: 5.1.0 is the first release that targets Laravel 11. If you're upgrading a 5.5-era app straight to L11, re-publish the config and diff it — old published config may reference options the newer release no longer reads the same way. Also verify the provider still auto-discovers after the skeleton restructure (php artisan about plus php artisan package:discover if in doubt).
  • extends is mostly view resolution: parent-theme routes, translations and config are not merged automatically. If you expect parent routes to appear under a child theme, you'll need to wire that yourself.
  • Asset publishing: theme assets usually need to be reachable from public/. Symlink or copy them at deploy time; don't assume the package serves them through a route.
  • Path stacking: if you also call view()->addLocation() for plugin views, those paths stack with the theme's. Use view()->getFinder()->getPaths() when debugging why the wrong index.blade.php loads.
  • Debug quickly: dd(Theme::get(), config('theme')) plus dd(view()->getFinder()->getPaths()) tells you what actually resolved at runtime.
  • Extension points: the Theme facade and config/theme.php are the supported surface. Subclass Yaap\Theme\Theme or bind your own implementation in the container if you need deeper control — avoid editing vendor files.
  • Small ecosystem: 95 stars and zero dependents means the package is usable but lightly exercised. Pin the version in composer.json and keep your theme folder layout conventional so you can swap in a custom implementation later if a quirk bites.
  • MIT license: vendoring a patched copy into your repo is legally fine if you need a quick fix.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package