naif/world-clock
A Laravel package for adding world clocks to your app. Display current local times for multiple cities or timezones, convert between zones, and configure clock labels and formats with simple, reusable Blade components.
This is a Laravel Nova card, not a general Laravel package — it renders a dashboard/panel widget showing the current time in one or more cities. Nothing happens unless Nova is installed and the card is registered.
composer require naif/world-clock
app/Providers/NovaServiceProvider.php, inside cards():use Naif\WorldClock\WorldClock;
public function cards()
{
return [
// ... your other cards
(new WorldClock)->timezones([
'America/New_York',
'Europe/London',
'Asia/Riyadh',
]),
];
}
/nova). If the card appears blank, you have an asset-registration problem, not a config problem — see Gotchas.Where to look first. Read these three files in the vendor directory before writing any code, because the fluent API surface is small and undocumented:
vendor/naif/world-clock/src/WorldClock.php — the card class; every public function here is a chainable config method.vendor/naif/world-clock/src/CardServiceProvider.php (or WorldClockServiceProvider.php) — tells you the component name and whether Nova::script() / Nova::style() are wired up.vendor/naif/world-clock/resources/js/card.vue — tells you the exact prop names the frontend expects, which is what withMeta([...]) must match.First real use case. "We have offices in three timezones and I keep opening worldtimebuddy during standups." Put one card on the main dashboard with two or three cities, confirm the times match date in a shell, then move on to per-user or per-team variants.
Fluent configuration in cards(). The idiomatic Nova pattern is to configure the card where you register it, so environment/tenant differences live in one file:
public function cards()
{
return [
(new WorldClock)->timezones([
'America/Los_Angeles',
'Europe/Berlin',
'Asia/Tokyo',
])->width('1/2'),
];
}
Nova's built-in ->width(), ->onlyOnDashboards(), ->canSee() and ->canRun() all work on any Card subclass, so you rarely need package-specific placement logic.
Fallback pattern when the fluent API is missing. Since the package is old and thinly documented, withMeta() is your escape hatch — anything in the meta bag arrives as a Vue prop:
(new WorldClock)->withMeta([
'timezones' => ['America/New_York', 'Europe/London'],
'label' => 'Team hours',
])
Verify the key names against card.vue; a mistyped key fails silently.
Per-user timezones. Cards are resolved per request, so $request->user() is available and you can drive the list from user settings — a nice upgrade over a hardcoded list:
(new WorldClock)->timezones(
collect($request->user()->watched_timezones ?? ['UTC'])
->prepend(config('app.timezone'))
->unique()
->values()
->all()
)
Multiple cards instead of one big card. If you want "US team" and "EU team" side-by-side with distinct widths, register two WorldClock cards. Nova renders each independently and you avoid fighting the Vue component's internal layout.
Resource detail pages. Cards are usually dashboard-only, but Laravel\Nova\Card can be attached to resource screens via Nova::resourcesFor()/panel definitions. If you want a clock on a specific resource, be aware the card refreshes only on page navigation — it is not a live element (see Gotchas).
Customization path. The package is 6 stars, MIT, last released 2019, zero dependents. Treat it as a vendored starting point: the realistic long-term pattern is to copy resources/js/card.vue + dist/js/card.js into your own nova-components/WorldClock and own it via php artisan nova:card. That takes an afternoon and removes the maintenance question entirely.
Nova::script() with a prebuilt dist/js/card.js). Nova 4 moved to Vite-built cards; the old compiled bundle often still loads, but Vue 2 → Vue 3 differences can break the component. Test on the exact Nova major you run before committing.composer dump-autoload, confirm extra.laravel.providers in the package's composer.json), then check the browser console for a 404 on card.js. php artisan nova:publish and php artisan view:clear fix most stale-asset cases.'EST' or a typo'd 'Europe/Berln' usually renders blank or Invalid Date rather than throwing. Always use IANA names (Continent/City). The authoritative list is php -r 'print_r(DateTimeZone::listIdentifiers());'.setInterval, the time is frozen at page load. Don't put it on a wall-mounted dashboard and expect it to tick; if liveness matters, add a setInterval(() => this.now = new Date(), 1000) in the component and rebuild assets.php artisan vendor:publish blindly hoping for options; list the package's publish groups first (php artisan vendor:publish interactive menu) or read the service provider's publishes() calls.withMeta(). Beyond that, subclass and override the component or jsonSerialize():class TeamClock extends WorldClock
{
public function component()
{
return 'team-clock'; // your own rebuilt component
}
}
composer.json, and if you rely on it for anything visible to stakeholders, plan to fork.How can I help you explore Laravel packages today?