Struktur Directory
Dokumen ini menjelaskan lokasi seluruh file setelah instalasi: file yang dipublish package ke aplikasi, file yang dibuat generator, serta dua path frontend yang dapat dikonfigurasi. Setelah memahami struktur ini, Anda akan lebih mudah mengetahui directory mana yang seharusnya berisi file yang hilang.
Apa yang Tersisa Setelah Instalasi
php artisan panel:install
git status --short2
config/panda-panel.php # published config
app/Panels/Admin/… # the scaffolded panel
resources/js/panel/… # the panel's components, layouts, renderers
resources/js/pages/panel/… # framework-generic Inertia pages
resources/js/pages/Panels/… # your panel-specific pages, widgets, columns
resources/js/components/… # UI primitives, published only where absent
resources/js/composables/…
resources/js/lib/…
resources/js/types/…
resources/css/panda-panel.css
.panel-assets.json # what you published, and what it looked like2
3
4
5
6
7
8
9
10
11
Semua file di bawah resources/js menjadi milik aplikasi sejak dipublish: masuk repository, ikut build, dan dapat diedit. Inilah yang dibutuhkan build-time component registry — component yang tidak pernah dilihat build tidak dapat di-resolve.
Tiga Lokasi Frontend
Pembagian ini bukan sekadar preferensi struktur. @inertiajs/vite hanya melakukan glob terhadap resources/js/pages/**, sehingga semua component yang harus dapat di-resolve Inertia berdasarkan nama harus berada di sana; component lainnya tidak perlu.
| Lokasi | Peran | Dapat Di-resolve Inertia |
|---|---|---|
resources/js/panel/** | Layout, component, renderer, composable, registry, type | tidak |
resources/js/pages/panel/** | Page generic milik framework | ya |
resources/js/pages/Panels/{Panel}/** | Page, Widget, dan Column khusus aplikasi | ya |
resources/js/panel
resources/js/panel/
├── actions/ ActionButton, ActionGroup, ActionDialog
├── components/ PanelSidebar, PanelNavigation, PanelHeader, PanelBreadcrumb, PageHeader, …
├── composables/ usePanel, useNavigation, usePanelPage, useResource, useActions
├── forms/ FormRenderer, FormComponentRenderer, FormSection, FormGrid, FormField, fields/*
├── hooks/ render hook plumbing
├── icons/ registry.ts — the build-time icon allowlist
├── infolists/ InfolistRenderer and its entries
├── layouts/ PanelLayout, SidebarPanelLayout, HeaderPanelLayout, PanelBlankLayout
├── lib/ grid.ts and shared helpers
├── relations/ relation manager UI
├── shell/ the panel chrome
├── tables/ DataTable, DataTableToolbar, DataTableFilters, DataTablePagination, …
├── types/ panel, navigation, breadcrumb, page, table, form, action, widget, guards
└── widgets/ WidgetGrid, WidgetRenderer, StatsWidget, TableWidget, ChartWidget, CustomWidget2
3
4
5
6
7
8
9
10
11
12
13
14
15
Tidak ada file di directory ini yang perlu di-resolve langsung oleh Inertia. File-file tersebut diimpor oleh Page, bukan disebut sebagai component name pada Inertia response.
resources/js/pages/panel
Berisi Page yang dirender langsung oleh framework. Terdapat tujuh belas file, dan setiap Page mendeklarasikan layout-nya sendiri:
resources/js/pages/panel/
├── Dashboard.vue panel/Dashboard
├── Page.vue panel/Page — the generic renderer
├── auth/
│ ├── EmailCode.vue ForgotPassword.vue Login.vue
│ ├── Register.vue ResetPassword.vue VerifyEmail.vue
├── resources/
│ ├── Create.vue Edit.vue Index.vue
│ ├── Integrations.vue ManageRelated.vue View.vue
└── settings/
├── Appearance.vue Profile.vue Security.vue2
3
4
5
6
7
8
9
10
11
Component name sebuah Page merupakan path relatif di bawah resources/js/pages tanpa extension — Page class yang mendeklarasikan protected static string $component = 'panel/Page' sedang meminta resources/js/pages/panel/Page.vue.
resources/js/pages/Panels
Ini adalah tree milik aplikasi. Generator menulis custom component ke sini, dan component registry melakukan glob terhadap directory ini:
resources/js/pages/Panels/
└── Admin/
├── Columns/AccountAge.vue custom table cells
├── Hooks/Announcement.vue render hook components
├── Pages/Settings.vue make:panel-page --component
└── Widgets/SystemInfo.vue make:panel-widget --type=custom2
3
4
5
6
Nama component yang tidak ada dalam glob akan gagal di-resolve. Pada development, Panel memberi warning satu kali untuk setiap nama yang tidak dikenal dan menyebut directory tempat component seharusnya berada. Pada production, component tersebut hanya tidak dirender.
PHP Milik Aplikasi
app/Panels/
├── Admin/
│ ├── AdminPanelProvider.php
│ ├── Pages/
│ │ └── Settings.php
│ ├── Resources/
│ │ └── Users/
│ │ ├── UserResource.php
│ │ ├── Forms/UserForm.php
│ │ ├── Tables/UsersTable.php
│ │ ├── Infolists/UserInfolist.php
│ │ ├── Exports/UserExporter.php
│ │ ├── Imports/UserImporter.php
│ │ └── Pages/
│ │ ├── ListUsers.php CreateUser.php ViewUser.php EditUser.php
│ └── Widgets/
│ ├── UserStats.php RecentUsers.php UserGrowth.php SystemInfo.php
└── App/
└── AppPanelProvider.php2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Struktur tersebut adalah hasil yang kurang lebih dibuat oleh make:panel-resource User --panel=Admin, kecuali Infolist, Exporter, dan Importer yang ditambahkan saat dibutuhkan. Directory Resource menggunakan bentuk plural Studly (Users), sedangkan nama class tetap singular (UserResource).
Discovery membaca nama class dari prefix PSR-4 Composer. Karena itu struktur directory di atas merupakan convention dengan satu aturan keras: namespace harus sesuai dengan path. Jika tidak, discovery tidak menemukan class di dalamnya.
Tidak ada bagian lain di app/ yang dipindahkan. Policy tetap berada di app/Policies, Model tetap di app/Models, dan Resource Panel menunjuk ke keduanya.
Lokasi Output Setiap Generator
| Command | PHP | Vue |
|---|---|---|
make:panel Admin | app/Panels/Admin/AdminPanelProvider.php, ditambah Pages/, Resources/, Widgets/ dengan .gitkeep | — |
make:panel-resource User --panel=Admin | app/Panels/Admin/Resources/Users/{UserResource,Forms/UserForm,Tables/UsersTable,Pages/*}.php | — |
make:panel-page Reports --panel=Admin | app/Panels/Admin/Pages/Reports.php (component panel/Page) | — |
make:panel-page Reports --panel=Admin --component | sama seperti di atas, component Panels/Admin/Pages/Reports | resources/js/pages/Panels/Admin/Pages/Reports.vue |
make:panel-widget Revenue --panel=Admin --type=stats | app/Panels/Admin/Widgets/Revenue.php | — |
make:panel-widget Health --panel=Admin --type=custom | sama seperti di atas | resources/js/pages/Panels/Admin/Widgets/Health.vue |
make:panel-relation-manager posts --panel=Admin --resource=Users | di bawah directory Resource | — |
Page tanpa --component menggunakan renderer generic panel/Page, sehingga Page yang tidak membutuhkan tampilan khusus sama sekali tidak memerlukan file Vue. custom Widget menjadi pengecualian: component tidak opsional karena tanpa component tersebut Widget hanya dapat menampilkan fallback.
Dua Path yang Dapat Dikonfigurasi
// config/panda-panel.php
'frontend' => [
'panel_path' => 'js/panel',
'pages_path' => 'js/pages/Panels',
],2
3
4
5
Keduanya relatif terhadap resources/ dan dibaca melalui satu class agar publisher, generator, icon command, dan code lain tidak memiliki implementasi path masing-masing:
use PandaPanel\Support\FrontendPaths;
FrontendPaths::panel(); // /app/resources/js/panel
FrontendPaths::panel('icons/registry.ts'); // /app/resources/js/panel/icons/registry.ts
FrontendPaths::pages(); // /app/resources/js/pages/Panels
FrontendPaths::pages('Admin/Widgets/X.vue'); // /app/resources/js/pages/Panels/Admin/Widgets/X.vue2
3
4
5
6
pages_path juga menjadi root untuk import.meta.glob yang digunakan frontend untuk me-resolve component name. Jika path ini dipindahkan, glob tersebut juga harus disesuaikan.
File yang Bukan Source Code
| Path | Ditulis oleh | Perlu Di-commit? |
|---|---|---|
.panel-assets.json | panel:install, panel:assets | Ya. Mencatat versi frontend Panel yang dipublish aplikasi, seperti composer.lock mencatat dependency yang diinstal. Tanpa file ini upgrade tidak dapat membedakan perubahan aplikasi dari copy yang tertinggal versi. |
bootstrap/cache/panels.php | panel:cache | Tidak. Ini build artifact yang hanya menyimpan nama class dan dibangun ulang saat deployment. panel:clear menghapusnya. |
stubs/panel/*.stub | vendor:publish --tag=panda-panel-stubs | Ya, jika Anda mempublish stub. Ini adalah cara project mengubah output generator. |
Manifest sengaja disimpan di root aplikasi: jika berada di bootstrap/cache, file akan diregenerate dan kehilangan fungsi historisnya; jika berada di storage, file biasanya masuk .gitignore dan hilang pada deployment pertama.
Struktur di Dalam Package
Bagian ini berguna saat membaca stack trace. Namespace PandaPanel\* dipetakan ke src/:
| Namespace | Isi |
|---|---|
PandaPanel\Core | Panel, PanelProvider, PanelManager, PanelRegistry |
PandaPanel\Resources | Resource, Resource Page, ResourceConfiguration |
PandaPanel\Tables, Forms, Infolists, Widgets, Actions | Schema builder dan component masing-masing |
PandaPanel\Pages | Page, Dashboard, tiga Settings Page |
PandaPanel\Http | Controller dan middleware |
PandaPanel\Routing | PanelRouteRegistrar |
PandaPanel\Discovery, Cache | Discovery dan manifest |
PandaPanel\Console\Commands | Seluruh Artisan command |
PandaPanel\Support | Helper, FrontendPaths, PanelContext, dan Support\Installer\* |
PandaPanel\Contracts | PanelUser, PanelNotifiable, HasPanelTenants, PanelPlugin |
PandaPanel\Testing | Test helper yang dikirim package dan di-autoload |
docs/, examples/, tests/, dan frontend/ masuk export-ignore, sehingga composer require tidak membawa directory tersebut. Gunakan repository/GitHub untuk membacanya; jangan mengharapkan directory itu berada di vendor/.
Catatan
vendor:publishkeresources/js/componentstidak menimpa component Anda. Tanpa--force, file yang sudah ada akan dilewati. Ini adalah behavior yang diharapkan pada starter kit yang sudah memiliki sebagian besar component tersebut.- Directory kosong tidak dilacak Git. Karena itu
make:panelmenulis.gitkeeppada tiga discovery directory. Jika dihapus, hasil clone dapat tidak memiliki directory yang ditunjuk provider. - Memindahkan
panel_pathsetelah asset dipublish meninggalkan copy lama.panel:assetsmembandingkan terhadap destination yang sedang dikonfigurasi; tree lama akan terlihat sebagai file di luar tracking, bukan sebagai file yang dapat otomatis dihapus. resources/js/pages/Panelscase-sensitive pada Linux. Directory lowercasepaneladalah Page milik framework;Panelsdengan huruf kapital adalah milik aplikasi. Keduanya merupakan directory berbeda dan sama-sama ada.
Lihat Juga
- Installation — publish tag dan file yang dipindahkan masing-masing
- Frontend requirements — publish map dan host seam
- Opening your first panel
- Resources: directory convention
- Concepts: component registries, frontend assets, caching
- Configuration: frontend paths
- Frontend: custom pages, custom widgets, custom columns