> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Overriding and updating package views

> Based on the Laravel 13 implementation, this guide explains the lookup order for namespaced views, maintaining published Blade templates, and the difference between the view cache and cached lookup results.

A package that lets users customize screen or mail templates needs more than a way to publish views. It also needs a contract that allows updates while published files stay in place. Fixing a Blade file in the package does not guarantee that the consuming application is rendering that file.

This page builds on [Laravel Package Development](/en/advanced/package-development) and treats view selection, file publishing, and caching as separate concerns. The official documentation references Laravel 13, and framework references point to the latest release, `v13.34.0`.

## Registering and publishing are separate steps

`loadViewsFrom()` registers a search path for a namespace. `publishes()` registers a source and destination, and the actual copy is performed by `vendor:publish`. In the following example, `courier::deliveries.show` is available even without publishing.

```php src/CourierServiceProvider.php theme={null}
<?php

namespace Acme\Courier;

use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');

        $this->publishes([
            __DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
        ], 'courier-views');
    }
}
```

Place the package file at `resources/views/deliveries/show.blade.php`. Dots in the view name are converted to directory separators during lookup.

```php theme={null}
return view('courier::deliveries.show', [
    'trackingCode' => 'TRACK-001',
]);
```

```blade resources/views/deliveries/show.blade.php theme={null}
<p>Tracking number: {{ $trackingCode }}</p>
```

The view namespace is separate from the Composer package name and the PHP namespace. Here, `courier`, passed as the second argument to `loadViewsFrom()`, forms the contract for both view references and the override directory.

## Overrides are resolved per file

When `view` is resolved, `ServiceProvider::loadViewsFrom()` checks each entry in the `view.paths` config in order. If a path contains a `vendor/courier` directory, that directory is added to the namespace, and the package path is added last.

`FileViewFinder` searches the namespace's paths in order and returns the first file it finds. With the standard `resources/views` setup, the order is as follows.

```mermaid theme={null}
flowchart TD
    A["courier::deliveries.show"] --> B["Look for resources/views/vendor/courier/<br>deliveries/show.blade.php"]
    B --> C{"File exists?"}
    C -->|Yes| D["Use the application's view"]
    C -->|No| E["Look for the package's resources/views/<br>deliveries/show.blade.php"]
    E --> F{"File exists?"}
    F -->|Yes| G["Use the package's view"]
    F -->|No| H["View not found exception"]
```

This is not a switch for the whole directory. If a user overrides only `deliveries/show.blade.php`, every other view that was not overridden is still loaded from the package.

| State of the consuming application | View selected |
| - | - |
| No override file | The package's file |
| An override file exists at the same relative path | The application's file |
| Only the override file was removed | Falls back to the package's file on a fresh boot |
| Neither location has the file | `View [...] not found.` exception |

<Info>
  When `view.paths` has multiple entries, there can be multiple override locations. `resource_path('views/vendor/courier')` is the publish destination in this example, not something that pins lookup to that location alone. Use a package-specific namespace, and avoid designs where multiple providers add paths to the same name.
</Info>

## Customize only the views you need

Users can copy the templates with the following command. Specify the provider and tag so other resources are not pulled in.

```bash theme={null}
php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider" --tag=courier-views
```

This registration publishes the entire view directory. If users do not need to override everything, they can review the contents and keep only the files they customize, or manually copy just the files they need to the same relative paths. This matters because any copy that exists is treated as an override, even if it was never edited.

<Warning>
  Published templates are not automatically synchronized with package updates. If an outdated copy takes priority, fixing only the package's version will not change that view. Display bug fixes and form changes also need to be compared against the override files.
</Warning>

### Republishing does not merge changes

`VendorPublishCommand` normally skips the copy when a destination file with the same name already exists. `--force` overwrites existing files. `--existing` is also an option that "overwrites files that have already been published," not a mode that preserves user edits.

| Action | Effect on view files |
| - | - |
| Normal republish | Keeps existing files and copies target files that do not exist yet |
| Publish with `--force` | Overwrites existing customizations as well |
| Publish with `--existing` | Overwrites only target files that already exist at the destination |

None of these perform a merge that compares the old version, the new version, and the user's edits. They also do not automatically remove views from the destination that were deleted from the package. Do not reduce your update procedure to "just republish the same tag."

## Maintain views as a public API

Beyond view names, the data a view receives and the parts it references also affect user customizations. For example, if a new version renames `trackingCode` to a different variable, users who kept the old template can no longer receive the value they need from the new code.

