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

Nova Google Maps Laravel Package

whitecube/nova-google-maps

Add an interactive Google Maps picker to Laravel Nova. This field lets users search addresses with autocomplete, drag a marker to fine-tune coordinates, and save latitude/longitude or formatted address data directly in your Nova resources. Configurable map options make it easy to fit.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Check compatibility first. This field targets the Nova 2/3 era (Laravel 6/7). Before installing, confirm your Nova major version and run composer why-not whitecube/nova-google-maps if resolution fails. On Nova 4/5 you will almost certainly need a fork.
  2. Install and publish assets/config:
    composer require whitecube/nova-google-maps
    php artisan vendor:publish --tag=nova-google-maps   # if the tag exists in your version
    
  3. Configure API keys. You need a Google Maps JavaScript API key (and, if the search uses Geocoding, that API enabled too). Set them in the published config or .env and cache config.
  4. Add the field to a resource:
    use Whitecube\NovaGoogleMaps\GoogleMaps;
    
    public function fields(Request $request)
    {
        return [
            GoogleMaps::make('Location'),
        ];
    }
    
  5. Prepare storage. The field stores a structured value (lat/lng plus a label/address), so use a JSON column:
    $table->json('location')->nullable();
    
    and cast it on the model:
    protected $casts = ['location' => 'array'];
    
  6. First use case: let an admin drop a pin (or search a place) for a business/branch/site, store the coordinates, and reuse them for a map embed, distance math, or a "nearby" query.

Implementation Patterns

Resource + cast + migration is the whole contract. Treat the field as a JSON-backed composite value. Everything else (rendering, distance queries, display) is derived from the stored array.

Normalising accessors. Don't reach into the raw JSON in views. Add helpers:

public function getLatAttribute() { return $this->location['lat'] ?? null; }
public function getLngAttribute() { return $this->location['lng'] ?? null; }
public function getLocationLabelAttribute() { return $this->location['address'] ?? $this->location['name'] ?? null; }

Search-to-pin workflow. The intended UX is: type an address → Algolia Places returns candidates → selecting one drops the marker and fills the payload. When search is unavailable (see Gotchas), the manual-drag fallback still yields usable coordinates — design around that.

Pair it with a plain text address field. The field is a location picker, not an address parser. If you need a canonical postal address, keep a separate address string column and treat the map payload as the geo anchor.

Distance / proximity queries. Because lat/lng sit in JSON, either add generated or duplicated lat/lng columns for indexing, or use a haversine expression:

$places = Place::selectRaw('*, ( 6371 * acos( cos( radians(?) ) * cos( radians( lat ) )
    * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance',
    [$lat, $lng, $lat])->having('distance', '<', 25)->get();

For anything beyond toy volumes, extract real columns.

Validation rule. Nova will happily save an empty pin. Add a custom rule that asserts both lat and lng exist and are within range (-90..90, -180..180).

Consuming on the frontend. Pass the coordinates to a Blade view and render a static map or an embedded map using an HTTP-referrer-restricted key (different from the admin key).

Multi-point / reordering. For "many locations" (e.g. a repeater), lean on Nova's built-in repeatable patterns or a sibling package; this field represents a single point.

Gotchas and Tips

  • Algolia Places is dead. Algolia shut down the Places API in 2022. The search box advertised in the description will not work. Your options: (a) replace the autocomplete in the Vue component with Google Places Autocomplete, (b) swap to Photon/Nominatim, or (c) accept manual pin placement. Budget for this — it is the single biggest risk.
  • Unmaintained since May 2020. Low star count, no recent commits. Pin the exact version, audit the compiled Vue asset, and be ready to fork. Do not assume Nova 4/5 support.
  • API key restrictions bite. Google keys restricted by HTTP referrer must include your Nova admin host. If the map loads blank and the console shows RefererNotAllowedMapError, it's the restriction, not the package.
  • Two keys, two surfaces. Use a locked-down admin key for the Nova field and a separate referrer-restricted key for public pages. Never ship an unrestricted server-side key.
  • Empty vs {} vs null. Saved-then-cleared pins may arrive as {"lat":null,"lng":null}. Guard every accessor with ?? null and is_numeric checks before doing math.
  • JSON columns are painful to query and index. If you filter or sort by proximity, migrate to dedicated decimal(10,7) columns; keep the JSON only if the payload also carries a label.
  • Modifying the component. The Vue file is shipped compiled. To customise the UI you must publish assets, run the package's build (npm run dev/prod inside the package directory or copy the component into your app), and rebuild — otherwise your edits silently wash out on composer update.
  • Debugging checklist: browser console for Maps/Places errors → network tab to see whether the Places request is even firing (a 404/deprecation response confirms the Algolia shutdown) → config:cache after changing keys → verify the model cast is actually array and not string.
  • Extension points: the field's ->zoom(), default-coordinates, and hide-search style helpers (where present) are thin wrappers around component props — inspect the published Vue source to see exactly which props the field passes before assuming a method exists.
  • Migration path: if you need long-term support, plan to replace this with a maintained Nova map field (e.g. Nova Map Field or a custom field wrapping Google Places Autocomplete). Keep the JSON payload shape stable so stored data survives the swap.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core