Going further
Modules and packages
A module of your app, or a package you publish, can keep its components, pages and stores in folders of its own. It registers them under a namespace, and its components are named with it: billing::invoice-table.
On this page
By default Nitro finds components in app/Nitro/Components, pages in app/Nitro/Pages
and stores in app/Nitro/Stores. That suits most apps. A large app split into modules, each
owning its screens, or a package that ships components, needs its own folders instead. That's what
nitro.namespaces is for. It works like Blade's view namespaces: Laravel's
loadViewsFrom(..., 'billing') gives you billing::invoice views, and a Nitro
namespace gives you billing::invoice-table components.
Registering a namespace
The module's service provider adds its namespace in register(), and loads its Blade views in
boot(), as any Laravel package does:
// modules/Billing/BillingServiceProvider.php
namespace Billing;
use Illuminate\Support\ServiceProvider;
class BillingServiceProvider extends ServiceProvider
{
public function register(): void
{
config()->set('nitro.namespaces.billing', [
'components' => [
'namespace' => 'Billing\Ui\Components',
'path' => __DIR__.'/Ui/Components',
'views' => 'billing::components',
],
'pages' => [
'namespace' => 'Billing\Ui\Pages',
'path' => __DIR__.'/Ui/Pages',
'views' => 'billing::pages',
],
'stores' => [
'namespace' => 'Billing\Ui\Stores',
'path' => __DIR__.'/Ui/Stores',
],
]);
}
public function boot(): void
{
$this->loadViewsFrom(__DIR__.'/resources/views', 'billing');
}
}
Each part is optional: a module with components only leaves out pages and stores.
Each takes what nitro.components, nitro.pages and nitro.stores take:
the classes' PHP namespace, their folder, and for components and pages the prefix of their Blade views.
- The name. A namespace is named in kebab case, such as
billingorbilling-admin.pagesandstoresare taken: they start page and store names. - Views. A component's view is its name under
views:billing::components.invoice-table, from the Blade namespace the provider loads. Withoutviews, it isbilling::invoice-table. - Folders inside folders. Pages may sit inside the components' folder, as
Ui/Components/Pageswould. A class belongs to the most specific folder that holds it, so those are pages, not components.
Names
A class in the namespace is named as the app's are, with the namespace in front:
| Class | Name |
|---|---|
Billing\Ui\Components\InvoiceTable
|
billing::invoice-table
|
Billing\Ui\Components\Reports\Summary
|
billing::reports.summary
|
Billing\Ui\Pages\Invoices\Index
|
pages::billing::invoices.index
|
Billing\Ui\Stores\Basket
|
stores::billing::basket
|
A component is an ordinary Nitro component:
// modules/Billing/Ui/Components/InvoiceTable.php
namespace Billing\Ui\Components;
use Billing\Contracts\Invoices;
use Nitro\Attributes\Server;
use Nitro\Component;
class InvoiceTable extends Component
{
public array $invoices = [];
public function mount(Invoices $invoices): void
{
$this->invoices = $invoices->open();
}
#[Server]
public function markPaid(int $id, Invoices $invoices): void
{
$invoices->markPaid($id);
$this->invoices = $invoices->open();
}
}
Place it by its name, from any view: the app's, or another module's:
{{-- any view of the app, or of another module --}}
<nitro:billing::invoice-table />
{{-- a component in a folder of the module: Ui/Components/Reports/Summary.php --}}
<nitro:billing::reports.summary :year="2026" />
Pages are routed by their class, so their names rarely show. A namespace's page is a chunk of its own, as
the app's are, named billing.invoices.index:
// modules/Billing/routes/web.php
use Billing\Ui\Pages\Invoices;
Route::nitro('/invoices', Invoices\Index::class);
Route::nitro('/invoices/{invoice}', Invoices\Show::class);
A store is used through a property of its type, as any store is, so its name doesn't show at all. See Sharing state.
Making components
make:nitro writes into a namespace when the name has one: the class into its folder, the view
into the Blade namespace its provider loads.
php artisan make:nitro billing::InvoiceTable
php artisan make:nitro billing::Invoices/Index --page
php artisan make:nitro billing::Basket --store
It stops with a message when the namespace isn't registered, when it has no folder for that kind (a page in a
namespace without pages), or when its Blade views aren't loaded.
Vue, React, Solid and Svelte views
A namespace can have JavaScript views too. Give it a folder for each engine it uses:
// in register(), beside 'components' and 'pages'
'views' => [
'vue' => __DIR__.'/resources/views/vue',
],
Its components name their views with the namespace:
// modules/Billing/Ui/Components/InvoiceChart.php
#[View(vue: 'billing::invoice-chart')]
class InvoiceChart extends Component
{
// ...
}
Nitro finds invoice-chart.vue in the module's folder. Your Vite builds it, so the browser has
to find it too: give the adapter the module's views with namespaced(), beside the app's.
Every adapter has it: nitro/vue, nitro/react, nitro/solid and
nitro/svelte.
// resources/js/app.js
import { nitroVue, namespaced } from 'nitro/vue';
nitroVue({
...import.meta.glob('../views/vue/**/*.vue'),
...namespaced('billing', import.meta.glob('../../modules/Billing/resources/views/vue/**/*.vue')),
});
A view named billing::invoice-chart is looked for among billing's views only, and
one without a namespace among the app's only, so two modules can each have an index.vue. A view
holding its own PHP, in a <php> block, works in a namespace's folder as in the app's, and
is named in the namespace: billing::invoice-chart.
In a package
A package registers its namespace the same way, in its own service provider, and ships its components,
pages and views in its own folders. Name the namespace after the package, so it doesn't meet another's. An
app that installs it places <nitro:billing::invoice-table /> without copying anything into its
own folders.
Builds and the cache
php artisan nitro:build includes every namespace's components, and its cached list is found
again when a file is added to any namespace's folder, as with the app's own.