Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/davidmpizarro/QuipuEco-Hackaton/llms.txt

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

QuipuEco’s map screen is the core navigational feature of the app — it shows all nearby Tambo store drop-off points and Lima Este municipal Centros Verdes on an immersive dark-mode map, uses the device’s GPS to geolocate the user, and draws a live walking route from the user’s position to any selected recycling point. All of this is powered by Mapbox GL JS, a WebGL-based mapping library. You need a Mapbox access token before the map will render.

What Mapbox provides to QuipuEco

Dark-mode map tiles

Raster tiles from CARTO’s dark_all style are used instead of the default Mapbox Streets tileset, matching QuipuEco’s dark green UI theme.

GPS geolocation

GeolocateControl tracks the user’s real-time position on the map and is triggered automatically on load, so the map centers on the user immediately.

Custom markers and popups

Each recycling point renders as a mapboxgl.Marker with a custom DOM element. Tapping a marker opens a mapboxgl.Popup with the point’s address and district.

Directions API

Walking routes between the user’s GPS position and a selected recycling point are fetched from the Mapbox Directions API and drawn as a GeoJSON line layer.

Obtaining a Mapbox token

1

Sign up for a Mapbox account

Go to mapbox.com and create a free account. No credit card is required for the free tier, which provides generous monthly map load and API call allowances — more than enough for local development and demos.
2

Navigate to Access Tokens

After signing in, click your profile avatar in the top-right corner and select Account. From the account dashboard, select Access Tokens in the left sidebar.
3

Create a new token

Click Create a token. Give it a descriptive name (e.g. QuipuEco Dev). For local development, the default public scopes are sufficient — the Directions API and map tile endpoints are covered by the default scope set.For production deployments, restrict the token to your deployed domain using the Allowed URLs field to prevent unauthorized usage.
4

Copy the token

Your new token will appear in the list. It always begins with pk. (public key prefix). Copy it to your clipboard.
5

Add the token to your .env file

In quipueco-frontend/ (the repository root), add the token to your .env file:
VITE_MAPBOX_TOKEN=pk.eyJ1IjoieW91ci11c2VybmFtZSIsImEiOiJBQkNEMTIzNC4uLiJ9...
Restart the Vite dev server (npm run dev) after saving the file so the new variable is picked up.

How the token is used in code

The token is assigned once at the module level in src/components/VistaMapaPuntos.jsx, before any map instance is created:
src/components/VistaMapaPuntos.jsx
import mapboxgl from "mapbox-gl";
import "mapbox-gl/dist/mapbox-gl.css";

mapboxgl.accessToken = import.meta.env.VITE_MAPBOX_TOKEN;
Setting mapboxgl.accessToken globally means all subsequent mapboxgl.Map, mapboxgl.Marker, and Directions API calls made from this file automatically include the token. You do not need to pass it explicitly to individual API calls.

Mapbox features used by QuipuEco

Map initialization with CARTO dark tiles

The map is initialized with a custom raster tile source instead of a Mapbox-hosted style, using CARTO’s publicly available dark_all tile layer:
src/components/VistaMapaPuntos.jsx
const map = new mapboxgl.Map({
  container: mapContainerRef.current,
  style: {
    version: 8,
    sources: {
      "carto-dark": {
        type: "raster",
        tiles: [
          "https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}@2x.png",
        ],
        tileSize: 256,
      },
    },
    layers: [
      { id: "carto-dark-layer", type: "raster", source: "carto-dark" },
    ],
  },
  center: [-77.03, -12.1],
  zoom: 12,
});
The map intentionally uses CARTO’s dark_all raster tiles rather than the default Mapbox Streets or Satellite styles. This provides a dark, low-distraction background that makes QuipuEco’s green markers and route polylines visually pop against the map canvas — consistent with the app’s dark-green design system.

Geolocation and navigation controls

Two built-in controls are added to the map on load:
src/components/VistaMapaPuntos.jsx
// Tracks the user's GPS position in real time
const geolocate = new mapboxgl.GeolocateControl({
  positionOptions: { enableHighAccuracy: true },
  trackUserLocation: true,
  showUserHeading: true,
  showAccuracyCircle: false,
});
map.addControl(geolocate, "top-right");

// Fires automatically so the map centers on the user at startup
map.on("load", () => {
  geolocate.trigger();
});

// Zoom in/out and compass bearing reset
map.addControl(new mapboxgl.NavigationControl(), "top-right");

Custom markers and popups

Each recycling point is rendered with a custom-styled DOM element as its marker pin, with an HTML popup containing the point’s name, address, and district:
src/components/VistaMapaPuntos.jsx
const el = document.createElement("div");
// el is styled via JavaScript (dimensions, background color, border-radius)

const popup = new mapboxgl.Popup({ offset: 25 }).setHTML(`
  <strong>${punto.nombre}</strong><br/>
  ${punto.direccion}<br/>
  <em>${punto.distrito}</em>
`);

new mapboxgl.Marker({ element: el })
  .setLngLat([punto.lng, punto.lat])
  .setPopup(popup)
  .addTo(map);

Directions API and route drawing

When a user taps “Trazar ruta” on a recycling point card, VistaMapaPuntos calls the Mapbox Directions API with the walking profile and renders the response as a GeoJSON line layer:
src/components/VistaMapaPuntos.jsx
const trazarRuta = async (punto) => {
  const url = `https://api.mapbox.com/directions/v5/mapbox/walking/` +
    `${userPos.lng},${userPos.lat};${punto.lng},${punto.lat}` +
    `?geometries=geojson&access_token=${mapboxgl.accessToken}`;

  const res = await fetch(url);
  const data = await res.json();
  const route = data.routes[0];
  const geojson = route.geometry;

  // Remove any previous route layer before drawing the new one
  if (map.getLayer("route")) map.removeLayer("route");
  if (map.getSource("route")) map.removeSource("route");

  map.addSource("route", {
    type: "geojson",
    data: { type: "Feature", geometry: geojson },
  });

  map.addLayer({
    id: "route",
    type: "line",
    source: "route",
    layout: { "line-join": "round", "line-cap": "round" },
    paint: { "line-color": color, "line-width": 4, "line-opacity": 0.9 },
  });

  // Auto-fit the viewport to show the full route
  const bounds = new mapboxgl.LngLatBounds();
  geojson.coordinates.forEach((c) => bounds.extend(c));
  map.fitBounds(bounds, { padding: 80 });

  // Derive walking and driving time estimates from the response
  const minsCaminar = Math.round(route.duration / 60);
  const km = (route.distance / 1000).toFixed(1);
  const minsCarro = Math.max(1, Math.round(minsCaminar / 5));
};
The line-color is set dynamically based on the recycling category (e.g. green for plastic, blue for paper), so each route is visually associated with the material type currently being viewed.

Free tier limits

Mapbox’s free tier provides:
  • 50,000 map loads per month — each time mapboxgl.Map is instantiated counts as one load
  • 100,000 Directions API requests per month — each call to the /directions/v5/ endpoint counts as one request
These limits are more than sufficient for local development, hackathon demos, and moderate-traffic production usage. For high-volume production deployments, refer to Mapbox pricing for pay-as-you-go rates.
During local development, you can monitor your token’s usage in the Mapbox dashboard under Account → Statistics. If you approach the free tier limit during a demo, creating a secondary token for production use keeps development and production metrics separate.

Build docs developers (and LLMs) love