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

Laravel Meetups Laravel Package

nunomaduro/laravel-meetups

A small Laravel package for listing and displaying community meetups in your app. It offers a straightforward way to showcase local events with minimal setup, making it easy to add a meetups directory or events section to your project.

View on GitHub
Deep Wiki
Context7

Getting Started

Verify the shape first. Despite the "package" framing, the repo describes itself as a console application. Before running composer require, look for:

composer.json      → "autoload.psr-4"? "extra.laravel.providers"?
src/               → ServiceProvider / Facade / config file?
README.md          → `composer require` or `git clone && php artisan meetups`?

No service provider + no extra.laravel → treat it as a reference implementation, not a dependency. Copy the commands into app/Console/Commands rather than installing.

Install (only if it really is a package):

composer require nunomaduro/laravel-meetups

Expect resolution issues on modern Laravel. Fall back to the branch if needed:

composer require nunomaduro/laravel-meetups:dev-master --with-all-dependencies

Where to look first, in order:

  1. README.md — the sole doc; the v1.2.0 release is literally "Updated readme".
  2. config/ — data source, cache TTL, city/group slug.
  3. src/Console/ — the Artisan command is the primary entry point per the project description.
  4. The class making the HTTP call — this is the seam you'll wrap or replace.

First use case: publish config, set a source (group slug or city), run the command to confirm data flows before touching views.

php artisan vendor:publish --provider="NunoMaduro\LaravelMeetups\MeetupsServiceProvider" --tag=config
php artisan list | grep -i meetup     # discover the actual command signature
php artisan meetups                   # or meetups:list / meetups:near

Implementation Patterns

Wrap the fetch behind a service boundary

Don't call package classes from controllers or Blade. One thin wrapper means one file to change when (not if) the upstream breaks:

// app/Services/MeetupDirectory.php
namespace App\Services;

use Illuminate\Support\Facades\Cache;

class MeetupDirectory
{
    public function upcoming(int $limit = 5): array
    {
        return Cache::remember('meetups.nearby', now()->addHours(6), function () use ($limit) {
            // delegate to the package command's logic, or your own Http call
            return $this->fetchFromSource($limit);
        });
    }

    protected function fetchFromSource(int $limit): array
    {
        // your Http::get(...)->json() or the package class
    }
}

Drive from a command, render from a view

Given the console-app framing, keep the acquisition in a scheduled command and let the web layer just read cache:

// app/Console/Commands/SyncMeetups.php
class SyncMeetups extends Command
{
    protected $signature = 'meetups:sync';
    protected $description = 'Refresh cached nearby meetups';

    public function handle(MeetupDirectory $directory): int
    {
        $fresh = $directory->refresh();  // cache-busting fetch
        $this->info(sprintf('Cached %d meetups', count($fresh)));

        return $fresh === [] ? self::FAILURE : self::SUCCESS;  // signal emptiness to the scheduler
    }
}
// routes/console.php
Schedule::command('meetups:sync')->hourly()->withoutOverlapping();

Feature-flag the whole thing

Because the data source is unmaintained, put it behind config so a dark feature doesn't take up a slot in the page layout:

if (config('meetups.enabled')) {
    return view('partials.meetups', ['meetups' => app(MeetupDirectory::class)->upcoming()]);
}

Prototype → replace

Best day-to-day use is a prototype scaffold: ship the Blade listing with static/hardcoded data to validate the UI, then swap in a live fetch only once the page proves out. This mirrors the original framing — sourcing venues, speakers, and sponsorship targets — which is an operational win for a DevRel workflow even if the product feature never lands.

Gotchas and Tips

The description overstates the package. "Fluent API", "Blade-ready output", "configurable caching" — none of that is verifiable from a single "updated readme" release. Treat every capability claim as aspirational until you see the source. The actual shape is an Artisan command, so plan your integration around that.

Framework drift will bite immediately. 2017 release → targets Laravel 5.4/5.5 and PHP 7.0/7.1. On Laravel 10+ / PHP 8.2+, expect --ignore-platform-reqs, removed str_*/array_* helpers, and Guzzle v6 idioms to cause friction. If the goal is a working feature, rewriting ~150 lines against Laravel's Http facade is usually faster than debugging the original.

The meetup data source is the real risk, not the PHP. Meetup.com's API moved to OAuth-gated paid access years ago. If the command scrapes, it's fragile by definition — gate it behind a feature flag and treat parse failures as first-class errors, not silent null.

Silent failures are the default. A scraper returning HTML instead of JSON, or an API returning [] on quota exhaustion, will exit 0 and quietly go dark. Return self::FAILURE on empty results and add a freshness check (assert cache age in the view or a status endpoint).

Don't install it as a Composer dependency you rely on. 10 stars, 0 dependents, last release June 2017, no security patching. If you must vendor it, pin to a commit and accept full ownership — but the honest option is copy-and-modernize into your own namespace.

Replace Guzzle with Http on day one. Beyond framework alignment, Http::fake() gives you the test coverage the original never had:

Http::fake(['*' => Http::response([['name' => 'Laravel Berlin', 'date' => '2024-06-01']])]);
$this->artisan('meetups:sync')->assertSuccessful();

Cache aggressively and stagger. Event cadence is hours, not minutes. Cache::remember with a 4–6 hour TTL and ->hourly()->withoutOverlapping() protects the upstream quota — which, not compute, is your real ceiling if you fan out across cities.

Watch timezones and "near you". If geolocation is resolved from a stale default or a config slug, the "nearby" framing silently degrades. Pin an explicit timezone in config and render dates with ->timezone(config('app.timezone')).

Extension points are thin, by design. There's no driver/repository abstraction despite what the summary implies. Your realistic extension surface is: fork the command, swap the fetch, add caching and formatting. That's a few hours of reading — budget accordingly and don't go looking for a plugin architecture that isn't there.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels