corals/laraship
Laraship is a modular Laravel SaaS and CMS platform with an extensible admin panel, CRUD generator, themes, subscriptions, e-commerce, and reusable modules for building multi-tenant applications faster.
Laraship is distributed as an application skeleton, not a drop-in library. The fastest start is the skeleton install rather than composer require into an existing app:
composer create-project corals/laraship my-app
cd my-app
cp .env.example .env
php artisan key:generate
# configure DB in .env, then:
php artisan migrate
php artisan db:seed
php artisan serve
Where to look first, in order:
modules/ — the heart of the platform. Each business capability (users, roles, settings, media, blog, etc.) is a self-contained module with its own controllers, models, routes, views, migrations, and service provider. Read one small module end-to-end before writing anything.config/ — platform-level config for modules, themes, and settings. This is where feature toggles and module registration live.themes/ (or the theme path referenced in config) — front-end views are layered over module views; knowing the override order prevents a lot of confusion.First real use case: pick a trivial entity (e.g., Project or Ticket), scaffold a module for it, and wire it into the admin nav. That single exercise touches routing, permissions, migrations, views, and the settings system — the four things you'll do every day.
Module-oriented development. Treat every feature as a module. A typical module layout:
modules/Projects/
Controllers/
Models/
Requests/
Routes/web.php (and api.php where applicable)
Views/
Migrations/
Providers/ProjectsServiceProvider.php
module.json (or equivalent registration metadata)
Register the provider in config/app.php (or the platform's module registry — check how existing modules do it), then composer dump-autoload if the module uses its own namespace.
Scaffold-then-refine. The platform's CRUD/module generator gives you a working controller, model, migration, request validation, and admin views. Use it to get the boring 80% and then edit by hand. Don't hand-roll what the generator produces unless you have a strong reason.
Permissions as a first-class concern. New admin screens should be gated with the platform's role/permission system, not ad-hoc middleware. Define permission keys alongside the module and assign them to roles in a seeder so fresh installs and CI environments behave identically.
Settings over hardcoding. Site name, mail config, feature flags, and per-module options are typically stored through the settings service and cached. Read them via the helper/service rather than config() so admin edits take effect without a deploy.
Theme-aware views. When you need to customize a front-end screen, override the view in the active theme instead of editing module views. This keeps upgrades clean — module updates won't clobber your customizations.
Events and hooks for cross-module work. Modules shouldn't reach into each other directly. Fire an event from module A and listen in module B (registered in B's service provider). This is the difference between a maintainable platform and a ball of mud six months in.
Typical day-to-day loop:
php artisan make:module Invoice # or the platform's scaffold command
php artisan migrate
php artisan module:enable Invoice # name varies — confirm from existing modules
php artisan optimize:clear
Then iterate on controller → request → view, seed permissions, and add a menu entry.
composer require corals/laraship inside an existing Laravel project and expect it to graft on. It owns app/, routing conventions, the admin panel, and the module loader. Adopt it as the base or not at all.php artisan optimize:clear (and any module-specific cache clear). Stale route/config/settings caches cause the majority of "my new module doesn't appear" bugs.composer dump-autoload. Check the module's composer.json/namespace against the directory name.php artisan route:list when a 404 appears out of nowhere.How can I help you explore Laravel packages today?