Every addon mirrors Laravel's application layout inside Addons/YourAddonName/. The key directories are Config/, Console/ (artisan commands), Database/Migrations/ and Seeders/, Helpers/, hooks/, Http/ (controllers, middleware, form requests), Models/, Providers/, Resources/ (views, lang, source assets), Routes/ (web.php and api.php), Settings/ (addon metadata plus install/uninstall SQL), and Tests/. Root files include the required module.json manifest, composer.json (merged into the main app via composer-merge-plugin), menu.json for sidebar navigation, and functions.php with lifecycle functions — install_addon() and update_addon() take no parameters and must return an array with a success key.
The public/ directory is the only web-accessible part of the addon: a symlink maps public/Addons/YourAddonName/ to it, so public/css/addon.css is served at /Addons/YourAddonName/css/addon.css. Put only compiled CSS/JS, images, fonts, and downloadable files there. Source files needing compilation (SASS, ES6) belong in Resources/assets/, with Laravel Mix output going to public/. Never place PHP files, configs, or secrets in public/.
Conventions to follow: addon directory in PascalCase with a lowercase alias, controllers suffixed Controller, singular PascalCase models, date-prefixed snake_case migrations, kebab-case views, and all classes namespaced under Addons\YourAddonName\. Keep controllers thin and use module_path() and asset() instead of hardcoded paths.