infyomlabs/laravel-calendar-events
Laravel Calendar Events is a ready-to-use package for adding calendar event management to Laravel apps. It provides models, migrations, controllers, routes, and views for creating, editing, and displaying events in a calendar interface.
This is a small, batteries-included package for rendering a month-view event calendar inside a Laravel app — migration, Event model, trait, controller, routes and Blade views all shipped. v1.2.0 is essentially the Laravel 10 compatibility release (no API changes announced), so the integration steps below apply from v1.1.x onward.
Minimal setup:
composer require infyomlabs/laravel-calendar-events
php artisan vendor:publish --provider="InfyOm\CalendarEvents\CalendarEventsServiceProvider"
php artisan migrate
Look here first, in this order:
config/laravel-calendar-events.php — the model binding and any layout/view settings. Almost all customisation starts here.start_date / end_date, title, description) before you write any queries against them.src/Traits/CalendarEvent.php — this is the actual API surface: $fillable, date casts and the getEvents()-style query used by the controller. Read this before extending anything.resources/views/vendor/laravel-calendar-events/ — the month grid; this is where you'll spend most of your customisation time.First use case: hit /calendar (the package registers a route), see an empty month grid, then create an event:
\InfyOm\CalendarEvents\Models\Event::create([
'title' => 'Kickoff',
'start_date' => now(),
'end_date' => now()->addHour(),
]);
If the event doesn't appear, you've almost certainly hit a date-format issue rather than a package bug — see Gotchas.
Use the shipped model, or bind your own. The Event model is intentionally thin. Two viable patterns:
InfyOm\CalendarEvents\Models\Event and add your own user_id, status, etc. via a migration. Fastest, but couples you to the package's namespace.App\Models\Event extending Illuminate\Database\Eloquent\Model and use CalendarEvent. Point config('laravel-calendar-events.models.event') at it. This is the pattern I'd recommend for anything beyond a prototype — you control fillable, relationships and accessors, and the package only supplies the rendering contract.Rendering the calendar inside an authenticated layout. Publish the views and have your own page @include the package's calendar partial rather than sending users to the package route. That keeps the package's public route unexposed and lets you wrap it in auth/tenant middleware.
Multi-source events (the common real requirement). If events come from more than one table (e.g. Event + Appointment), the trait's single-model binding is a limitation. The workable approach is a read-model: a scheduled command or observer that denormalises both sources into the events table, or a custom controller that merges two collections and passes them to a published view. Don't try to make the config accept an array of models — it won't.
Colour / styling per event. The published view reads event attributes directly, so adding a color column and a small Blade conditional in your overridden partial is the clean extension point. Avoid editing the compiled assets; override the view and let your app's CSS handle it.
Seeding and testing. Because start_date/end_date are cast to Carbon, factories and seeders should pass Carbon instances or ISO-8601 strings (now()->toIso8601String()), not Y-m-d. In tests, assert on the rendered view (assertSee('Kickoff')) rather than the model — the model is just Eloquent.
Integration tip: wrap calendar queries in a repository or scope so you can swap the package out later. The package is low-maintenance (v1.2.0 is a one-PR release from a first-time contributor), so treat the rendering layer as replaceable and keep your own date-range logic outside it.
composer why-not infyomlabs/laravel-calendar-events before assuming the package is at fault.DATETIME and cast in the app timezone. Mixing UTC writes with a non-UTC app.timezone pushes events across month boundaries and off the grid. Store in one timezone, render in one timezone.start_date within the month window; an event starting on the 31st at 23:00 can fall outside it. Verify the trait's scope actually uses whereBetween with padded boundaries, and add end_date overlap logic in your own controller if not.vendor:publish will happily overwrite your edited views. Publish once, commit the result, and never re-publish in a deploy script. If you must, publish to a differently-named tag.events table, the published migration will fail or, worse, silently do nothing if you've configured a different table. Rename the migration or the table before running it.php artisan route:list --path=calendar and wrap or remove it. The package has no opinion on authorisation.php artisan config:clear after touching the config (the model binding is cached), then php artisan route:list, then dd() inside the published controller. Blank calendar with a populated table is nearly always the model binding pointing at the wrong class.RRULE, .ics export, or Google/Outlook sync, this package is the wrong tool — reach for spatie/laravel-google-calendar or sabre/vobject instead. It draws a month, that's it."infyomlabs/laravel-calendar-events": "^1.2") and watch upstream activity. With a single contributor and sparse release cadence, plan on forking the view layer if you need sustained changes — the published views make that cheap, which is really this package's main virtue.How can I help you explore Laravel packages today?