DEV Community

Cover image for Map Location Picker Plugin
Michael
Michael

Posted on

Map Location Picker Plugin

Map Location Picker Plugin for Storyblok

This is a submission for the Storyblok Challenge

Demo

Code Repository:

GitHub – storyblok-get-location-plugin

Demo Video or Screenshots

Watch the demo on YouTube

What I Built

I created a Storyblok Field Plugin that makes adding real-world locations as easy as typing an address. Powered by the Google Maps Geocoding API, editors can search for a place, see it instantly pinned on a map, and automatically store clean location data — latitude, longitude, and formatted address — into their Storyblok content.

No complex setup. No copying coordinates from Google. Just search, pin, and go.

It’s a lightweight plugin for a heavyweight need. Whether it’s contact pages, store locators, event listings, or any content that benefits from geographic context, this solves a common problem with minimal friction.

The goal wasn’t to reinvent maps. It was to take something almost every site needs and make it feel like a native part of the Storyblok editing experience. I wanted location data to be just another field — not a separate workflow.

It’s simple by design — and that’s the point.

Getting Started

1. Clone the repository

git clone https://github.com/your-username/storyblok-map-location-plugin.git
cd storyblok-map-location-plugin
Enter fullscreen mode Exit fullscreen mode

2. Deploy the plugin to Storyblok

npm run deploy --workspace=get-location
Enter fullscreen mode Exit fullscreen mode

3. Follow the Prompts

It will ask for your Storyblok Personal Access Token.
You can create one at:

  • Storyblok → My Account → Personal Access Tokens
  • Make sure the token has permission to manage your space and plugins.

4. Add the plugin to a Block

  1. Go to your Storyblok Space
  2. Open or create a component
  3. Add a new field:
    • Type: custom
    • Plugin: Select your deployed plugin (e.g., get-location)
  4. Save the schema

  5. You can use the following code to implement the visual UI of the data:

.address-map-iframe {
  width: 100%;
  height: 280px;
  border: none;
  display: block;
  border-bottom: 1px solid #e5e7eb;
}

.map-wrapper {
  border-radius: 8px;
  overflow: hidden;
}

.address-map-text {
  padding: 1rem 0.5rem;
  font-size: 0.95rem;
  color: #374151;
  font-family: system-ui, sans-serif;
  margin: 0;
}

.address-map-fallback {
  font-size: 0.875rem;
  color: #9ca3af;
  font-style: italic;
  margin: 1rem 0;
}
Enter fullscreen mode Exit fullscreen mode
export default function AddressMap({ blok }) {
  if (!blok?.address_view?.embedUrl || !blok?.address_view?.formatted_address) {
    return <p className="address-map-fallback">Address not found</p>;
  }

  return (
    <div className="map-wrapper">
      <iframe
        className="address-map-iframe"
        loading="lazy"
        src={blok.address_view.embedUrl}
        title="Google Maps Location"
        referrerPolicy="no-referrer-when-downgrade"
        allowFullScreen
      ></iframe>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Tech Stack

  • Frontend Plugin: React + Vite
  • Framework/Platform: Storyblok Field Plugin SDK (iframe-based integration)
  • Design System: Custom CSS mimicking Blok.ink (Storyblok Design System)
  • Input & Button Components: Styled to match SbTextField and SbButton
  • Cloud Function: Firebase Functions for address-to-coordinate resolution
  • Maps API: Google Maps Geocoding API (called via Firebase Function)
  • UX Behavior: Debounced search, cooldown logic, and loading indicator
  • Preview Feature: Google Maps iframe showing selected location
  • State Management: React useState for managing form and result states

How I Used Storyblok

  • Registered the plugin as a custom field type using the Field Plugin UI
  • Used useFieldPlugin() to sync data between the Visual Editor and plugin iframe
  • Saved structured data such as:
{
  lat: number
  lng: number
  formatted_address: string
  embedUrl: string
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)