tomatophp/circle-notes-module
A notes module for TomatoPHP and Laravel admin panels, adding simple note management to your dashboard. Early-stage package with minimal adoption, so review the source and documentation before relying on it in production.
tomatophp/circle-notes-module v1.0.0 is the first tagged release, so treat it as greenfield adoption rather than an upgrade — there is no migration guide, no deprecation list, and no prior API surface to preserve. The release notes are a bare changelog link, so the source tree and README are your real documentation.
Minimal path to a working install:
composer require tomatophp/circle-notes-module — pin it explicitly ("^1.0") since 1.x is unproven and patch releases may still shift signatures.php artisan vendor:publish --tag=circle-notes-config (verify the exact tag with php artisan vendor:publish --provider="TomatoPHP\CircleNotes\CircleNotesServiceProvider" if the tag isn't documented).php artisan migrate and confirm the published migrations create the notes table(s) with the foreign keys your Circle (or equivalent parent) model expects.module.json; if you use the modules package you may need to enable it in modules_statuses.json instead of relying on discovery.First use case to validate end-to-end: attach a note to a parent record in tinker before touching any UI.
$circle = Circle::first();
$circle->notes()->create(['body' => 'smoke test', 'user_id' => auth()->id()]);
If that relation doesn't exist, the package is exposing its own Note model with a noteable morph instead — check src/Models for the actual contract before wiring anything into your app.
Where to look first, in order: src/Models/Note.php, the migration stubs, src/CircleNotesServiceProvider.php (for published tags and bindings), then any Filament resource classes under src/Filament. The provider tells you more about the package's integration points than the README usually will.
Relation-manager attachment. The most common integration is hanging notes off an existing Eloquent model. If the package ships a trait (commonly HasNotes or similar), add it to your Circle/Team/Project model and let the package own the inverse side. If it doesn't ship a trait, add the morphMany yourself and match the morph alias the package registers — mismatched aliases are the single most common cause of empty result sets.
Polymorphic noteable. Notes modules are almost always polymorphic so a note can belong to a circle, a thread, or a user. Register a stable morph map in AppServiceProvider::boot() before anything else touches the relation:
Relation::enforceMorphMap([
'circle' => \App\Models\Circle::class,
'user' => \App\Models\User::class,
]);
Do this on day one. Retrofitting a morph map onto rows written with FQCNs is a data migration you don't want.
Filament resource extension. In the TomatoPHP ecosystem these modules typically ship Filament resources rather than plain controllers. Two viable patterns:
/admin/notes. Fastest, but you inherit its form schema and table columns wholesale.form()/table() only. Prefer this when you need tenancy scoping or extra columns; subclassing survives patch releases far better than copy-pasting the resource into app/.Add the notes relation manager to your own CircleResource rather than linking out to a separate page — users expect notes inline with the parent record, and it keeps authorization in one place.
Authorization. Do not assume policies ship with 1.0.0. Check for a Policies directory; if it's absent, create NotePolicy yourself and register it, otherwise every authenticated user can edit every note. This is the highest-risk gap in a young module.
Events and side effects. If the package dispatches NoteCreated/NoteUpdated, hook notifications, search indexing, and audit logging there instead of overriding controllers. If it doesn't dispatch events, wrap creation in your own action class so you have a single seam to add them later.
Seeding and tenancy. For multi-tenant apps, confirm the migration includes a tenant_id/team_id column or that notes are scopable through the parent. If not, add a global scope on the Note model rather than filtering in every query.
composer.json and read the diff on every bump until 1.1+ lands with real notes.php artisan config:clear. A stale bootstrap/cache/config.php silently ignores your new circle-notes.php and you'll debug a problem that doesn't exist.Filament\Resources\Resource signatures, form/table schema APIs). Confirm the module's composer.json constraint matches your installed major; a resource that loads but renders an empty form is usually a version mismatch, not a bug.$circle->notes returns an empty collection. Dump Note::first()->noteable_type and compare it against your morph map.--tag=circle-notes-translations or the package equivalent) if you need to override labels; editing vendor files works until the next composer update and then vanishes.composer dump-autoload after enabling it in modules_statuses.json — the module's namespace won't resolve otherwise and you'll get a confusing "class not found" from the provider.php artisan about to confirm the provider is loaded, (2) php artisan route:list | grep note for Filament routes, (3) check storage/logs/laravel.log for policy/authorization denials before assuming a UI bug, (4) verify the morph map.git diff between tags before upgrading in production.How can I help you explore Laravel packages today?