Before a release, check the following contracts.

* Do not change the namespace or view names such as `deliveries.show` carelessly.
* Document the variables you pass, their types, and whether each is required or optional.
* Include the targets of `@include` and `@extends`, as well as Blade component props, in your list of changes.
* List the views you changed, and the changes that should be applied to previously published copies, in the release notes.

For users, provide a procedure for comparing the old and new package views and manually bringing the necessary changes into their customized files. Files that no longer need to be overridden can be removed to fall back to the package's views, after preserving any changes through backups or version control.

## The Blade cache does not update override files

`view:cache` precompiles Blade templates into PHP. `ViewCacheCommand` first runs `view:clear`, then collects the regular view paths and the paths registered for namespaces to find the templates to compile.

```bash theme={null}
php artisan view:cache
```

This process does not rewrite published Blade files, nor does it change view lookup priority. If an outdated override file exists, it will still be selected after the cache is rebuilt. During deployment, finish updating the code and override files before compiling.

If you want to delete the compiled files and re-render during development, use the following command.

```bash theme={null}
php artisan view:clear
```

When normal timestamp checking is enabled, the Blade compiler compares the modification times of the source file and the compiled file. However, some setups disable timestamp checking, so do not rely solely on automatic detection for rebuilds at deploy time.

### Distinguish this from cached lookup results

`FileViewFinder::find()` stores the paths it finds in the `$views` array of that Finder instance. In addition, the existence of override directories is checked in the `loadViewsFrom()` callback. Adding a new directory after boot does not automatically add it to the already registered search paths.

| What is managed | Role | How to handle updates |
| - | - | - |
| Published Blade files | User customizations | Bring in the changes, or stop overriding |
| Compiled PHP | Output of Blade compilation | Manage with `view:cache` / `view:clear` |
| Finder's registered paths and lookup results | View selection for the running instance | Restart long-running processes with the new code and configuration |

`view:clear` is not a command that wipes the Finder state held by other running processes. For long-running processes such as Octane, reload them according to your normal deployment procedure. The Finder's `flush()` clears lookup results, but it does not register new override directories.

## Checks before release

In addition to the package's tests, verify the following combinations in a consuming application. Tests that only render the latest templates cannot verify compatibility for users who published an older version.

* With nothing published, the package's views are rendered.
* Overriding a single file gives priority to that file only, and the rest fall back to the package.
* With the old version's published templates still in place, the views render with the data the new version passes.
* A normal republish preserves customizations, and the addition of unpublished files behaves as intended.
* After changing an override file, `view:cache` succeeds and a fresh boot shows the updated output.

## Related pages

<Columns cols={2}>
  <Card title="Views" icon="eye" href="/en/views">
    Review the basics of creating views, passing data, and precompiling.
  </Card>

  <Card title="Blade Templates" icon="code" href="/en/blade">
    Review how to use layouts, includes, and components.
  </Card>

  <Card title="Version Compatibility Management" icon="code-branch" href="/en/advanced/package-versioning">
    Tie template contract changes to your release policy.
  </Card>

  <Card title="Octane" icon="bolt" href="/en/octane">
    Review the lifecycle and reloading of long-running applications.
  </Card>
</Columns>

## Primary sources

* [Laravel official documentation: Package views](https://github.com/laravel/docs/blob/156fc7fde114548640e13c39aa79b991291c3f91/packages.md#views)
* [ServiceProvider: Registering view paths](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Support/ServiceProvider.php)
* [FileViewFinder: Lookup order and retained lookup results](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/View/FileViewFinder.php)
* [VendorPublishCommand: Conditions for publishing files](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/VendorPublishCommand.php)
* [ViewCacheCommand: Collecting view paths and compiling](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ViewCacheCommand.php)
* [ViewClearCommand: Deleting compiled files](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/Foundation/Console/ViewClearCommand.php)
* [Compiler: Checking modification times](https://github.com/laravel/framework/blob/v13.34.0/src/Illuminate/View/Compilers/Compiler.php)


## Related topics

- [Laravel Package Development](/en/advanced/package-development.md)
- [Advanced Topics](/en/advanced/index.md)
- [Publishing and updating package migrations](/en/advanced/package-migrations.md)
- [⚡ Getting started with Livewire 4 — reactive UIs without JavaScript](/en/blog/livewire-introduction.md)
- [Localization](/en/localization.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.