title = "User Groups"
url = "/community/user-groups"
layout = "default"
description = "Find local Godot user groups run by community members."
is_hidden = 0
==
function onStart() {
  // Order countries alphabetically with their name in English.
  // A community is considered physical if it defines GPS coordinates (in [latitude, longitude] format).
  // Otherwise, it's considered an online community.
  $this['userGroups'] = [
    'Algeria' => [
      [
        'name' => 'Arab Gamedev',
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://facebook.com/groups/arabgamedev'],
        ],
      ],
    ],
    'Argentina' => [
      [
        'name' => 'Godot en Español',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/2BtycSPdkk'],
        ],
      ],
    ],
    'Brazil' => [
      [
        'name' => 'Godot Brazil',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/gWmQKBv'],
        ],
      ],
      [
        'name' => 'Godot Brasil',
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/godotBrasil'],
        ],
      ],
      [
        'name' => 'São Paulo',
        'coordinates' => [-23.5505, -46.6333],
        'links' => [
          ['title' => 'MeetUp', 'url' => 'https://www.meetup.com/GodotSP/'],
        ],
      ],
      [
        'name' => 'Campinas',
        'coordinates' => [-22.8136, -47.0641],
        'links' => [
          ['title' => 'Gamux', 'url' => 'https://gamuxunicamp.github.io/website/'],
        ],
      ],
    ],
    'Belgium' => [
      [
        'name' => 'Godot Club',
        'coordinates' => [50.848916943044415, 4.349575282209013],
        'links' => [
          ['title' => 'Website', 'url' => 'https://polymorph.cool/godot-club/'],
        ],
      ],
    ],
    'Bulgaria' => [
      [
        'name' => 'BGodot',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/j3KRdV3b4P'],
        ],
      ],
    ],
    'Canada' => [
      [
        'name' => 'Godot Toronto',
        'links' => [
          ['title' => 'MeetUp', 'url' => 'https://www.meetup.com/Godot-Toronto/'],
        ],
      ],
    ],
    'China' => [
      [
        'name' => 'Godot China',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/R23VUTXwvz'],
          ['title' => 'QQ Group', 'url' => 'https://qm.qq.com/cgi-bin/qm/qr?k=EneMKrKt96ttI4ZFmQ8omTtpF0Sd0iL_&jump_from=webapi'],
        ],
      ],
      [
        'name' => 'GodoterCN',
        'links' => [
          ['title' => 'Website', 'url' => 'https://godoter.cn'],
        ],
      ],
      [
        'name' => 'Godoter Planet (Godoter 星球)',
        'links' => [
          ['title' => 'QQ Group', 'url' => 'https://qm.qq.com/cgi-bin/qm/qr?k=jKCCDvS6uTXHLrVBRuGk67iCvA5bshPY&jump_from=webapi'],
        ],
      ],
      [
        'name' => 'Godot Tieba',
        'links' => [
          ['title' => 'Forum', 'url' => 'https://tieba.baidu.com/f?kw=godot'],
        ],
      ],
      [
        'name' => 'GodotCN (Godot中文社区)',
        'links' => [
          ['title' => 'Website', 'url' => 'http://godott.com'],
          ['title' => 'QQ Group', 'url' => 'https://qm.qq.com/cgi-bin/qm/qr?k=hEscGFbQTiOX0bhsTT2myxM3PifsAmIp&jump_from=webapi'],
        ],
      ],
    ],
    'Croatia' => [
      [
        'name' => 'Croatia',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/6gjwfSG'],
          ['title' => 'Facebook', 'url' => 'https://web.facebook.com/groups/godotenginecroatia/'],
        ],
      ],
    ],
    'Czech Republic and Slovakia' => [
      [
        'name' => 'Godot CZ/SK',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.com/invite/g4XVFjXwfu'],
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/godotczsk'],
        ],
      ],
    ],
    'Ecuador' => [
      [
        'name' => 'Godot Ecuador',
        'coordinates' => [-1.8312, -78.1834],
        'links' => [
          ['title' => 'Reddit', 'url' => 'https://www.reddit.com/r/GodotEcuador/'],
          ['title' => 'Discord', 'url' => 'https://discord.gg/nZecyhN'],
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/godotengineecuador/'],
        ],
      ],
    ],
    'Egypt' => [
      [
        'name' => 'Godot Egypt (Ain Shams University)',
        'coordinates' => [30.077605, 31.285800],
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/QCxAgAAtYg'],
        ],
      ],
    ],
    'Finland' => [
      [
        'name' => 'Godot Suomi',
        'coordinates' => [60.16952, 24.93545],
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/5QF5du3'],
        ],
      ],
    ],
    'France or French-speaking' => [
      [
        'name' => 'Godot Francophone',
        'links' => [
          ['title' => 'Website', 'url' => 'https://www.godot-francophone.org/'],
          ['title' => 'Discord', 'url' => 'https://discordapp.com/invite/NQVd34V'],
          ['title' => 'GitHub', 'url' => 'https://github.com/Godot-Engine-Francophone'],
        ],
      ],
      [
        'name' => 'Godot est arrivé!',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/9FJAZaC'],
        ],
      ],
      [
        'name' => 'SoloCode France',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/gZ3QJ5T'],
        ],
      ],
    ],
    'Germany' => [
      [
        'name' => 'Godot Germany',
        'links' => [
          ['title' => 'Website', 'url' => 'https://godot-community.de/'],
          ['title' => 'Discord', 'url' => 'https://discord.gg/Tr7Ma6E'],
          ['title' => 'Reddit', 'url' => 'https://www.reddit.com/r/GodotCommunityDE/'],
        ],
      ],
      [
        'name' => 'Godot Engine German Developers',
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/359812631518879'],
        ],
      ],
    ],
    'India' => [
      [
        'name' => 'Godot India',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/cRvFbRg'],
          ['title' => 'Telegram', 'url' => 'https://t.me/godotindia'],
        ],
      ],
    ],
    'Indonesia' => [
      [
        'name' => 'Godot Indonesia',
        'links' => [
          ['title' => 'Website', 'url' => 'https://godot.id'],
          ['title' => 'Telegram', 'url' => 'https://t.me/godot_indonesia'],
        ],
      ],
    ],
    'Italy' => [
      [
        'name' => 'Godot Engine Italia',
        'links' => [
          ['title' => 'Website', 'url' => 'https://godotengineitalia.com/'],
          ['title' => 'Telegram', 'url' => 'https://t.me/joinchat/Ga4KigwWn53t2RRfoaPSKg'],
          ['title' => 'Discord', 'url' => 'https://discord.gg/7YuUqJB'],
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/1926189904375792/'],
        ],
      ],
    ],
    'Iran' => [
      [
        'name' => 'Godot Iran (گودو ایران)',
        'links' => [
          ['title' => 'Website', 'url' => 'https://TahsinRafiey.org/godot-iran'],
          ['title' => 'Telegram', 'url' => 'https://t.me/GodotIran'],
          ['title' => 'Matrix', 'url' => 'https://matrix.to/#/#godotiran:matrix.org'],
        ],
      ],
      [
        'name' => 'GDworld',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/n3BX6ujU5f'],
          ['title' => 'Telegram', 'url' => 'https://t.me/world_of_godot'],
        ],
      ],
    ],
    'Israel' => [
      [
        'name' => 'Godot Israel',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/k5HN6SQqnv'],
        ],
      ],
    ],
    'Japan' => [
      [
        'name' => 'Godot Japan',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/DyFvSJZ'],
        ],
      ],
    ],
    'Latvia' => [
      [
        'name' => 'Godot Engine Latvia',
        'coordinates' => [56.9496, 24.1052],
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/844651272628474/'],
          ['title' => 'Discord', 'url' => 'https://discord.gg/r6ewZGv'],
          ['title' => 'Twitter', 'url' => 'https://twitter.com/GodotLatvia'],
        ],
      ],
    ],
    'Pakistan' => [
      [
        'name' => 'Godot Engine Pakistan',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/YYjxgdn47P'],
        ],
      ],
    ],
    'Philippines' => [
      [
        'name' => 'Godot Engine Philippines',
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/godotph'],
        ],
      ],
    ],
    'Poland' => [
      [
        'name' => 'Godocik',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/HBuuuPa'],
          ['title' => 'YouTube', 'url' => 'https://www.youtube.com/channel/UCLYdPKE5eviBMZV5WLG43rA'],
        ],
      ],
    ],
    'Portugal' => [
      [
        'name' => 'Godot Portugal',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/nWMbpsFf'],
          ['title' => 'Twitter', 'url' => 'https://twitter.com/godot_pt'],
        ],
      ],
    ],
    'Russia' => [
      [
        'name' => 'Godot Engine Russia',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/MK9aWFX'],
        ],
      ],
      [
        'name' => 'Godot Russia',
        'links' => [
          ['title' => 'VKontakte', 'url' => 'https://vk.com/godot_engine'],
          ['title' => 'Telegram', 'url' => 'https://t.me/godot_engine'],
        ],
      ],
      [
        'name' => 'Game Constructors',
        'links' => [
          ['title' => 'VKontakte', 'url' => 'https://vk.com/game_constructors'],
          ['title' => 'Discord', 'url' => 'https://discord.gg/VjZ2ZZH93c'],
          ['title' => 'ZEN', 'url' => 'https://zen.me/1WHp7X'],
        ],
      ],
    ],
    'Saudi Arabia' => [
      [
        'name' => 'Godot Engine Arabic',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/sGukE2UDJ6'],
        ],
      ],
      [
        'name' => 'Godot Engine Arabic 2',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/fvNyxDQAJy'],
        ],
      ],
    ],
    'South Korea' => [
      [
        'name' => 'Godot Engine Korea',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/XK8Emsf'],
        ],
      ],
    ],
    'Spain' => [
      [
        'name' => 'Godot Engine in Spanish',
        'links' => [
          ['title' => 'Website', 'url' => 'http://godotengineenespanol.surge.sh'],
          ['title' => 'Discord', 'url' => 'https://discord.com/invite/fp4Z7QmZGu'],
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/GodotEngineEnEspanol'],
        ],
      ],
      [
        'name' => 'Zenvoid (Medialab Prado)',
        'coordinates' => [40.4105013, -3.6958529],
        'links' => [
          ['title' => 'Website', 'url' => 'https://www.medialab-prado.es/actividades/zenvoid-studio-desarrollo-de-videojuegos'],
        ],
      ],
    ],
    'Sweden' => [
      [
        'name' => 'Godot Sweden',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/6ZsgWmH'],
        ],
      ],
    ],
    'Taiwan' => [
      [
        'name' => 'Godot Engine Taiwan',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/fuTtQMaxZ2'],
        ],
      ],
      [
        'name' => 'Godot Taiwan (Godot 台灣使用者小聚)',
        'links' => [
          ['title' => 'Facebook', 'url' => 'https://www.facebook.com/groups/godot.taiwan'],
        ],
      ],
    ],
    'Turkey' => [
      [
        'name' => 'Godot Engine Türkiye',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/3zuaj9EsYv'],
          ['title' => 'Telegram', 'url' => 'https://t.me/joinchat/GsAFJn7i-1fk0YUW'],
        ],
      ],
      [
        'name' => 'Godot in Turkey',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/AtHr842H7b'],
        ],
      ],
      [
        'name' => 'Godot Türk Topluluğu',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/B48HBJM'],
        ],
      ],
    ],
    'United States' => [
      [
        'name' => 'Godot Southwest US',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/qx7Ec49yDg'],
        ],
      ],
      [
        'name' => 'Godot Wisconsin',
        'links' => [
          ['title' => 'Meetup', 'url' => 'https://www.meetup.com/wi-godot-game-app-developer-meetup/'],
        ],
      ],
      [
        'name' => 'Chickensoft',
        'links' => [
          ['title' => 'Discord', 'url' => 'https://discord.gg/MjA6HUzzAE'],
        ],
      ],
    ],
  ];
}
==
{##}
<link rel="stylesheet" href="{{ 'assets/leaflet/leaflet.css?1' | theme }}">
<script defer src="{{ 'assets/leaflet/leaflet.js?1' | theme }}"></script>
<script>
  const points = {{ userGroups | json_encode(constant('JSON_UNESCAPED_SLASHES') b-or constant('JSON_UNESCAPED_UNICODE')) | raw }};
  const countryCoordinates = {
    // Full country name: [latitude, longitude]
    // Use <https://latitude.to/> to find GPS coordinates.
    'Algeria': [28.00003, 2.99998],
    'Argentina': [-38.4192641, -63.5989206],
    'Brazil': [-14.240073, -53.180502],
    'Bulgaria': [42.60740, 25.48566],
    'Canada': [56.130366, -106.346771],
    'China': [35.486703, 101.901875],
    'Croatia': [45.815399, 15.966568],
    'Czech Republic and Slovakia': [50.073658, 14.418540],
    'Ecuador': [-1.160171, -78.432915],
    'Finland': [62.777754, 26.199539],
    'France or French-speaking': [47.824905, 2.618787],
    'Germany': [51.133481, 10.018343],
    'India': [22.199166, 78.476681],
    'Indonesia': [-2.548926, 118.0148634],
    'Italy': [42.504154, 12.646361],
    'Iran': [32.4207423, 53.6830157],
    'Israel': [31.53131, 34.86677],
    'Japan': [36.57484, 139.23942],
    'Latvia': [56.959065, 24.862593],
    'Pakistan': [30.3894, 69.353220],
    'Philippines': [14.583333, 120.966667],
    'Poland': [51.9189046, 19.1343786],
    'Portugal': [40.03326, -7.88963],
    'Russia': [55.751400, 37.620900],
    'Saudi Arabia': [25.62426, 42.35283],
    'South Korea': [36.638392, 127.6961188],
    'Spain': [40.2085, -3.713],
    'Sweden': [64.964875, 17.675409],
    'Taiwan': [23.44265, 120.50237],
    'Turkey': [39.908606, 32.784806],
    'United States': [39.78373, -100.44588],
  }

  function escapeXml(unsafe) {
    return unsafe.replace(/[<>&'"]/g, function (character) {
      switch (character) {
        case '<': return '&lt;';
        case '>': return '&gt;';
        case '&': return '&amp;';
        case "'": return '&apos;';
        case '"': return '&quot;';
      }
    });
  }

  window.addEventListener('DOMContentLoaded', () => {
    const bounds = L.latLngBounds(L.latLng(90, -180), L.latLng(-90, 180));
    const myMap = L.map('community-map', {
      // Show the whole world (centered around Europe) when loading.
      center: [40, 0],
      zoom: 3,
      maxBounds: bounds,
      maxBoundsViscosity: 1,
    });

    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap contributors</a>',
      // Use more reasonable zoom level limits where tiles are still displayed.
      minZoom: 2,
      maxZoom: 18,
      noWrap: true,
      bounds,
    }).addTo(myMap);

    // The icon to use for physical venues.
    const physicalIcon = L.icon({
      iconUrl: '{{ "assets/leaflet/images/physical-marker-icon.png" | theme }}',
      iconRetinaUrl: '{{ "assets/leaflet/images/physical-marker-icon-2x.png" | theme }}',
      iconSize: [25, 41],
      iconAnchor: [12, 41],
      shadowUrl: '{{ "assets/leaflet/images/marker-shadow.png" | theme }}',
      shadowSize: [41, 41],
      shadowAnchor: [13, 41],
      popupAnchor: [1, -34],
      tooltipAnchor: [16, -28],
    });

    // Object with country names as key, array of points as value.
    const onlinePoints = {};

    // Flatten the object while looping over it.
    Object.keys(points).forEach((country, index) => {
      points[country].forEach((point, index2) => {
        // Store the country so we can get the coordinates for online communities.
        point.country = country;
        if (point.coordinates) {
          // Physical community.
          const marker = L.marker(point.coordinates, {
            title: point.name,
            icon: physicalIcon,
          });
          marker.bindPopup(`
            <strong>${escapeXml(point.name)}</strong><br>
            ${point.links.map((link) => ` <a href="${escapeXml(link.url)}">${escapeXml(link.title)}</a>`)}
          `).openPopup();
          marker.addTo(myMap);
        } else {
          // Online community.
          // We only want one marker per country (with a merged tooltip, see below).
          // Therefore, we don't add the marker here directly.
          if (!onlinePoints[point.country]) {
            onlinePoints[point.country] = []
          }

          onlinePoints[point.country].push(point);
        }
      });
    });

    // Add markers for online communities with merged tooltips.
    Object.keys(onlinePoints).forEach((country, index) => {
      let markerPopup = '';
      onlinePoints[country].forEach((point, index2) => {
        // Add a line separation between online communities.
        markerPopup += `
            ${index2 >= 1 ? '<hr>' : ''}
            <strong>${escapeXml(point.name)}</strong><br>
            ${point.links.map((link) => ` <a href="${escapeXml(link.url)}">${escapeXml(link.title)}</a>`)}
        `;
      });

      const marker = L.marker(countryCoordinates[country], {
        title: country,
      });
      marker.bindPopup(markerPopup).openPopup();
      marker.addTo(myMap);
    });
  });
