npm package: @gearbox-built/sanity-autocomplete-address
Description: Sanity Input Component that connects to Google Places API
Author: Gearbox Built
Latest version: 1.0.1

# @gearbox-built/sanity-autocomplete-address

> A Sanity Studio v3 plugin that provides a Google Places autocomplete address input component

## What Does This Plugin Do?

This plugin adds an intelligent address input field to your Sanity Studio that helps users enter addresses quickly and accurately. As users type, it shows address suggestions powered by Google Places API, and when they select an address, it automatically captures:

- The full formatted address
- Street address
- Geographic coordinates (latitude/longitude)
- Google Place ID
- Detailed address components (city, state, country, etc.)

Perfect for real estate listings, store locators, event locations, or any content that needs accurate address data.

## Requirements

- **Sanity Studio v3** (v3.65 or higher)
- **React 18 or 19**
- **Google Maps API Key** with Places API enabled ⚠️ _Note: Google no longer allows new customers to use the Places Autocomplete widget - existing customers only_

## Getting Your Google Maps API Key

> **⚠️ Important Note**: This plugin uses the `react-google-autocomplete` library, which relies on the Google Places Autocomplete widget. As of recent updates, **Google no longer allows new customers to use the Autocomplete widget** - it's only available to existing customers who had it enabled before the change. New users should consider alternative solutions or use the newer Places API (New) with a different implementation.
>
> If you're an existing customer with access, you can continue using this plugin.

Before installing this plugin, you'll need a Google Maps API key:

1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project (or select an existing one)
3. Enable the **Places API** for your project
4. Create credentials (API key)
5. **REQUIRED: Restrict your API key** to prevent unauthorized use:
   - In Google Cloud Console, go to your API key settings
   - Under "Application restrictions", select "HTTP referrers (websites)"
   - Add your Sanity Studio domain(s): `https://your-studio.sanity.studio/*` and `http://localhost:3333/*` (for local development)
   - Under "API restrictions", select "Restrict key" and choose "Places API"

**Critical Security Note**: Since Sanity Studio environment variables are exposed in the browser, **you MUST restrict your API key to specific domains**. Without restrictions, anyone can view your site's source code, copy your API key, and use it for their own purposes, potentially running up charges on your Google Cloud account.

## Installation

```bash
npm install @gearbox-built/sanity-autocomplete-address
```

or

```bash
yarn add @gearbox-built/sanity-autocomplete-address
```

## Setup

### Step 1: Configure the Plugin

Add the plugin to your `sanity.config.ts` (or `.js`) file:

```typescript
import {defineConfig} from 'sanity'
import PluginConfig from '@gearbox-built/sanity-autocomplete-address'

export default defineConfig({
  // ... your other config options
  plugins: [
    PluginConfig({
      apiKey: process.env.SANITY_STUDIO_GOOGLE_MAPS_API_KEY || '',
      options: {
        // Optional: Restrict results to specific countries
        // componentRestrictions: {country: 'us'},
        // Optional: Restrict to specific types of places
        // types: ['address'],
      },
    }),
  ],
})
```

### Step 2: Add Environment Variable

Create or update your `.env` file in your Sanity Studio root:

```env
SANITY_STUDIO_GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here
```

**Important Security Notes**:

- Sanity Studio environment variables must be prefixed with `SANITY_STUDIO_` to be accessible in the browser
- ⚠️ **Environment variables prefixed with `SANITY_STUDIO_` are exposed to the browser** - they are NOT secret
- **You MUST restrict your API key** in Google Cloud Console to only allow requests from your specific domain(s)
- Without domain restrictions, anyone who views your site's source code could use your API key

### Step 3: Use in Your Schema

Add the `address` field to any of your document schemas:

```typescript
import {defineType, defineField} from 'sanity'

export default defineType({
  name: 'venue',
  title: 'Venue',
  type: 'document',
  fields: [
    defineField({
      name: 'name',
      title: 'Venue Name',
      type: 'string',
    }),
    defineField({
      name: 'location',
      title: 'Address',
      type: 'address', // This is the field type provided by the plugin
      description: 'Start typing to search for an address',
    }),
  ],
})
```

## Configuration Options

### Plugin Options

| Option    | Type   | Required | Description                                    |
| --------- | ------ | -------- | ---------------------------------------------- |
| `apiKey`  | string | Yes      | Your Google Maps API key                       |
| `options` | object | No       | Additional configuration for Google Places API |

### Google Places Options

You can pass any [Google Places Autocomplete options](https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions) in the `options` object:

```typescript
PluginConfig({
  apiKey: process.env.SANITY_STUDIO_GOOGLE_MAPS_API_KEY || '',
  options: {
    // Restrict to specific countries (ISO 3166-1 Alpha-2 country codes)
    componentRestrictions: {
      country: ['us', 'ca'], // USA and Canada only
    },

    // Restrict to specific place types
    types: ['address'], // Only street addresses

    // Bias results to a specific location
    bounds: {
      north: 45.5,
      south: 45.3,
      east: -122.5,
      west: -122.8,
    },
  },
})
```

