Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/jacobsamo/buzztrip/llms.txt

Use this file to discover all available pages before exploring further.

The places table is the canonical store for enriched location data in BuzzTrip. Every marker on a map links to a place record, which holds the coordinates, address, provider IDs, photos, ratings, and POI type information sourced from Google Maps, Mapbox, or Foursquare. Places are shared across maps — if two markers point to the same physical location, they reference the same place document.

How Places Work

When a marker is created, BuzzTrip checks whether a place already exists at the target coordinates using the by_place_lat_lng compound index. If a matching place is found, the new marker links to it directly. If no match exists, a new place record is created first. On creation, two things happen automatically:
  1. Plus code generation — An Open Location Code is computed from the lat/lng values using the open-location-code-typescript library and stored in plus_code.
  2. Geospatial indexing — The place is inserted into BuzzTrip’s geospatial Convex component with its coordinates and metadata (placeTypes, plusCode, what3words), enabling efficient radius and bounding-box queries.
Plus codes are generated automatically — you do not need to provide them when creating a place. If the library fails to encode the coordinates (e.g., for out-of-range values), plus_code will be undefined and the error is logged but does not prevent the place from being created.

Place Schema

title
string
required
Human-readable name for the place (e.g. “Eiffel Tower”, “Blue Bottle Coffee”).
lat
number
required
Latitude in decimal degrees.
lng
number
required
Longitude in decimal degrees.
bounds
BoundsSchema
required
Bounding box for the place. Can be either a full { east, north, south, west } object or a simple { lat, lng } point.
icon
IconType | string
required
An icon identifier derived from the primary POI type. Used to render the marker pin on the map.
rating
number
required
Aggregate rating (e.g. from Google Maps or Foursquare). Defaults to 0 if no rating is available.
description
string
Optional freeform description of the place.
address
string
Formatted street address.
gm_place_id
string
Google Maps place ID (e.g. ChIJ...). Used to cross-reference data with the Google Maps Places API.
mb_place_id
string
Mapbox place ID. Used to cross-reference data with the Mapbox Geocoding API.
fq_place_id
string
Foursquare place ID. Used to cross-reference data with the Foursquare Places API.
plus_code
string
Open Location Code (Plus Code) auto-generated from lat/lng. Example: 8FW4V75V+8Q. You do not need to supply this field.
what3words
string
what3words address for the location (e.g. filled.count.soap). Stored when available; not auto-generated.
photos
string[] | null | undefined
Array of photo URL strings, or null/undefined if none are available. Initially populated from the provider (Google Maps, Foursquare). Additional user-submitted photos are stored separately in the place_photos table.
types
string[]
Array of POI type tags (e.g. ['restaurant', 'food', 'point_of_interest']). Sourced from the map provider and used to derive the icon field.
website
string
Official website URL for the place.
phone
string
Phone number for the place.

Place Deduplication

Places are deduplicated using the by_place_lat_lng compound index on (lat, lng). Before inserting a new place, BuzzTrip queries this index to check for an exact coordinate match. If one is found, the existing place ID is used for the new marker. This means a single place record can accumulate provider IDs over time — for example, a place first added via Google Maps might later have its mb_place_id or fq_place_id filled in when the same location is looked up via Mapbox or Foursquare.

Multiple Provider IDs

A single place document can hold IDs from all three supported map providers simultaneously:
FieldProvider
gm_place_idGoogle Maps Places API
mb_place_idMapbox Geocoding API
fq_place_idFoursquare Places API
This cross-provider design means place data can be enriched from multiple sources without creating duplicate records.

createPlace (Internal Helper)

createPlace is an internal async helper function (not a public Convex mutation) called during marker creation. It handles the full place insertion flow:
  1. Generates a plus code from lat/lng using OpenLocationCode.encode()
  2. Inserts the place document into the places table via ctx.db.insert()
  3. Registers the place in the geospatial index via geospatial.insert() with:
    • Coordinates: { latitude, longitude }
    • Metadata: { placeTypes, plusCode, what3words }
// convex/places.ts (internal helper — not a public mutation)
import OpenLocationCode from "open-location-code-typescript";
import { geospatial } from "./helpers";

export const createPlace = async (ctx: MutationCtx, place: NewPlace) => {
  let plusCode: string | undefined = undefined;
  try {
    plusCode = OpenLocationCode.encode(place.lat, place.lng);
  } catch (error) {
    console.error(`Failed to generate plus code: ${error}`);
  }

  const newPlaceId = await ctx.db.insert("places", {
    title: place.title,
    lat: place.lat,
    lng: place.lng,
    bounds: place.bounds,
    icon: place.icon,
    rating: place.rating,
    plus_code: plusCode,
    // ...other fields
  });

  await geospatial.insert(
    ctx,
    newPlaceId,
    { latitude: place.lat, longitude: place.lng },
    {
      placeTypes: place.types ?? null,
      plusCode: plusCode ?? null,
      what3words: null,
    }
  );

  return newPlaceId;
};

Reviews and Photos

User-submitted content is stored in two separate tables linked to places by place_id:

places_reviews

Stores user reviews for a place. Each review includes author_name, author_url, profile_photo_url, rating, and a description. Linked to both places (via place_id) and users (via user_id).

place_photos

Stores user-submitted photos for a place. Each photo record includes photo_url, width, height, and a caption. Linked to both places (via place_id) and users (via user_id).

places_reviews Schema

place_id
Id<'places'>
required
Reference to the parent place document.
user_id
Id<'users'>
required
Reference to the user who submitted the review.
author_name
string
required
Display name of the reviewer.
author_url
string | null
required
Link to the author’s profile (may be null).
profile_photo_url
string
required
URL of the reviewer’s avatar.
rating
number | null
required
Numeric rating, or null if not provided.
description
string
required
Review body text.

place_photos Schema

place_id
Id<'places'>
required
Reference to the parent place document.
user_id
Id<'users'>
required
Reference to the user who submitted the photo.
photo_url
string
required
URL of the uploaded photo.
width
number
required
Image width in pixels.
height
number
required
Image height in pixels.
caption
string
required
Text caption for the photo.

Build docs developers (and LLMs) love