Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Platform Laravel Package

asgardcms/platform

AsgardCMS Platform provides the core foundation for a modular, multilingual CMS built on Laravel, with extensible modules for managing pages, menus, media, users, and permissions.

View on GitHub
Deep Wiki
Context7

Getting Started

asgardcms/platform is not a library you composer require into an existing app — it is the application skeleton. You get it via composer create-project, and it arrives pre-wired with a modular architecture (Modules/), a theming layer (Themes/), and a set of first-party modules pulled in as Composer dependencies.

Reality check before you start. This is the 3.6.x line, which is Laravel 5.x / PHP 7.1–7.2 era. Patch releases still land (3.6.1 fixes regressions from 3.6.0), so the codebase is maintained but not modernised: it will not resolve cleanly on PHP 8 or against modern Composer 2 metadata. Plan on:

# PHP 7.2/7.3 container is the path of least resistance
composer create-project asgardcms/platform my-app "~3.6.1" --no-scripts
# if dependency resolution fights you:
composer install --ignore-platform-reqs --no-scripts

Pin to ~3.6.1, not ~3.0, and not 3.6.0. 3.6.0 shipped a routing/localization regression that 404'd locale-prefixed frontend routes; 3.6.1 reverts it. If you already installed 3.6.0, upgrading to 3.6.1 is the fix — no manual patching needed.

Then the standard bootstrap:

cp .env.example .env
php artisan key:generate
php artisan migrate
php artisan asgard:install        # seeds admin user, settings, default content
php artisan module:publish        # pushes module Assets/ into public/modules/
php artisan serve

Because module/asset command names drifted across Asgard versions, run php artisan list once and note the asgard:* and module:* commands actually present in your install. On 3.6.x you should see asgard:module:scaffold plus the theme scaffold equivalents — those are the ones to use rather than hand-writing boilerplate.

Where to look first, in order:

  1. Modules/ — one directory per feature: Core, User, Dashboard, Media, Menu, Page, Blog, Setting, Translation, Workshop. Note these are installed here (not in vendor/) by composer/installers using the asgard-module package type; themes are analogous with asgard-theme → Themes/.
  2. Modules/Page/ — read this module top to bottom. It is the canonical reference implementation: Entities/ (with a PageTranslation), Repositories/ (+ cache decorator and presenter), Http/Controllers/ (backend + frontend), Http/Requests/, Resources/views/, Routes/, Config/permissions.php, Database/Migrations/, Providers/.
  3. Modules/Workshop/ — the scaffolders. Read this before generating anything so you know what the generated module looks like and which base classes it binds to.
  4. config/ — especially laravellocalization.php (locale prefixes), app.php providers, and the modules/themes config.
  5. Themes/ and public/themes/ — the frontend layer.

First use case: scaffold a "News" module with php artisan asgard:module:scaffold, then use Modules/Page as the reference for anything the scaffold doesn't generate (translatable entities, criteria, permissions, frontend routes). Everything you need — CRUD in the admin, translations, permissions, frontend route — is demonstrated in Page.

Implementation Patterns

Module anatomy. Every module carries a module.json (name, slug, version, providers, autoload) plus a service provider that registers routes, views, translations, config, and migrations. Scaffolded modules on 3.6.x get "version": "1.0.0" written into module.json by default (same for generated themes) — keep that field populated and bump it per release; tooling and the admin module list read it. Add a feature by creating a new module — never by editing Modules/Core or any other Composer-installed module, because composer update will overwrite it.

Repository pattern is the spine. Asgard layers prettus/l5-repository with its own base classes. Day to day you'll write:

class PageRepository extends BaseRepository implements PageRepositoryInterface
{
    public function boot() {
        $this->pushCriteria(new RequestCriteria($this->app));
        $this->pushCriteria(new WithTranslationsCriteria($this->app));
    }
}

and consume it as $this->page->with(['translations'])->find($id) or $this->page->paginate(15). Controllers stay thin; validation lives in Http/Requests; cross-cutting filtering lives in criteria, not in controllers. Use skipCriteria() when you need raw data (exports, imports, admin grids).

Be deliberate about which repository base class you import — the Workshop scaffolder historically bound the wrong one (laravel-modules' Repository instead of Asgard's), which produced generated modules that fataled on instantiation. That's fixed in 3.6.1; if a freshly scaffolded module blows up with a binding/interface error, you're on stale Workshop code.

Caching via decorator. Modules bind a Cacheable*Repository decorator (backed by the cache repository) in the service provider. This is the biggest performance win and the biggest source of "why isn't my data updating" — see Gotchas.

Multilingual entities. Any translatable model has a $translatedAttributes array and a sibling XTranslation model. Patterns that matter:

// entity
protected $translatedAttributes = ['title', 'slug', 'body'];
// repository hydrates the current locale via the translations criteria
$page->translate($locale)->title;

