App Package structure
Find the file to change for an App feature and understand which identifiers belong to its public contract.
App Package structure
Find the file to change
An App is one independent repository and Composer release. After Create an App Package and Create a Resource, use this map to find the owner of a change. Paths below are relative to the App root.
| Change | File or directory |
|---|---|
| Package identity and dependency ranges | composer.json |
| Frontend peer dependencies and App aliases | package.json |
| Discovery locations and migration paths | src/WorkshopAppManifest.php |
| Persistent fields | database/migrations/tenant/ and src/Models/Note.php |
| Validation and API responses | src/Http/Controllers/NoteController.php |
| Record authorization | src/Policies/NotePolicy.php |
| Resource identity, descriptor, permissions, menu | src/Contribution/Resources/NoteModule.php |
| API routes | routes/routes.php |
| Resource types and route helpers | resources/js/resources/notes/note-resource-contract.ts |
| Shared detail/form field presentation | resources/js/resources/notes/note-information-schema.tsx |
| Page state and data fetching | resources/js/resources/notes/surface/ |
| List, form, and detail composition | resources/js/resources/notes/section/ |
| Frontend registration | resources/js/index.ts |
| Labels | resources/lang/{locale}.json |
| Regression coverage | tests/ and frontend tests |
This is the Workshop/Note generated layout, not a claim that every existing App
uses identical internal composition. The generator source is
app/Console/Commands/MakePackageResource.php and stubs/package-resource/.
Make one change across its owners
Adding a field usually changes persistence, validation, response types, and presentation. Declaring it in a descriptor alone does not implement storage or form handling. Follow Data Model and Migrations, then Build an App screen.
Keep private helpers beside their App feature. A capability belongs in the SDK only when it expresses a durable platform responsibility, not just because two Apps happen to need similar code. For another App's data, use Choose a cross-App integration.
Identity and discovery
| Identifier | What depends on it |
|---|---|
| Composer package name | Dependency selection and release installation |
app_key | App identity, route and permission namespaces |
app_table_prefix | App-owned table names |
| Resource key | Catalog, permissions, references, and descriptors |
| Descriptor or event key | Published configuration and runtime consumers |
Treat public keys as compatibility contracts. A label can change without renaming its key. A table prefix or Resource key change needs an explicit migration and consumer plan; it is not a routine refactor.
Manifest-declared contribution locations determine discovery. Putting a class in any arbitrary folder is insufficient. The generator prepares these locations; see Extension Model before introducing another contribution. The exact metadata contract is in App manifest.
Local source and installed packages
Local setup can mount a selected App checkout under packages/. That is an
editing arrangement. CI and released hosts may install the same package under
vendor/ from Composer. Your runtime code must work with either installation.
Use manifest-relative paths or the SDK's supported metadata; never reconstruct
a Core package path. Do not edit vendor/.
All package files ship together: PHP, frontend, translations, and migrations. Release an App explains version selection and host installation. A source checkout existing on disk does not prove that Composer is currently using it.