Skip to main content

MapFirstCore API

The MapFirstCore class is the foundation of the MapFirst SDK. It manages map connections, property search, marker rendering, and state — all from a single instance. Use it directly in vanilla JavaScript projects, or let the useMapFirst hook wrap it for you in React.

React users

If you're using React, you rarely need to interact with MapFirstCore directly. The useMapFirst hook creates and manages the instance for you. This page is most useful for vanilla JavaScript projects or advanced React patterns where you need direct access.


Import

// ES Modules
import { MapFirstCore } from "@mapfirst.ai/core";

// Browser (CDN)
const { MapFirstCore } = window.MapFirstCore;

Constructor

new MapFirstCore(config);

Parameters

interface MapFirstConfig {
// Map adapter (null when using platform-specific initialization)
adapter: any | null;

// API Configuration
apiKey?: string; // Your MapFirst API key
useApi?: boolean; // Use MapFirst API (default: true)
environment?: "dev" | "prod"; // API environment (default: "prod")
apiUrl?: string; // Custom API URL (optional)

// Initial location data
initialLocationData?: {
city?: string;
country?: string;
currency?: string;
};

// Initial request body (alternative to initialLocationData)
requestBody?: any;

// Initial state
state?: Partial<MapState>;

// Property configuration
properties?: Property[]; // Pre-loaded properties
primaryType?: PropertyType; // Initial property type filter
selectedMarkerId?: number | null; // Initially selected marker

// Map behavior
autoSelectOnClick?: boolean; // Auto-select marker on click
fitBoundsPadding?: {
// Padding for fitBounds
top?: number;
bottom?: number;
left?: number;
right?: number;
};

// Callbacks
callbacks?: {
onPropertiesChange?: (properties: Property[]) => void;
onSelectedPropertyChange?: (id: number | null) => void;
onPrimaryTypeChange?: (type: PropertyType) => void;
onFiltersChange?: (filters: FilterState) => void;
onBoundsChange?: (bounds: MapBounds | null) => void;
onPendingBoundsChange?: (bounds: MapBounds | null) => void;
onCenterChange?: (center: [number, number], zoom: number) => void;
onZoomChange?: (zoom: number) => void;
onActiveLocationChange?: (location: ActiveLocation) => void;
onLoadingStateChange?: (loading: boolean) => void;
onSearchingStateChange?: (searching: boolean) => void;
onFirstCallDoneChange?: (firstCallDone: boolean) => void;
onIsFlyToAnimatingChange?: (animating: boolean) => void;
};
}

Example

Here's a minimal setup that initializes the SDK, listens for property changes, and tracks search state:

const mapFirst = new MapFirstCore({
apiKey: "your-api-key",
initialLocationData: {
city: "Paris",
country: "France",
currency: "EUR",
},
state: {
filters: {
checkIn: "2024-06-01",
checkOut: "2024-06-07",
numAdults: 2,
numRooms: 1,
currency: "EUR",
},
},
callbacks: {
onPropertiesChange: (properties) => {
console.log("Properties updated:", properties);
},
onSearchingStateChange: (searching) => {
console.log("Searching:", searching);
},
},
});

Methods

attachMap

Attach a map instance to MapFirst. This is how the SDK knows which map to render markers on. Call this after the map has fully loaded.

attachMap(map: any, options: AttachMapOptions): void

Parameters:

interface AttachMapOptions {
platform: "maplibre" | "mapbox" | "google";
maplibregl?: typeof maplibregl; // Required for MapLibre
mapboxgl?: typeof mapboxgl; // Required for Mapbox
google?: typeof google; // Required for Google Maps
onMarkerClick?: (property: Property) => void;
}

Example:

// MapLibre
mapFirst.attachMap(map, {
platform: "maplibre",
maplibregl: maplibregl,
onMarkerClick: (property) => {
alert(property.name);
},
});

// Google Maps
mapFirst.attachMap(map, {
platform: "google",
google: window.google,
});

runPropertiesSearch

Search for properties by location. This is the primary search method — specify a city, country, and optional filters to find accommodations, restaurants, or attractions.

runPropertiesSearch(params: SearchParams): Promise<void>

Example:

await mapFirst.runPropertiesSearch({
body: {
city: "London",
country: "United Kingdom",
filters: {
checkIn: "2024-07-01",
checkOut: "2024-07-05",
numAdults: 2,
currency: "GBP",
},
},
});

runSmartFilterSearch

AI-powered natural language search. Pass a plain-text query and the SDK will use AI to extract structured filters and return matching properties.

runSmartFilterSearch(params: SmartSearchParams): Promise<void>

Example:

await mapFirst.runSmartFilterSearch({
query: "romantic restaurants with outdoor seating",
});

performBoundsSearch

Search within the current visible map area. Perfect for implementing a "Search this area" button.

performBoundsSearch(): Promise<void>

Example:

await mapFirst.performBoundsSearch();

setPrimaryType

Set the active property type filter. This controls which category of markers is displayed on the map.

setPrimaryType(type: 'Accommodation' | 'Eat & Drink' | 'Attraction'): void

Example:

mapFirst.setPrimaryType("Eat & Drink");

setSelectedMarker

Select or deselect a property marker on the map. Selected markers are visually highlighted.

setSelectedMarker(id: number | null): void

Example:

// Select
mapFirst.setSelectedMarker(12345);

// Deselect
mapFirst.setSelectedMarker(null);

flyMapTo

Smoothly animate the map camera to a specific location and zoom level.

flyMapTo(lng: number, lat: number, zoom?: number): void

Example:

// Fly to Eiffel Tower
mapFirst.flyMapTo(2.2945, 48.8584, 15);

getState

Get a snapshot of the current SDK state. Useful for reading properties, search status, or filter values at any point in time.

getState(): MapFirstState

Example:

const state = mapFirst.getState();
console.log("Current properties:", state.properties);
console.log("Is searching:", state.isSearching);

destroy

Clean up all resources — removes markers, detaches event listeners, and disconnects from the map. Always call this when you're done with the instance.

Memory leaks

Failing to call destroy() when removing a map (e.g., on page navigation) can lead to memory leaks, especially in single-page applications. In React, call it in your useEffect cleanup function.

destroy(): void

Example:

mapFirst.destroy();

Events / Callbacks

All callbacks are optional and passed in the callbacks object during initialization. They fire whenever the corresponding state changes.

onPropertiesChange

Called when properties are updated.

onPropertiesChange?: (properties: Property[]) => void

onSelectedPropertyChange

Called when selection changes.

onSelectedPropertyChange?: (id: number | null) => void

onBoundsChange

Called when map bounds change.

onBoundsChange?: (bounds: MapBounds | null) => void

onSearchingStateChange

Called when search state changes.

onSearchingStateChange?: (isSearching: boolean) => void

onFirstCallDoneChange

Called when the first search completes. Useful for showing/hiding loading states or triggering map animations after initial data loads.

onFirstCallDoneChange?: (firstCallDone: boolean) => void

onIsFlyToAnimatingChange

Called when a fly-to animation starts or finishes.

onIsFlyToAnimatingChange?: (animating: boolean) => void

onError

Called when an error occurs.

onError?: (error: Error) => void

Types

These TypeScript interfaces describe the data structures used throughout the SDK. All types are exported from @mapfirst.ai/core.

Property

Represents a property (accommodation, restaurant, or attraction) returned from search results. This is the main data object you'll work with.

interface Property {
tripadvisor_id: number; // Unique TripAdvisor ID
name: string; // Property name
rating: number; // TripAdvisor rating (0-5)
reviews: number; // Number of reviews
location?: {
// Geographic coordinates
lat: number;
lon: number;
};
type: PropertyType; // "Accommodation" | "Eat & Drink" | "Attraction"
awards?: PropertyAward[]; // TripAdvisor awards (e.g., Travelers' Choice)
pricing?: HotelPricingAPIResults; // Hotel pricing data when available
url?: string; // Property URL
secondaries: string[]; // Related property IDs
price_level?: PriceLevel; // "Mid Range" | "Fine Dining" | "Cheap Eats"
city?: string; // City name
country?: string; // Country name
}

Example:

const property = {
tripadvisor_id: 123456,
name: "Hotel Example",
rating: 4.5,
reviews: 1250,
location: { lat: 48.8566, lon: 2.3522 },
type: "Accommodation",
awards: [
{
name: "Travelers Choice Best of the Best",
image: { key: "logo", url: "https://..." },
type: "1",
},
],
price_level: "Mid Range",
city: "Paris",
country: "France",
};

PropertyType

type PropertyType = "Accommodation" | "Eat & Drink" | "Attraction";

PropertyAward

type PropertyAward = {
name: string; // Award name
image: PropertyAwardImage; // Award badge image
type: "0" | "1"; // Award category
};

type PropertyAwardImage = {
key: string; // Image type (e.g., "logo")
url: string; // Image URL
};

PriceLevel

Price level indicator shown as a string.

type PriceLevel = "Mid Range" | "Fine Dining" | "Cheap Eats";

MapBounds

Represents a rectangular geographic area defined by its southwest and northeast corners.

interface MapBounds {
sw: { lat: number; lng: number };
ne: { lat: number; lng: number };
}

Next Steps