Admin forms use per-locale tabs, submit title[en], title[fr], etc., and the repository's create/update splits the translated keys into the translation table. If a field silently doesn't save, the first thing to check is whether it's listed in $translatedAttributes.

Routes split by surface. Modules ship separate backend and frontend route files loaded by the module's RouteServiceProvider. This is the area with the most churn across 3.6.x — the upstream routing service provider was reverted between 3.6.0 and 3.6.1 to fix #581. Keep your module RouteServiceProvider identical in shape to a freshly scaffolded one rather than copying from a blog post, and don't hand-roll route registration in a module you also want to route:cache. Frontend routes get locale prefixes from the localization package — read the current locale via LaravelLocalization::getCurrentLocale() rather than app()->getLocale() so URL generation stays consistent.

Permissions. Each module declares its permissions in Config/permissions.php, registered through the permission manager in the service provider and persisted on install/migrate. After adding a permission you must re-run the sync command and clear caches, otherwise your new admin screen 403s. Guard UI with the permission Blade directive and server-side with the permission check on the user object — never rely on hiding the menu item alone.

Cross-module integration. Use the Menu module to register admin nav and frontend menus, and the Setting module for configurable values (Setting::get('core::site-name')) instead of hardcoding. Fire domain events (PostWasCreated, etc.) from your service/repository layer and listen in other modules — that's how you avoid a Core module that knows about everything.

Theming. Create a child theme under Themes/Vendor/Name with a theme.json (scaffolder now writes a default version here too) and assets, then switch via the admin settings or the Theme facade (Theme::set(...), Theme::partial(...)). Frontend module views can be overridden in the theme, so client-specific markup never touches module source.

Upgrading a 3.6.x install. Patch releases touch published assets as well as source, so the sequence is: composer update, then php artisan module:publish (re-copies assets), php artisan module:migrate, php artisan vendor:publish --tag=... where applicable, composer dump-autoload -o, and finally cache:clear / view:clear / route:clear. Skipping the republish step after an upgrade is the number one cause of "the fix didn't take".

Testing. Feature-test admin endpoints with actingAs($admin) against the module's routes, and use database transactions per test. Beware that repository caching will happily serve stale rows between tests — disable the cache decorator or use the array cache driver in phpunit.xml.

Gotchas and Tips

  • Version lock-in is the main risk. PHP 8, Laravel 6+, and many modern packages are incompatible. If this is a new build, treat Asgard as an architectural reference, not a runtime. If it's an existing install, freeze PHP 7.2/7.3 in Docker and pin Composer dependencies with a committed composer.lock.
  • Stay off 3.6.0. Localization-aware routing broke there and was fixed in 3.6.1. Symptom: frontend pages 404 only under a locale prefix (/en/...), while backend admin routes work fine. If you see that on a 3.6.x install, check the version before debugging your own routes.
  • Repository cache staleness. Direct SQL, seeders, imports, and queued jobs bypass the cache decorator, so reads keep returning old data. Keep a consistent flush strategy (cache:clear, or tag/key-based invalidation) around any bulk mutation, and remember config:cache/route:cache/view:clear after changing providers, permissions, or routes.
  • Assets don't live where you edit them. Module source assets sit in Modules/X/Assets/; the served files are copies in public/modules/X/. Editing without republishing produces the classic "my CSS change did nothing" — republish and hard-refresh. This applies equally after a composer update of the platform, since releases commit published assets.
  • Module migrations are not php artisan migrate. They're run per module (module:migrate, or the module-scoped equivalent). Running only the app-level migrate leaves you with missing tables and confusing SQLSTATE errors.
  • New classes → composer dump-autoload. PSR-4 mappings come from module.json; a freshly generated class won't resolve until you dump autoload. Class-not-found errors after adding a module usually mean this, or a missing provider registration.
  • Missing version in module.json. Modules scaffolded before the version default was added can have no version key, which trips the module list and Composer installer metadata. Add "version": "1.0.0" (and keep bumping it) rather than fighting the tooling.
  • Never patch Modules/* directly. Composer will overwrite it. Extend through events, a wrapper repository binding, a theme override, or your own module that depends on the original.
  • Locale prefixes and route caching. Locale-aware route registration often breaks under route:cache; if you get 404s only in production, clear the route cache and check whether the module's routes are closure-based. The 3.6.0→3.6.1 routing revert is a reminder that this layer is fragile — keep route files declarative.
  • Permissions/seed drift. New permission entries exist in code but not in the DB until synced; menus and settings behave the same way. Add the sync step to your deploy script, right after migrate.
  • Debugging toolbox: php artisan module:list to confirm what's actually enabled, php artisan route:list to confirm routes loaded (and to spot missing locale prefixes), storage/logs/laravel.log with APP_DEBUG=true, and the events/listeners map when a change "isn't firing" — it's often a listener that was never registered in the provider.
  • Best extension points, in priority order: events/listeners → new modules → theme overrides → repository/interface rebinding. Direct source edits are last and should be documented as a fork if you truly need them.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib