Skip to main content
200 Mates follows a simple, modular file structure that separates concerns while keeping the codebase accessible and maintainable.

Project Overview

200mates/
├── index.html              # Main HTML structure
├── app.js                  # Application entry point
├── config/
│   └── constants.js        # Supabase config & app constants
├── data/
│   ├── capital-coords.js   # Capital city coordinates
│   ├── countries.js        # Country data & translations
│   ├── i18n.js            # Translations (ES/EN/PT)
│   └── iso-tables.js      # ISO country code mappings
├── modules/
│   ├── form.js            # Form handling & submission
│   ├── gallery.js         # Recent mates gallery
│   ├── globe.js           # Globe.gl visualization
│   ├── gps.js             # Geolocation functionality
│   ├── menu.js            # Hamburger menu & tabs
│   ├── modal.js           # Success modal & lightbox
│   ├── state.js           # Global state management
│   └── utils.js           # Utility functions
└── styles/
    └── style.css          # All application styles

Root Files

index.html

The main HTML file contains the complete page structure:
  • Header: Logo, language switcher, stats, hamburger menu
  • Main layout: Globe section + side panel
  • Side panel: Gallery and submission form
  • Overlays: Popup, lightbox, success modal, dropdown menu
All external dependencies are loaded via CDN:
  • Bootstrap 5.3.3 (CSS & JS)
  • Globe.gl 2.27.2
  • TopJSON Client 3
  • Supabase JS SDK 2

app.js

The application entry point (index.html:274) orchestrates initialization:
app.js
// Language switching logic
// Load mates from Supabase
// Fetch GeoJSON data for countries
// Initialize GPS, render globe, update gallery
// Poll for new mates every 30 seconds
Key functions:
  • loadMates(): Fetches mate submissions from Supabase
  • applyI18n(): Updates UI text based on selected language
  • initGPS(): Requests user location
  • setInterval(loadMates, 30_000): Auto-refresh data

config/ Directory

constants.js

Central configuration file:
config/constants.js
const SUPABASE_URL  = "https://qpwwexlxiksmaaehqsev.supabase.co";
const SUPABASE_ANON = "eyJhbGc...";
const sb = supabase.createClient(SUPABASE_URL, SUPABASE_ANON);

const DEFAULT_ALTITUDE = 2.5;  // Globe camera altitude
const ZOOM_THRESHOLD   = 1.8;  // When to show country labels
Supabase credentials are safe to commit because Row Level Security (RLS) is enabled on all tables.

data/ Directory

capital-coords.js

Coordinate data for capital cities, used as fallback when GPS coordinates aren’t available:
const capitalCoords = {
  "ARG": { lat: -34.6037, lng: -58.3816 },  // Buenos Aires
  "BRA": { lat: -15.8267, lng: -47.9218 },  // Brasília
  // ...
};

countries.js

Country names in Spanish, English, and Portuguese for the form dropdown:
const countriesES = [ /* Spanish names */ ];
const countriesEN = [ /* English names */ ];
const countriesPT = [ /* Portuguese names */ ];

i18n.js

All UI text translations for the three supported languages:
const translations = {
  es: { title: "200 Mates", submitBtn: "Compartir", /* ... */ },
  en: { title: "200 Mates", submitBtn: "Share", /* ... */ },
  pt: { title: "200 Mates", submitBtn: "Compartilhar", /* ... */ }
};

iso-tables.js

Mappings between ISO country codes (ISO 3166-1) formats:
  • numericToIso3: Numeric → Alpha-3 (e.g., “032” → “ARG”)
  • nameToIso3: Country name → Alpha-3

modules/ Directory

form.js

Handles the mate submission form:
  • Field validation
  • Photo upload and preview
  • Preparation type toggle (amargo, dulce, tereré, cocido)
  • Country autocomplete
  • Supabase submission with image upload to storage
Key functions:
  • Form validation and submission
  • File drag & drop handling
  • Success modal trigger
Displays recent mate submissions in the side panel:
  • Renders gallery cards
  • Handles lightbox opening
  • Shows skeleton loaders while data loads
Referenced in: app.js:48 (renderGallery())

globe.js

Manages the 3D globe visualization using Globe.gl:
  • Renders country polygons with colors
  • Displays markers for mate locations
  • Draws arcs from capitals to mate locations
  • Handles popup on marker hover
  • Camera controls and interactions
Key features:
  • Dark theme optimized for mate aesthetics
  • Automatic camera rotation
  • Interactive markers with tooltips

gps.js

Handles geolocation functionality:
  • Requests browser location permission
  • Updates GPS status indicator
  • Reverse geocodes coordinates to country
  • Populates hidden form fields (lat, lng, country_code)
Status messages:
  • “Solicitando GPS…” (Requesting)
  • “GPS detectado” (Success)
  • “GPS no disponible” (Failed/denied)
Controls the hamburger dropdown menu:
  • Tab switching (About, Support, Moderation, Press)
  • Footer navigation (FAQs, Terms, Privacy, Contact)
  • Backdrop click handling
  • Animation states
Manages overlay components:
  • Success modal after form submission (with animated mate emoji)
  • Lightbox for viewing full-size mate photos
  • ID display and copy-to-clipboard functionality

state.js

Global state variables:
modules/state.js
let currentLang = "es";
let allMates = [];
let countriesGeo = [];
let countriesColored = [];
let lastMarkerIds = "";

utils.js

Helper functions used across modules:
  • t(key): Translation lookup
  • resolveCoords(mate): Get coordinates from GPS or capital fallback
  • Coordinate resolution logic

styles/ Directory

style.css

All application styles in a single file (805 lines). See Styling Guide for detailed breakdown. Main sections:
  • CSS custom properties (design tokens)
  • Layout (header, main, side panel)
  • Components (cards, forms, buttons)
  • Globe customization
  • Modals and overlays
  • Responsive breakpoints

Script Load Order

Scripts are loaded in dependency order (index.html:260-274):
<!-- External dependencies -->
<script src="bootstrap.bundle.min.js"></script>
<script src="@supabase/supabase-js"></script>

<!-- Data -->
<script src="data/i18n.js"></script>
<script src="config/constants.js"></script>
<script src="data/iso-tables.js"></script>
<script src="data/capital-coords.js"></script>
<script src="data/countries.js"></script>

<!-- Modules -->
<script src="modules/state.js"></script>
<script src="modules/utils.js"></script>
<script src="modules/globe.js"></script>
<script src="modules/gps.js"></script>
<script src="modules/gallery.js"></script>
<script src="modules/modal.js"></script>
<script src="modules/form.js"></script>
<script src="modules/menu.js"></script>

<!-- Main app -->
<script src="app.js"></script>
The load order matters! State must load before modules that depend on it. Utils must load before functions that call t() for translations.

Finding Specific Features

Language Switching

Location: app.js:5-15, data/i18n.jsLanguage buttons trigger applyI18n() which updates all data-i18n attributes

Form Submission

Location: modules/form.jsHandles validation, image upload to Supabase Storage, and database insertion

Globe Visualization

Location: modules/globe.jsSets up Globe.gl, renders polygons, markers, and arcs

GPS Detection

Location: modules/gps.jsUses Navigator Geolocation API and reverse geocoding

Next: Styling Guide

Explore the CSS architecture and design system used in 200 Mates.

Build docs developers (and LLMs) love