## What Data Gets Stored?

When a user selects an address, the plugin stores the following data structure:

```typescript
{
  label: "520 Normandy Road, Victoria, BC, Canada",
  street: "520 Normandy Road",
  placeId: "ChIJ123456789",
  cords: {
    lat: 48.4284,
    lng: -123.3656
  },
  data: [
    {
      long_name: "520",
      short_name: "520",
      types: ["street_number"]
    },
    {
      long_name: "Normandy Road",
      short_name: "Normandy Rd",
      types: ["route"]
    },
    // ... more address components
  ]
}
```

### Field Descriptions

- **`label`**: The full formatted address as displayed to the user
- **`street`**: The street address (street number + route)
- **`placeId`**: Google's unique identifier for this place
- **`cords`**: Geographic coordinates (latitude and longitude)
- **`data`**: Raw address components from Google Places API

## Troubleshooting

### "Google Maps API Key Undefined" Error

This error appears when the plugin can't find your API key. Check that:

1. Your `.env` file contains `SANITY_STUDIO_GOOGLE_MAPS_API_KEY=your_key`
2. The variable name starts with `SANITY_STUDIO_`
3. You've restarted your Sanity Studio development server after adding the `.env` file
4. The API key is being passed to the plugin configuration

### No Autocomplete Suggestions Appearing

If suggestions don't appear as you type:

1. **Check API Key**: Verify your Google Maps API key is valid
2. **Enable Places API**: Make sure the Places API is enabled in your Google Cloud Console
3. **Check Billing**: Google requires billing to be enabled (they offer free credits)
4. **Check Restrictions**: If you've restricted your API key, ensure it allows requests from your domain
5. **Check Console**: Open browser DevTools and look for error messages

### "No Lat/Lng Found" Error

This happens when you don't select an address from the dropdown. The plugin requires you to:

1. Type your address
2. Wait for suggestions to appear
3. Click on one of the suggested addresses

Don't just type an address and press Enter—you must select from the dropdown.

### Component Not Rendering

If the address field doesn't appear in your Studio:

1. Verify the plugin is added to your `sanity.config.ts` plugins array
2. Check that you're using `type: 'address'` in your schema
3. Restart your development server
4. Check for console errors in your browser's DevTools

### TypeScript Errors

If you see TypeScript errors related to the plugin:

```bash
npm install --save-dev @types/react@^19 @types/react-dom@^19
```

## React 18 and React 19 Support

This plugin supports both React 18 and React 19. The plugin uses:

- ESM (ECMAScript Modules) architecture
- Proper peer dependencies for both React versions
- TypeScript with modern type definitions

No special configuration needed—it will work with whichever React version your Sanity Studio uses.

## Example Use Cases

### Real Estate Listings

```typescript
defineField({
  name: 'propertyAddress',
  title: 'Property Address',
  type: 'address',
  validation: (Rule) => Rule.required(),
})
```

## Development

### Testing Locally

This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit) for development:

```bash
# Install dependencies
yarn install

# Run tests
yarn test

# Run tests in watch mode
yarn test:watch

# Build the plugin
yarn build

# Link and watch for changes
yarn link-watch
```

Then in your Sanity Studio project:

```bash
yalc add --link @gearbox-built/sanity-autocomplete-address && yarn install
```

See [TESTING.md](./TESTING.md) for comprehensive testing documentation.

## API Reference

### Address Field Type

When you use `type: 'address'` in your schema, it creates a field that stores:

```typescript
interface AddressValue {
  label?: string // Full formatted address
  street?: string // Street address
  placeId?: string // Google Place ID
  cords?: {
    // Coordinates
    lat: number
    lng: number
  }
  data?: AddressComponent[] // Raw address components
}

interface AddressComponent {
  long_name: string // Full name (e.g., "California")
  short_name: string // Abbreviated (e.g., "CA")
  types: string[] // Types (e.g., ["administrative_area_level_1"])
}
```

## Support

- **Issues**: [GitHub Issues](https://github.com/gearbox-built/housing/issues)
- **Documentation**: [Sanity.io Documentation](https://www.sanity.io/docs)

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

[MIT](LICENSE) © Gearbox Built

## Credits

Built with:

- [react-google-autocomplete](https://www.npmjs.com/package/react-google-autocomplete) - Google Places autocomplete for React
- [@sanity/ui](https://www.sanity.io/ui) - Sanity's UI components
- [Google Places API](https://developers.google.com/maps/documentation/places/web-service/overview) - Location data and autocomplete

---

**Need Help?** Check out the [TESTING.md](./TESTING.md) file for detailed testing instructions and troubleshooting steps.