</script>


{% put head_text %}
  <p class="small">
    Some community members manage local Godot user groups.
    Anyone is welcome to join or create a local community!
  </p>
{% endput %}

<h2 class="title">Community map</h2>
<p>
  This map lists all physical venues and online community hosted by community members.
  Scroll down to view a list of online communities.
</p>
<div id="community-map" style="height: 35rem"></div>
<p>
  <!-- Color legend. -->
  <span style="display: inline-block; width: 0.75rem; height: 0.75rem; border-radius: 50%; background-color: #b7422c; margin-right: 0.4rem"></span>
  Physical community
  <span style="display: inline-block; width: 0.75rem; height: 0.75rem; border-radius: 50%; background-color: #257eca; margin-right: 0.4rem; margin-left: 1.5rem"></span>
  Online community
</p>

{% for countryName, userGroupCountry in userGroups %}
<h3 class="title">{{ countryName }}</h3>
<ul>
  {% for userGroup in userGroupCountry %}
  <li>
    {{ userGroup.name }}
    ({% for userGroupLink in userGroup.links %}<a href="{{ userGroupLink.url }}">{{ userGroupLink.title }}</a>{% if not loop.last %}, {% endif %}{% endfor %})
  </li>
  {% endfor %}
</ul>
{% endfor %}

<p style="margin-top: 4rem">
  If you run a local community and would like to have it listed here,
  please send an email to <em>webmaster at godotengine · org</em>.
</p>
