{"id":48833,"date":"2026-09-03T11:15:41","date_gmt":"2026-09-03T09:15:41","guid":{"rendered":"https:\/\/www.freelancermap.com\/blog\/?page_id=48833"},"modified":"2026-09-04T15:30:55","modified_gmt":"2026-09-04T13:30:55","slug":"freelance-events","status":"publish","type":"page","link":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/","title":{"rendered":"Freelance Events &amp; Conferences 2026"},"content":{"rendered":"\n<p>Discover freelance events, conferences, meetups, workshops and networking opportunities around the world. Find events for freelancers and independent professionals by date, location, event type, topic or format \u2013 online, in person or hybrid.<\/p>\n\n\n\n<p>Whether you want to expand your network, learn new skills, meet potential clients or stay up to date with the future of freelancing, our event directory helps you find the right event for you.<\/p>\n\n\n\n<div id=\"fm-events\">\n\n  <style>\n    #fm-events {\n      --fm-green: #00FFC8;\n      --fm-purple: #49376F;\n      --fm-black: #111111;\n      --fm-white: #ffffff;\n      --fm-gray-50: #f7f7f7;\n      --fm-gray-100: #eeeeee;\n      --fm-gray-300: #cccccc;\n      --fm-gray-600: #666666;\n      --fm-radius: 8px;\n\n      color: var(--fm-black);\n      font-family: inherit;\n      line-height: 1.5;\n      width: 100%;\n      box-sizing: border-box;\n    }\n\n    #fm-events *,\n    #fm-events *::before,\n    #fm-events *::after {\n      box-sizing: border-box;\n    }\n\n    #fm-events a,\n    #fm-events button,\n    #fm-events select {\n      text-transform: none !important;\n      letter-spacing: normal !important;\n      box-shadow: none !important;\n      text-shadow: none !important;\n      font-style: normal !important;\n    }\n\n    #fm-events h2 {\n      color: var(--fm-purple);\n      font-size: 32px;\n      line-height: 1.2;\n      margin: 0 0 24px;\n      font-weight: 700;\n    }\n\n    #fm-events h3 {\n      color: var(--fm-purple);\n      font-size: 22px;\n      line-height: 1.3;\n      margin: 0 0 8px;\n      font-weight: 700;\n    }\n\n    #fm-events .fm-filter-section {\n      background: var(--fm-gray-50);\n      border-top: 4px solid var(--fm-green);\n      padding: 28px;\n      margin: 40px 0 50px;\n      border-radius: 0 var(--fm-radius) var(--fm-radius) var(--fm-radius);\n    }\n\n    #fm-events .fm-filter-grid {\n      display: grid;\n      grid-template-columns: repeat(4, minmax(0, 1fr));\n      gap: 20px;\n    }\n\n    #fm-events .fm-filter-field {\n      min-width: 0;\n    }\n\n    #fm-events .fm-filter-field label {\n      display: block;\n      color: var(--fm-purple);\n      font-weight: 700;\n      font-size: 15px;\n      margin-bottom: 8px;\n    }\n\n    #fm-events .fm-filter-field select {\n      display: block !important;\n      width: 100% !important;\n      min-height: 48px !important;\n      max-width: 100% !important;\n      box-sizing: border-box !important;\n      padding: 10px 28px 10px 14px !important;\n      border: 1px solid var(--fm-gray-300) !important;\n      border-radius: var(--fm-radius) !important;\n      background: var(--fm-white) !important;\n      color: var(--fm-black) !important;\n      font-family: inherit !important;\n      font-size: 15px !important;\n      line-height: 1.3 !important;\n      margin: 0 !important;\n      cursor: pointer;\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n    }\n\n    #fm-events .fm-filter-field select:focus {\n      outline: 2px solid var(--fm-green);\n      outline-offset: 2px;\n    }\n\n    #fm-events .fm-filter-actions {\n      margin-top: 20px;\n    }\n\n    #fm-events .fm-reset-button {\n      display: inline-block !important;\n      border: 0 !important;\n      background: var(--fm-purple) !important;\n      color: var(--fm-white) !important;\n      padding: 11px 18px !important;\n      margin: 0 !important;\n      font-family: inherit !important;\n      font-size: 15px !important;\n      line-height: 1.3 !important;\n      font-weight: 700 !important;\n      box-sizing: border-box !important;\n      vertical-align: middle;\n      cursor: pointer;\n      border-radius: var(--fm-radius) !important;\n    }\n\n    #fm-events .fm-reset-button:hover {\n      background: var(--fm-green);\n      color: var(--fm-black);\n    }\n\n    #fm-events .fm-reset-button:focus-visible {\n      outline: 2px solid var(--fm-purple);\n      outline-offset: 2px;\n    }\n\n    #fm-events .fm-calendar-section {\n      margin-bottom: 55px;\n    }\n\n    #fm-events .fm-calendar-header {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 20px;\n      margin-bottom: 20px;\n    }\n\n    #fm-events .fm-calendar-header h2 {\n      margin: 0;\n    }\n\n    #fm-events .fm-calendar-navigation {\n      display: flex;\n      gap: 8px;\n      flex-shrink: 0;\n    }\n\n    #fm-events .fm-calendar-navigation button {\n      width: 44px !important;\n      height: 44px !important;\n      border: 0 !important;\n      background: var(--fm-purple) !important;\n      color: var(--fm-white) !important;\n      font-size: 20px !important;\n      line-height: 1 !important;\n      margin: 0 !important;\n      padding: 0 !important;\n      box-sizing: border-box !important;\n      cursor: pointer;\n      border-radius: var(--fm-radius) !important;\n    }\n\n    #fm-events .fm-calendar-navigation button:hover:not(:disabled) {\n      background: var(--fm-green);\n      color: var(--fm-black);\n    }\n\n    #fm-events .fm-calendar-navigation button:focus-visible {\n      outline: 2px solid var(--fm-green);\n      outline-offset: 2px;\n    }\n\n    #fm-events .fm-calendar-navigation button:disabled {\n      opacity: 0.35;\n      cursor: default;\n    }\n\n    #fm-events .fm-calendar-month-title {\n      text-align: center;\n      color: var(--fm-purple);\n      font-size: 21px;\n      font-weight: 700;\n      margin: 0 0 15px;\n    }\n\n    #fm-events .fm-calendar-scroll {\n      width: 100%;\n      overflow-x: auto;\n      overflow-y: hidden;\n      -webkit-overflow-scrolling: touch;\n      padding-bottom: 5px;\n    }\n\n    #fm-events .fm-calendar {\n      width: 100%;\n      border-left: 1px solid var(--fm-gray-300);\n      border-top: 1px solid var(--fm-gray-300);\n      border-radius: var(--fm-radius);\n      overflow: hidden;\n    }\n\n    #fm-events .fm-calendar-weekdays,\n    #fm-events .fm-calendar-grid {\n      display: grid;\n      grid-template-columns: repeat(7, minmax(0, 1fr));\n    }\n\n    #fm-events .fm-calendar-weekday {\n      background: var(--fm-gray-100);\n      color: var(--fm-purple);\n      font-weight: 700;\n      text-align: center;\n      padding: 11px 5px;\n      border-right: 1px solid var(--fm-gray-300);\n      border-bottom: 1px solid var(--fm-gray-300);\n      min-width: 0;\n    }\n\n    #fm-events .fm-weekday-short {\n      display: none;\n    }\n\n    #fm-events .fm-calendar-day {\n      position: relative;\n      min-width: 0;\n      min-height: 125px;\n      padding: 7px;\n      background: var(--fm-white);\n      border-right: 1px solid var(--fm-gray-300);\n      border-bottom: 1px solid var(--fm-gray-300);\n      overflow: hidden;\n    }\n\n    #fm-events .fm-calendar-day-empty {\n      background: var(--fm-gray-50);\n    }\n\n    #fm-events .fm-calendar-day-number {\n      display: block;\n      font-size: 14px;\n      font-weight: 700;\n      margin-bottom: 5px;\n    }\n\n    #fm-events .fm-calendar-day-today .fm-calendar-day-number {\n      display: inline-block;\n      background: var(--fm-purple);\n      color: var(--fm-white);\n      padding: 2px 7px;\n      border-radius: var(--fm-radius);\n    }\n\n    #fm-events .fm-calendar-event {\n      display: block !important;\n      width: 100% !important;\n      min-width: 0 !important;\n      max-width: 100% !important;\n      box-sizing: border-box !important;\n      margin: 4px 0 !important;\n      padding: 6px 7px !important;\n      background: var(--fm-green) !important;\n      color: var(--fm-black) !important;\n      border: 0 !important;\n      border-left: 4px solid var(--fm-purple) !important;\n      border-radius: var(--fm-radius) !important;\n      font-size: 12px !important;\n      font-family: inherit !important;\n      line-height: 1.25 !important;\n      font-weight: 700 !important;\n      text-decoration: none !important;\n      overflow: hidden !important;\n      overflow-wrap: anywhere !important;\n      word-break: normal !important;\n      cursor: pointer !important;\n    }\n\n    #fm-events .fm-calendar-event:hover {\n      background: var(--fm-purple) !important;\n      color: var(--fm-white) !important;\n    }\n\n    #fm-events .fm-calendar-event:focus-visible {\n      outline: 2px solid var(--fm-purple) !important;\n      outline-offset: 2px !important;\n    }\n\n    #fm-events .fm-calendar-event-title {\n      display: block;\n      overflow: hidden;\n      overflow-wrap: anywhere;\n    }\n\n    #fm-events .fm-calendar-day-indicator {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      margin-top: 6px;\n    }\n\n    #fm-events .fm-calendar-day-dot {\n      width: 8px;\n      height: 8px;\n      border-radius: 50%;\n      background: var(--fm-green);\n      display: inline-block;\n    }\n\n    #fm-events .fm-calendar-day-badge {\n      display: inline-flex;\n      align-items: center;\n      justify-content: center;\n      min-width: 18px;\n      height: 18px;\n      padding: 0 4px;\n      border-radius: 999px;\n      background: var(--fm-purple);\n      color: var(--fm-white);\n      font-size: 10px;\n      font-weight: 700;\n      line-height: 1;\n    }\n\n    #fm-events .fm-calendar-day-clickable {\n      cursor: pointer;\n    }\n\n    #fm-events .fm-calendar-day-clickable:hover,\n    #fm-events .fm-calendar-day-clickable:focus-visible {\n      background: var(--fm-gray-50);\n      outline: 2px solid var(--fm-green);\n      outline-offset: -2px;\n    }\n\n    #fm-events .fm-calendar-scroll-hint {\n      display: none;\n      color: var(--fm-gray-600);\n      font-size: 13px;\n      text-align: center;\n      margin-top: 8px;\n    }\n\n    #fm-events .fm-events-list-section {\n      margin-bottom: 60px;\n    }\n\n    #fm-events .fm-results-count {\n      color: var(--fm-gray-600);\n      margin: -12px 0 22px;\n      font-size: 15px;\n    }\n\n    #fm-events .fm-event-list {\n      display: grid;\n      gap: 18px;\n    }\n\n    #fm-events .fm-event-card {\n      background: var(--fm-white);\n      border: 1px solid var(--fm-gray-300);\n      border-left: 5px solid var(--fm-purple);\n      padding: 22px 24px;\n      border-radius: var(--fm-radius);\n    }\n\n    #fm-events .fm-event-card:hover {\n      border-left-color: var(--fm-green);\n    }\n\n    #fm-events .fm-event-card-highlight {\n      animation: fm-highlight-pulse 1.8s ease;\n    }\n\n    @keyframes fm-highlight-pulse {\n      0% {\n        background: var(--fm-green);\n      }\n      100% {\n        background: var(--fm-white);\n      }\n    }\n\n    #fm-events .fm-event-card-date {\n      color: var(--fm-purple);\n      font-size: 14px;\n      font-weight: 700;\n      margin-bottom: 7px;\n    }\n\n    #fm-events .fm-event-card h3 {\n      margin-bottom: 9px;\n    }\n\n    #fm-events .fm-event-description {\n      color: var(--fm-black);\n      font-size: 15px;\n      line-height: 1.5;\n      margin: 0 0 15px;\n    }\n\n    #fm-events .fm-event-meta {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 8px;\n      margin-bottom: 15px;\n    }\n\n    #fm-events .fm-event-meta-item {\n      display: inline-block;\n      background: var(--fm-gray-100);\n      color: var(--fm-black);\n      font-size: 14px;\n      line-height: 1.3;\n      padding: 5px 11px;\n      border-radius: var(--fm-radius);\n      white-space: nowrap;\n    }\n\n    #fm-events .fm-event-link {\n      display: inline-block !important;\n      background: var(--fm-green) !important;\n      color: var(--fm-black) !important;\n      padding: 10px 16px !important;\n      margin: 0 !important;\n      font-size: 15px !important;\n      line-height: 1.2 !important;\n      font-weight: 700 !important;\n      font-family: inherit !important;\n      border: 0 !important;\n      box-sizing: border-box !important;\n      text-decoration: none !important;\n      border-radius: var(--fm-radius) !important;\n    }\n\n    #fm-events .fm-event-link:hover {\n      background: var(--fm-purple) !important;\n      color: var(--fm-white) !important;\n    }\n\n    #fm-events .fm-event-link:focus-visible {\n      outline: 2px solid var(--fm-purple);\n      outline-offset: 2px;\n    }\n\n    #fm-events .fm-no-results {\n      background: var(--fm-gray-50);\n      border-left: 4px solid var(--fm-green);\n      padding: 22px;\n      color: var(--fm-black);\n      border-radius: var(--fm-radius);\n    }\n\n    #fm-events .fm-loading {\n      padding: 20px 0;\n      color: var(--fm-gray-600);\n    }\n\n    #fm-events .fm-day-modal-overlay {\n      position: fixed;\n      inset: 0;\n      background: rgba(17, 17, 17, 0.5);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      z-index: 1000;\n      padding: 20px;\n    }\n\n    #fm-events .fm-day-modal-overlay[hidden] {\n      display: none;\n    }\n\n    #fm-events .fm-day-modal {\n      background: var(--fm-white);\n      width: 100%;\n      max-width: 480px;\n      max-height: 80vh;\n      overflow-y: auto;\n      border-radius: var(--fm-radius);\n      padding: 20px;\n    }\n\n    #fm-events .fm-day-modal-header {\n      display: flex;\n      align-items: flex-start;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 16px;\n    }\n\n    #fm-events .fm-day-modal-header h3 {\n      margin: 0;\n      font-size: 19px;\n    }\n\n    #fm-events .fm-day-modal-close {\n      flex-shrink: 0;\n      border: 0;\n      background: var(--fm-gray-100);\n      color: var(--fm-black);\n      width: 34px;\n      height: 34px;\n      border-radius: var(--fm-radius);\n      font-size: 18px;\n      line-height: 1;\n      cursor: pointer;\n    }\n\n    #fm-events .fm-day-modal-close:hover {\n      background: var(--fm-purple);\n      color: var(--fm-white);\n    }\n\n    #fm-events .fm-day-modal-close:focus-visible {\n      outline: 2px solid var(--fm-green);\n      outline-offset: 2px;\n    }\n\n    #fm-events .fm-day-modal-event {\n      border: 1px solid var(--fm-gray-300);\n      border-left: 4px solid var(--fm-purple);\n      border-radius: var(--fm-radius);\n      padding: 14px 16px;\n      margin-bottom: 12px;\n    }\n\n    #fm-events .fm-day-modal-event:last-child {\n      margin-bottom: 0;\n    }\n\n    @media (max-width: 900px) {\n      #fm-events .fm-filter-grid {\n        grid-template-columns: repeat(2, minmax(0, 1fr));\n      }\n\n      #fm-events .fm-calendar-day {\n        min-height: 95px;\n        padding: 5px;\n      }\n\n      #fm-events .fm-calendar-event {\n        font-size: 11px !important;\n        padding: 5px 6px !important;\n      }\n    }\n\n    @media (max-width: 600px) {\n      #fm-events .fm-filter-section {\n        padding: 20px;\n      }\n\n      #fm-events .fm-filter-grid {\n        grid-template-columns: 1fr;\n      }\n\n      #fm-events h2 {\n        font-size: 27px;\n      }\n\n      #fm-events .fm-calendar-header {\n        flex-direction: column;\n        align-items: flex-start;\n        gap: 12px;\n      }\n\n      #fm-events .fm-calendar-header h2 {\n        font-size: 27px;\n      }\n\n      #fm-events .fm-calendar-navigation {\n        align-self: flex-start;\n      }\n\n      #fm-events .fm-calendar-scroll {\n        overflow-x: visible;\n      }\n\n      #fm-events .fm-calendar {\n        min-width: 0;\n      }\n\n      #fm-events .fm-calendar-weekday {\n        padding: 8px 2px;\n        font-size: 12px;\n      }\n\n      #fm-events .fm-weekday-full {\n        position: absolute !important;\n        width: 1px !important;\n        height: 1px !important;\n        padding: 0 !important;\n        margin: -1px !important;\n        overflow: hidden !important;\n        clip: rect(0, 0, 0, 0) !important;\n        white-space: nowrap !important;\n        border: 0 !important;\n      }\n\n      #fm-events .fm-weekday-short {\n        display: inline;\n      }\n\n      #fm-events .fm-calendar-day {\n        min-height: 52px;\n        padding: 4px 2px;\n      }\n\n      #fm-events .fm-calendar-day-number {\n        font-size: 12px;\n        margin-bottom: 0;\n      }\n\n      #fm-events .fm-calendar-scroll-hint {\n        display: block;\n      }\n\n      #fm-events .fm-event-card {\n        padding: 19px;\n      }\n\n      #fm-events .fm-event-meta-item {\n        font-size: 13px;\n      }\n\n      #fm-events .fm-day-modal-overlay {\n        align-items: flex-end;\n        padding: 0;\n      }\n\n      #fm-events .fm-day-modal {\n        max-width: none;\n        max-height: 85vh;\n        border-radius: var(--fm-radius) var(--fm-radius) 0 0;\n      }\n    }\n  <\/style>\n\n\n  <section class=\"fm-filter-section\" aria-label=\"Find a freelance event\">\n\n    <h2>Find a freelance event<\/h2>\n\n    <div class=\"fm-filter-grid\">\n\n      <div class=\"fm-filter-field\">\n        <label for=\"fm-country\">Country<\/label>\n        <select id=\"fm-country\">\n          <option value=\"\">All countries<\/option>\n        <\/select>\n      <\/div>\n\n      <div class=\"fm-filter-field\">\n        <label for=\"fm-city\">City<\/label>\n        <select id=\"fm-city\">\n          <option value=\"\">All cities<\/option>\n        <\/select>\n      <\/div>\n\n      <div class=\"fm-filter-field\">\n        <label for=\"fm-format\">Format<\/label>\n        <select id=\"fm-format\">\n          <option value=\"\">All formats<\/option>\n          <option value=\"Online\">Online<\/option>\n          <option value=\"In person\">In person<\/option>\n          <option value=\"Hybrid\">Hybrid<\/option>\n        <\/select>\n      <\/div>\n\n      <div class=\"fm-filter-field\">\n        <label for=\"fm-month\">Month<\/label>\n        <select id=\"fm-month\">\n          <option value=\"upcoming\">Upcoming events<\/option>\n          <option value=\"year\">All events in 2026<\/option>\n        <\/select>\n      <\/div>\n\n    <\/div>\n\n    <div class=\"fm-filter-actions\">\n      <button type=\"button\" class=\"fm-reset-button\" id=\"fm-reset\">\n        Reset filters\n      <\/button>\n    <\/div>\n\n  <\/section>\n\n\n  <section class=\"fm-calendar-section\">\n\n    <div class=\"fm-calendar-header\">\n      <h2>Freelance event calendar<\/h2>\n\n      <div class=\"fm-calendar-navigation\">\n        <button type=\"button\" id=\"fm-prev-month\" aria-label=\"Previous month\">\n          &#8592;\n        <\/button>\n\n        <button type=\"button\" id=\"fm-next-month\" aria-label=\"Next month\">\n          &#8594;\n        <\/button>\n      <\/div>\n    <\/div>\n\n    <div class=\"fm-calendar-month-title\" id=\"fm-calendar-title\">\n      Loading calendar&#8230;\n    <\/div>\n\n    <div class=\"fm-calendar-scroll\">\n\n      <div class=\"fm-calendar\">\n\n        <div class=\"fm-calendar-weekdays\">\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Mon<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">M<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Tue<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">T<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Wed<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">W<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Thu<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">T<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Fri<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">F<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Sat<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">S<\/span><\/div>\n          <div class=\"fm-calendar-weekday\"><span class=\"fm-weekday-full\">Sun<\/span><span class=\"fm-weekday-short\" aria-hidden=\"true\">S<\/span><\/div>\n        <\/div>\n\n        <div class=\"fm-calendar-grid\" id=\"fm-calendar-grid\"><\/div>\n\n      <\/div>\n\n    <\/div>\n\n    <div class=\"fm-calendar-scroll-hint\">\n      Tap a day with events to see full details.\n    <\/div>\n\n  <\/section>\n\n\n  <section class=\"fm-events-list-section\">\n\n    <h2>Upcoming freelance events<\/h2>\n\n    <div class=\"fm-results-count\" id=\"fm-results-count\"><\/div>\n\n    <div class=\"fm-event-list\" id=\"fm-event-list\">\n      <div class=\"fm-loading\">Loading events&#8230;<\/div>\n    <\/div>\n\n  <\/section>\n\n\n  <div class=\"fm-day-modal-overlay\" id=\"fm-day-modal-overlay\" hidden>\n    <div class=\"fm-day-modal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"fm-day-modal-title\">\n      <div class=\"fm-day-modal-header\">\n        <h3 id=\"fm-day-modal-title\">Events<\/h3>\n        <button type=\"button\" class=\"fm-day-modal-close\" id=\"fm-day-modal-close\" aria-label=\"Close\">&times;<\/button>\n      <\/div>\n      <div class=\"fm-day-modal-body\" id=\"fm-day-modal-body\"><\/div>\n    <\/div>\n  <\/div>\n\n\n  <script>\n  (function () {\n\n    'use strict';\n\n    document.addEventListener('DOMContentLoaded', function () {\n\n      function showFallback(err) {\n\n        if (window.console) {\n\n          if (console.error) {\n            console.error('[fm-events] failed to initialize:', err);\n          }\n        }\n\n        var fallbackTitle =\n          document.getElementById('fm-calendar-title');\n\n        if (fallbackTitle) {\n          fallbackTitle.textContent = 'Calendar unavailable';\n        }\n\n        var fallbackList =\n          document.getElementById('fm-event-list');\n\n        if (fallbackList) {\n          fallbackList.innerHTML =\n            '<div class=\"fm-no-results\">' +\n            'Sorry, the event list could not be loaded right now. ' +\n            'Please try refreshing the page.' +\n            '<\/div>';\n        }\n      }\n\n\n      try {\n\n        runFmEvents();\n\n      } catch (fmError) {\n\n        showFallback(fmError);\n      }\n\n\n      function runFmEvents() {\n\n\n        var EVENTS_CSV_URL =\n          'https:\/\/docs.google.com\/spreadsheets\/d\/1NSPsFgJ5x8_l4MRSGM43whPNgUwmHw9H58KIpTa06Hc\/export?format=csv';\n\n\n        var today = new Date();\n        today.setHours(0, 0, 0, 0);\n\n        var currentYear = today.getFullYear();\n\n        var state = {\n          country: '',\n          city: '',\n          format: '',\n          month: 'upcoming',\n          calendarDate: new Date(\n            today.getFullYear(),\n            today.getMonth(),\n            1\n          )\n        };\n\n        var allEvents = [];\n\n\n        function parseDate(value) {\n\n          var parts = value.split('-');\n\n          return new Date(\n            parseInt(parts[0], 10),\n            parseInt(parts[1], 10) - 1,\n            parseInt(parts[2], 10)\n          );\n        }\n\n\n        function formatDate(date) {\n\n          var months = [\n            'January',\n            'February',\n            'March',\n            'April',\n            'May',\n            'June',\n            'July',\n            'August',\n            'September',\n            'October',\n            'November',\n            'December'\n          ];\n\n          return months[date.getMonth()] + ' ' +\n            date.getDate() + ', ' +\n            date.getFullYear();\n        }\n\n\n        function formatDateRange(event) {\n\n          var start = parseDate(event.start);\n          var end = parseDate(event.end);\n\n          if (event.start === event.end) {\n            return formatDate(start);\n          }\n\n          return formatDate(start) + ' \\u2013 ' + formatDate(end);\n        }\n\n\n        function parseCsv(text) {\n\n          var rows = [];\n          var row = [];\n          var field = '';\n          var inQuotes = false;\n          var i = 0;\n          var len = text.length;\n          var ch = '';\n          var next = '';\n\n          while (i < len) {\n\n            ch = text.charAt(i);\n\n            if (inQuotes) {\n\n              if (ch === '\"') {\n\n                next = text.charAt(i + 1);\n\n                if (next === '\"') {\n                  field += '\"';\n                  i += 2;\n                  continue;\n                }\n\n                inQuotes = false;\n                i += 1;\n                continue;\n              }\n\n              field += ch;\n              i += 1;\n              continue;\n            }\n\n            if (ch === '\"') {\n              inQuotes = true;\n              i += 1;\n              continue;\n            }\n\n            if (ch === ',') {\n              row.push(field);\n              field = '';\n              i += 1;\n              continue;\n            }\n\n            if (ch === '\\r') {\n              i += 1;\n              continue;\n            }\n\n            if (ch === '\\n') {\n              row.push(field);\n              rows.push(row);\n              row = [];\n              field = '';\n              i += 1;\n              continue;\n            }\n\n            field += ch;\n            i += 1;\n          }\n\n          if (field.length > 0 || row.length > 0) {\n            row.push(field);\n            rows.push(row);\n          }\n\n          return rows;\n        }\n\n\n        var CSV_FIELD_MAP = {\n          'title': 'title',\n          'description': 'description',\n          'start date': 'start',\n          'end date': 'end',\n          'country': 'country',\n          'city': 'city',\n          'format': 'format',\n          'ticket': 'ticket',\n          'url': 'url'\n        };\n\n\n        function csvRowsToEvents(rows) {\n\n          var result = [];\n\n          if (!rows.length) {\n            return result;\n          }\n\n          var headerRow = rows[0];\n          var keys = [];\n\n          for (var h = 0; h < headerRow.length; h++) {\n\n            var normalized =\n              headerRow[h].trim().toLowerCase();\n\n            keys.push(\n              CSV_FIELD_MAP[normalized] || null\n            );\n          }\n\n          for (var r = 1; r < rows.length; r++) {\n\n            var row = rows[r];\n            var isEmpty = true;\n\n            for (var x = 0; x < row.length; x++) {\n\n              if (row[x]) {\n\n                if (row[x].trim() !== '') {\n                  isEmpty = false;\n                  break;\n                }\n              }\n            }\n\n            if (isEmpty) {\n              continue;\n            }\n\n            var obj = {\n              title: '',\n              description: '',\n              start: '',\n              end: '',\n              country: '',\n              city: '',\n              format: '',\n              ticket: '',\n              url: ''\n            };\n\n            for (var c = 0; c < row.length; c++) {\n\n              var key = keys[c];\n\n              if (key) {\n                obj[key] = (row[c] || '').trim();\n              }\n            }\n\n            if (!obj.title) {\n              continue;\n            }\n\n            if (!obj.start) {\n              continue;\n            }\n\n            if (!obj.end) {\n              continue;\n            }\n\n            result.push(obj);\n          }\n\n          return result;\n        }\n\n\n        function buildAllEvents(fetchedEvents) {\n\n          var result = fetchedEvents.slice();\n\n          result.sort(function (a, b) {\n            return parseDate(a.start) - parseDate(b.start);\n          });\n\n          return result;\n        }\n\n\n        function eventMatchesBasicFilters(event) {\n\n          if (state.country) {\n\n            if (event.country !== state.country) {\n              return false;\n            }\n          }\n\n          if (state.city) {\n\n            if (event.city !== state.city) {\n              return false;\n            }\n          }\n\n          if (state.format) {\n\n            if (event.format !== state.format) {\n              return false;\n            }\n          }\n\n          return true;\n        }\n\n\n        function eventMatchesMonth(event) {\n\n          var start = parseDate(event.start);\n          var end = parseDate(event.end);\n\n          if (state.month === 'upcoming') {\n            return end >= today;\n          }\n\n          if (state.month === 'year') {\n\n            if (start.getFullYear() > currentYear) {\n              return false;\n            }\n\n            if (end.getFullYear() < currentYear) {\n              return false;\n            }\n\n            return true;\n          }\n\n          var monthNumber = parseInt(state.month, 10);\n\n          var monthStart =\n            new Date(currentYear, monthNumber, 1);\n\n          var monthEnd =\n            new Date(currentYear, monthNumber + 1, 0);\n\n          if (start > monthEnd) {\n            return false;\n          }\n\n          if (end < monthStart) {\n            return false;\n          }\n\n          return true;\n        }\n\n\n        function getFilteredEvents() {\n\n          var result = [];\n\n          for (var i = 0; i < allEvents.length; i++) {\n\n            var event = allEvents[i];\n\n            if (!eventMatchesBasicFilters(event)) {\n              continue;\n            }\n\n            if (!eventMatchesMonth(event)) {\n              continue;\n            }\n\n            result.push(event);\n          }\n\n          result.sort(function (a, b) {\n            return parseDate(a.start) - parseDate(b.start);\n          });\n\n          return result;\n        }\n\n\n        function getCalendarEvents() {\n\n          var result = [];\n\n          for (var i = 0; i < allEvents.length; i++) {\n\n            var event = allEvents[i];\n\n            if (!eventMatchesBasicFilters(event)) {\n              continue;\n            }\n\n            var start = parseDate(event.start);\n            var end = parseDate(event.end);\n\n            var monthStart = new Date(\n              state.calendarDate.getFullYear(),\n              state.calendarDate.getMonth(),\n              1\n            );\n\n            var monthEnd = new Date(\n              state.calendarDate.getFullYear(),\n              state.calendarDate.getMonth() + 1,\n              0\n            );\n\n            if (start > monthEnd) {\n              continue;\n            }\n\n            if (end < monthStart) {\n              continue;\n            }\n\n            if (state.month === 'upcoming') {\n\n              if (end < today) {\n                continue;\n              }\n            }\n\n            if (state.month === 'year') {\n\n              if (start.getFullYear() > currentYear) {\n                continue;\n              }\n\n              if (end.getFullYear() < currentYear) {\n                continue;\n              }\n            }\n\n            if (\n              state.month !== 'upcoming'\n            ) {\n\n              if (\n                state.month !== 'year'\n              ) {\n\n                var selectedMonth =\n                  parseInt(state.month, 10);\n\n                if (\n                  state.calendarDate.getMonth() !==\n                  selectedMonth\n                ) {\n                  continue;\n                }\n              }\n            }\n\n            result.push(event);\n          }\n\n          return result;\n        }\n\n\n        var countrySelect =\n          document.getElementById('fm-country');\n\n        var citySelect =\n          document.getElementById('fm-city');\n\n        var formatSelect =\n          document.getElementById('fm-format');\n\n        var monthSelect =\n          document.getElementById('fm-month');\n\n\n        var monthNames = [\n          'January',\n          'February',\n          'March',\n          'April',\n          'May',\n          'June',\n          'July',\n          'August',\n          'September',\n          'October',\n          'November',\n          'December'\n        ];\n\n\n        for (var m = 0; m < 12; m++) {\n\n          var monthOption =\n            document.createElement('option');\n\n          monthOption.value = String(m);\n          monthOption.textContent = monthNames[m];\n\n          monthSelect.appendChild(monthOption);\n        }\n\n\n        function populateCountryOptions() {\n\n          var uniqueCountries = [];\n\n          for (var i = 0; i < allEvents.length; i++) {\n\n            if (allEvents[i].country) {\n\n              if (\n                uniqueCountries.indexOf(\n                  allEvents[i].country\n                ) === -1\n              ) {\n                uniqueCountries.push(\n                  allEvents[i].country\n                );\n              }\n            }\n          }\n\n          uniqueCountries.sort();\n\n          for (\n            var c = 0;\n            c < uniqueCountries.length;\n            c++\n          ) {\n\n            var countryOption =\n              document.createElement('option');\n\n            countryOption.value =\n              uniqueCountries[c];\n\n            countryOption.textContent =\n              uniqueCountries[c];\n\n            countrySelect.appendChild(\n              countryOption\n            );\n          }\n        }\n\n\n        function updateCityOptions() {\n\n          var selectedCountry =\n            state.country;\n\n          citySelect.innerHTML =\n            '<option value=\"\">All cities<\/option>';\n\n          var cities = [];\n\n\n          for (var i = 0; i < allEvents.length; i++) {\n\n            var event = allEvents[i];\n\n            if (event.city) {\n\n              var countryMatches = true;\n\n              if (selectedCountry) {\n\n                if (\n                  event.country !== selectedCountry\n                ) {\n                  countryMatches = false;\n                }\n              }\n\n              if (countryMatches) {\n\n                if (\n                  cities.indexOf(event.city) === -1\n                ) {\n                  cities.push(event.city);\n                }\n              }\n            }\n          }\n\n\n          cities.sort();\n\n\n          for (var j = 0; j < cities.length; j++) {\n\n            var option =\n              document.createElement('option');\n\n            option.value = cities[j];\n            option.textContent = cities[j];\n\n            citySelect.appendChild(option);\n          }\n\n\n          if (cities.indexOf(state.city) === -1) {\n            state.city = '';\n          }\n\n          citySelect.value = state.city;\n        }\n\n\n        function escapeHtml(value) {\n\n          return String(value)\n            .replace(\/&#038;\/g, '&amp;')\n            .replace(\/<\/g, '&lt;')\n            .replace(\/>\/g, '&gt;')\n            .replace(\/\"\/g, '&quot;')\n            .replace(\/'\/g, '&#039;');\n        }\n\n\n        function escapeAttribute(value) {\n\n          return String(value)\n            .replace(\/&\/g, '&amp;')\n            .replace(\/\"\/g, '&quot;')\n            .replace(\/<\/g, '&lt;')\n            .replace(\/>\/g, '&gt;');\n        }\n\n\n        function eventAnchorId(event) {\n\n          var slug = event.title\n            .toLowerCase()\n            .replace(\/[^a-z0-9]+\/g, '-')\n            .replace(\/(^-+|-+$)\/g, '');\n\n          return 'fm-event-' + slug + '-' + event.start;\n        }\n\n\n        function scrollToEventCard(anchorId) {\n\n          var target =\n            document.getElementById(anchorId);\n\n          if (!target) {\n            return;\n          }\n\n          target.scrollIntoView({\n            behavior: 'smooth',\n            block: 'center'\n          });\n\n          target.classList.add(\n            'fm-event-card-highlight'\n          );\n\n          window.setTimeout(function () {\n\n            target.classList.remove(\n              'fm-event-card-highlight'\n            );\n          }, 1800);\n        }\n\n\n        function buildMetaHtml(event) {\n\n          var locationText = '';\n\n          if (event.city) {\n\n            if (event.country) {\n\n              locationText =\n                event.city +\n                ', ' +\n                event.country;\n\n            } else {\n\n              locationText =\n                event.city;\n            }\n\n          } else {\n\n            locationText =\n              event.country;\n          }\n\n          return (\n            '<span class=\"fm-event-meta-item\">' +\n              escapeHtml(locationText) +\n            '<\/span>' +\n            '<span class=\"fm-event-meta-item\">' +\n              escapeHtml(event.format) +\n            '<\/span>' +\n            '<span class=\"fm-event-meta-item\">' +\n              'Ticket: ' + escapeHtml(event.ticket) +\n            '<\/span>'\n          );\n        }\n\n\n        function buildLinkHtml(event) {\n\n          if (!event.url) {\n            return '';\n          }\n\n          return (\n            '<a class=\"fm-event-link\" href=\"' +\n              escapeAttribute(event.url) +\n              '\" target=\"_blank\" rel=\"noopener\">' +\n              'Visit event \\u2192' +\n            '<\/a>'\n          );\n        }\n\n\n        function renderEventList() {\n\n          var container =\n            document.getElementById('fm-event-list');\n\n          var count =\n            document.getElementById('fm-results-count');\n\n          if (!container) {\n            return;\n          }\n\n          var events =\n            getFilteredEvents();\n\n\n          if (count) {\n\n            count.textContent =\n              events.length +\n              (\n                events.length === 1\n                  ? ' event found'\n                  : ' events found'\n              );\n          }\n\n\n          if (!events.length) {\n\n            container.innerHTML =\n              '<div class=\"fm-no-results\">' +\n              'No events match your selected filters.' +\n              '<\/div>';\n\n            return;\n          }\n\n\n          var html = '';\n\n\n          for (var i = 0; i < events.length; i++) {\n\n            var event = events[i];\n\n            html +=\n              '<article class=\"fm-event-card\" id=\"' +\n                eventAnchorId(event) +\n                '\">' +\n\n                '<div class=\"fm-event-card-date\">' +\n                  formatDateRange(event) +\n                '<\/div>' +\n\n                '<h3>' +\n                  escapeHtml(event.title) +\n                '<\/h3>' +\n\n                (\n                  event.description\n                    ? '<p class=\"fm-event-description\">' +\n                        escapeHtml(event.description) +\n                      '<\/p>'\n                    : ''\n                ) +\n\n                '<div class=\"fm-event-meta\">' +\n                  buildMetaHtml(event) +\n                '<\/div>' +\n\n                buildLinkHtml(event) +\n\n              '<\/article>';\n          }\n\n\n          container.innerHTML = html;\n        }\n\n\n        var mobileMediaQuery =\n          window.matchMedia('(max-width: 600px)');\n\n\n        function isMobileView() {\n          return mobileMediaQuery.matches;\n        }\n\n\n        var dayModalOverlay =\n          document.getElementById('fm-day-modal-overlay');\n\n        var dayModalTitle =\n          document.getElementById('fm-day-modal-title');\n\n        var dayModalBody =\n          document.getElementById('fm-day-modal-body');\n\n        var dayModalClose =\n          document.getElementById('fm-day-modal-close');\n\n        var dayModalReady = true;\n\n        if (!dayModalOverlay) {\n          dayModalReady = false;\n        }\n\n        if (!dayModalTitle) {\n          dayModalReady = false;\n        }\n\n        if (!dayModalBody) {\n          dayModalReady = false;\n        }\n\n        if (!dayModalClose) {\n          dayModalReady = false;\n        }\n\n        var dayModalLastFocused = null;\n\n\n        function handleModalKeydown(event) {\n\n          if (event.key === 'Escape') {\n            closeDayModal();\n          }\n        }\n\n\n        function openDayModal(date, events) {\n\n          if (!dayModalReady) {\n            return;\n          }\n\n          dayModalLastFocused =\n            document.activeElement;\n\n          dayModalTitle.textContent =\n            'Events on ' + formatDate(date);\n\n\n          var html = '';\n\n          for (var i = 0; i < events.length; i++) {\n\n            var event = events[i];\n\n            html +=\n              '<div class=\"fm-day-modal-event\">' +\n\n                '<div class=\"fm-event-card-date\">' +\n                  formatDateRange(event) +\n                '<\/div>' +\n\n                '<h3>' +\n                  escapeHtml(event.title) +\n                '<\/h3>' +\n\n                (\n                  event.description\n                    ? '<p class=\"fm-event-description\">' +\n                        escapeHtml(event.description) +\n                      '<\/p>'\n                    : ''\n                ) +\n\n                '<div class=\"fm-event-meta\">' +\n                  buildMetaHtml(event) +\n                '<\/div>' +\n\n                buildLinkHtml(event) +\n\n              '<\/div>';\n          }\n\n          dayModalBody.innerHTML = html;\n\n          dayModalOverlay.hidden = false;\n          document.body.style.overflow = 'hidden';\n\n          dayModalClose.focus();\n\n          document.addEventListener(\n            'keydown',\n            handleModalKeydown\n          );\n        }\n\n\n        function closeDayModal() {\n\n          if (!dayModalReady) {\n            return;\n          }\n\n          dayModalOverlay.hidden = true;\n          document.body.style.overflow = '';\n\n          document.removeEventListener(\n            'keydown',\n            handleModalKeydown\n          );\n\n          if (dayModalLastFocused) {\n            dayModalLastFocused.focus();\n          }\n        }\n\n\n        if (dayModalReady) {\n\n          dayModalClose.addEventListener(\n            'click',\n            closeDayModal\n          );\n\n          dayModalOverlay.addEventListener(\n            'click',\n            function (event) {\n\n              if (event.target === dayModalOverlay) {\n                closeDayModal();\n              }\n            }\n          );\n\n        } else if (window.console) {\n\n          if (console.warn) {\n\n            console.warn(\n              '[fm-events] day-detail modal markup is missing; ' +\n              'mobile day taps will show indicators only.'\n            );\n          }\n        }\n\n\n        function attachDayInteraction(cell, date, events) {\n\n          var label =\n            formatDate(date) +\n            ', ' +\n            events.length +\n            (\n              events.length === 1\n                ? ' event'\n                : ' events'\n            ) +\n            '. Press Enter for details.';\n\n          var indicator =\n            document.createElement('span');\n\n          indicator.className =\n            'fm-calendar-day-indicator';\n\n          if (events.length === 1) {\n\n            var dot =\n              document.createElement('span');\n\n            dot.className =\n              'fm-calendar-day-dot';\n\n            dot.setAttribute('aria-hidden', 'true');\n\n            indicator.appendChild(dot);\n\n          } else {\n\n            var badge =\n              document.createElement('span');\n\n            badge.className =\n              'fm-calendar-day-badge';\n\n            badge.textContent =\n              String(events.length);\n\n            badge.setAttribute('aria-hidden', 'true');\n\n            indicator.appendChild(badge);\n          }\n\n          cell.appendChild(indicator);\n\n          if (!dayModalReady) {\n            return;\n          }\n\n          cell.classList.add('fm-calendar-day-clickable');\n          cell.setAttribute('tabindex', '0');\n          cell.setAttribute('role', 'button');\n          cell.setAttribute('aria-haspopup', 'dialog');\n          cell.setAttribute('aria-label', label);\n\n          cell.addEventListener('click', function () {\n            openDayModal(date, events);\n          });\n\n          cell.addEventListener('keydown', function (event) {\n\n            if (event.key === 'Enter' || event.key === ' ') {\n              event.preventDefault();\n              openDayModal(date, events);\n            }\n          });\n        }\n\n\n        function renderCalendar() {\n\n          var grid =\n            document.getElementById('fm-calendar-grid');\n\n          var title =\n            document.getElementById('fm-calendar-title');\n\n          if (!grid) {\n            return;\n          }\n\n          var year =\n            state.calendarDate.getFullYear();\n\n          var month =\n            state.calendarDate.getMonth();\n\n\n          if (title) {\n\n            title.textContent =\n              monthNames[month] +\n              ' ' +\n              year;\n          }\n\n          grid.innerHTML = '';\n\n\n          var firstDay =\n            new Date(year, month, 1);\n\n          var mondayOffset =\n            firstDay.getDay();\n\n\n          if (mondayOffset === 0) {\n            mondayOffset = 7;\n          }\n\n          mondayOffset =\n            mondayOffset - 1;\n\n\n          var daysInMonth =\n            new Date(\n              year,\n              month + 1,\n              0\n            ).getDate();\n\n\n          for (\n            var empty = 0;\n            empty < mondayOffset;\n            empty++\n          ) {\n\n            var emptyCell =\n              document.createElement('div');\n\n            emptyCell.className =\n              'fm-calendar-day fm-calendar-day-empty';\n\n            grid.appendChild(emptyCell);\n          }\n\n\n          var calendarEvents =\n            getCalendarEvents();\n\n          var mobile =\n            isMobileView();\n\n\n          for (\n            var day = 1;\n            day <= daysInMonth;\n            day++\n          ) {\n\n            var cell =\n              document.createElement('div');\n\n            cell.className =\n              'fm-calendar-day';\n\n\n            var currentDate =\n              new Date(year, month, day);\n\n\n            if (\n              currentDate.getFullYear() ===\n              today.getFullYear()\n            ) {\n\n              if (\n                currentDate.getMonth() ===\n                today.getMonth()\n              ) {\n\n                if (\n                  currentDate.getDate() ===\n                  today.getDate()\n                ) {\n\n                  cell.className +=\n                    ' fm-calendar-day-today';\n                }\n              }\n            }\n\n\n            var number =\n              document.createElement('span');\n\n            number.className =\n              'fm-calendar-day-number';\n\n            number.textContent = day;\n\n            cell.appendChild(number);\n\n\n            var dayEvents = [];\n\n            for (\n              var e = 0;\n              e < calendarEvents.length;\n              e++\n            ) {\n\n              var calendarEvent =\n                calendarEvents[e];\n\n              var start =\n                parseDate(calendarEvent.start);\n\n              var end =\n                parseDate(calendarEvent.end);\n\n\n              if (currentDate < start) {\n                continue;\n              }\n\n              if (currentDate > end) {\n                continue;\n              }\n\n              dayEvents.push(calendarEvent);\n            }\n\n\n            if (mobile) {\n\n              if (dayEvents.length > 0) {\n                attachDayInteraction(\n                  cell,\n                  currentDate,\n                  dayEvents\n                );\n              }\n\n            } else {\n\n              for (\n                var d = 0;\n                d < dayEvents.length;\n                d++\n              ) {\n\n                var dayEvent =\n                  dayEvents[d];\n\n                var anchorId =\n                  eventAnchorId(dayEvent);\n\n                var link =\n                  document.createElement('a');\n\n                link.className =\n                  'fm-calendar-event';\n\n                link.href =\n                  '#' + anchorId;\n\n                link.addEventListener(\n                  'click',\n                  function (clickEvent) {\n\n                    clickEvent.preventDefault();\n\n                    scrollToEventCard(\n                      this.getAttribute(\n                        'data-anchor'\n                      )\n                    );\n                  }\n                );\n\n                link.setAttribute(\n                  'data-anchor',\n                  anchorId\n                );\n\n\n                var titleSpan =\n                  document.createElement('span');\n\n                titleSpan.className =\n                  'fm-calendar-event-title';\n\n                titleSpan.textContent =\n                  dayEvent.title;\n\n                link.appendChild(titleSpan);\n\n                cell.appendChild(link);\n              }\n            }\n\n\n            grid.appendChild(cell);\n          }\n\n\n          updateCalendarNavigation();\n        }\n\n\n        function updateCalendarNavigation() {\n\n          var previousButton =\n            document.getElementById(\n              'fm-prev-month'\n            );\n\n          var nextButton =\n            document.getElementById(\n              'fm-next-month'\n            );\n\n          if (!previousButton || !nextButton) {\n            return;\n          }\n\n\n          previousButton.disabled = false;\n          nextButton.disabled = false;\n\n\n          if (state.month === 'upcoming') {\n\n            var currentMonthStart =\n              new Date(\n                today.getFullYear(),\n                today.getMonth(),\n                1\n              );\n\n\n            if (\n              state.calendarDate <= currentMonthStart\n            ) {\n              previousButton.disabled = true;\n            }\n          }\n\n\n          if (state.month === 'year') {\n\n            if (\n              state.calendarDate.getFullYear() < currentYear\n            ) {\n              previousButton.disabled = true;\n            }\n\n            if (\n              state.calendarDate.getFullYear() > currentYear\n            ) {\n              nextButton.disabled = true;\n            }\n          }\n\n\n          if (\n            state.month !== 'upcoming'\n          ) {\n\n            if (\n              state.month !== 'year'\n            ) {\n\n              var selectedMonth =\n                parseInt(state.month, 10);\n\n\n              if (\n                state.calendarDate.getFullYear() !==\n                currentYear\n              ) {\n\n                previousButton.disabled = true;\n                nextButton.disabled = true;\n\n              } else {\n\n                if (\n                  state.calendarDate.getMonth() !==\n                  selectedMonth\n                ) {\n\n                  previousButton.disabled = true;\n                  nextButton.disabled = true;\n                }\n              }\n            }\n          }\n        }\n\n\n        function attachEventListeners() {\n\n          if (countrySelect) {\n\n            countrySelect.addEventListener(\n              'change',\n              function () {\n\n                state.country =\n                  this.value;\n\n                updateCityOptions();\n\n                renderEventList();\n                renderCalendar();\n              }\n            );\n          }\n\n\n          if (citySelect) {\n\n            citySelect.addEventListener(\n              'change',\n              function () {\n\n                state.city =\n                  this.value;\n\n                renderEventList();\n                renderCalendar();\n              }\n            );\n          }\n\n\n          if (formatSelect) {\n\n            formatSelect.addEventListener(\n              'change',\n              function () {\n\n                state.format =\n                  this.value;\n\n                renderEventList();\n                renderCalendar();\n              }\n            );\n          }\n\n\n          if (monthSelect) {\n\n            monthSelect.addEventListener(\n              'change',\n              function () {\n\n                state.month =\n                  this.value;\n\n\n                if (\n                  state.month === 'upcoming'\n                ) {\n\n                  state.calendarDate =\n                    new Date(\n                      today.getFullYear(),\n                      today.getMonth(),\n                      1\n                    );\n\n                } else {\n\n                  if (\n                    state.month === 'year'\n                  ) {\n\n                    state.calendarDate =\n                      new Date(\n                        currentYear,\n                        today.getMonth(),\n                        1\n                      );\n\n                  } else {\n\n                    state.calendarDate =\n                      new Date(\n                        currentYear,\n                        parseInt(state.month, 10),\n                        1\n                      );\n                  }\n                }\n\n\n                renderEventList();\n                renderCalendar();\n              }\n            );\n          }\n\n\n          var resetButton =\n            document.getElementById('fm-reset');\n\n          if (resetButton) {\n\n            resetButton.addEventListener(\n              'click',\n              function () {\n\n                state.country = '';\n                state.city = '';\n                state.format = '';\n                state.month = 'upcoming';\n\n\n                if (countrySelect) {\n                  countrySelect.value = '';\n                }\n\n                if (formatSelect) {\n                  formatSelect.value = '';\n                }\n\n                if (monthSelect) {\n                  monthSelect.value = 'upcoming';\n                }\n\n\n                updateCityOptions();\n\n\n                state.calendarDate =\n                  new Date(\n                    today.getFullYear(),\n                    today.getMonth(),\n                    1\n                  );\n\n\n                renderEventList();\n                renderCalendar();\n              }\n            );\n          }\n\n\n          var prevMonthButton =\n            document.getElementById('fm-prev-month');\n\n          if (prevMonthButton) {\n\n            prevMonthButton.addEventListener(\n              'click',\n              function () {\n\n                if (this.disabled) {\n                  return;\n                }\n\n\n                state.calendarDate =\n                  new Date(\n                    state.calendarDate.getFullYear(),\n                    state.calendarDate.getMonth() - 1,\n                    1\n                  );\n\n\n                renderCalendar();\n              }\n            );\n          }\n\n\n          var nextMonthButton =\n            document.getElementById('fm-next-month');\n\n          if (nextMonthButton) {\n\n            nextMonthButton.addEventListener(\n              'click',\n              function () {\n\n                if (this.disabled) {\n                  return;\n                }\n\n\n                state.calendarDate =\n                  new Date(\n                    state.calendarDate.getFullYear(),\n                    state.calendarDate.getMonth() + 1,\n                    1\n                  );\n\n\n                renderCalendar();\n              }\n            );\n          }\n\n\n          if (mobileMediaQuery.addEventListener) {\n\n            mobileMediaQuery.addEventListener(\n              'change',\n              renderCalendar\n            );\n\n          } else if (mobileMediaQuery.addListener) {\n\n            mobileMediaQuery.addListener(\n              renderCalendar\n            );\n          }\n        }\n\n\n        fetch(EVENTS_CSV_URL)\n          .then(function (response) {\n\n            if (!response.ok) {\n              throw new Error(\n                'Network response was not ok: ' +\n                response.status\n              );\n            }\n\n            return response.text();\n          })\n          .then(function (csvText) {\n\n            var rows = parseCsv(csvText);\n            var fetchedEvents = csvRowsToEvents(rows);\n\n            allEvents = buildAllEvents(fetchedEvents);\n\n            populateCountryOptions();\n            attachEventListeners();\n            updateCityOptions();\n            renderEventList();\n            renderCalendar();\n          })\n          .catch(function (fetchError) {\n\n            showFallback(fetchError);\n          });\n\n      }\n\n    });\n\n  })();\n  <\/script>\n\n<\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Why attend freelance events?<\/h2>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Networking<\/h3>\n\n\n\n<p>Meet fellow freelancers, potential clients and collaborators, exchange ideas and build relationships that can support your business long after the event.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Learning<\/h3>\n\n\n\n<p>Discover new tools, strategies and trends, and learn directly from freelancers and experts who understand the challenges of independent work.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">New opportunities<\/h3>\n\n\n\n<p>Events can open the door to new clients, partnerships, projects and communities while helping you stay connected to your industry.<\/p>\n<\/div><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">What are freelance events?<\/h3>\n\n\n\n<p>Freelance events include conferences, meetups, workshops, networking events and online sessions designed for freelancers, independent professionals and self-employed people.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Are there online events for freelancers?<\/h3>\n\n\n\n<p>Yes. Many freelance events take place online, making it possible to join from anywhere in the world. Use the format filter above to find online events.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">How can I find freelance events near me?<\/h3>\n\n\n\n<p>Use the country and city filters to find freelance events in a specific location. You can also browse the calendar to see when events take place.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">Are freelance events free?<\/h3>\n\n\n\n<p>Some events are free, while others require a ticket or registration. Check the individual event information for details.<\/p>\n<\/div><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Discover freelance events, conferences, meetups, workshops and networking opportunities around the world. Find events for freelancers and independent professionals by date, location, event type, topic or format \u2013 online, in person or hybrid. Whether you want to expand your network, learn new skills, meet potential clients or stay up to date with the future of [&hellip;]<\/p>\n","protected":false},"author":3156,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","footnotes":""},"class_list":["post-48833","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v23.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Freelance Events &amp; Conferences - Calendar 2026 | freelancermap<\/title>\n<meta name=\"description\" content=\"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Freelance Events &amp; Conferences - Calendar 2026 | freelancermap\" \/>\n<meta property=\"og:description\" content=\"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/\" \/>\n<meta property=\"og:site_name\" content=\"Freelancer Blog\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/freelancermapInternational\/\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-04T13:30:55+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@freelancer_INT\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/\",\"url\":\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/\",\"name\":\"Freelance Events & Conferences - Calendar 2026 | freelancermap\",\"isPartOf\":{\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#website\"},\"datePublished\":\"2026-09-03T09:15:41+00:00\",\"dateModified\":\"2026-09-04T13:30:55+00:00\",\"description\":\"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.freelancermap.com\/blog\/freelance-events\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.freelancermap.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Freelance Events &amp; Conferences 2026\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#website\",\"url\":\"https:\/\/www.freelancermap.com\/blog\/\",\"name\":\"Freelancer Blog\",\"description\":\"Tips &amp; Practical Advice for Freelancers and IT professionals\",\"publisher\":{\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.freelancermap.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#organization\",\"name\":\"freelancermap.com\",\"url\":\"https:\/\/www.freelancermap.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.freelancermap.com\/blog\/wp-content\/uploads\/2025\/02\/freelancermap-black-logo@4x.png\",\"contentUrl\":\"https:\/\/www.freelancermap.com\/blog\/wp-content\/uploads\/2025\/02\/freelancermap-black-logo@4x.png\",\"width\":1044,\"height\":145,\"caption\":\"freelancermap.com\"},\"image\":{\"@id\":\"https:\/\/www.freelancermap.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/freelancermapInternational\/\",\"https:\/\/x.com\/freelancer_INT\",\"https:\/\/www.linkedin.com\/company\/freelancermap-gmbh\/\",\"https:\/\/www.instagram.com\/freelancermap_int\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Freelance Events & Conferences - Calendar 2026 | freelancermap","description":"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/","og_locale":"en_US","og_type":"article","og_title":"Freelance Events & Conferences - Calendar 2026 | freelancermap","og_description":"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.","og_url":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/","og_site_name":"Freelancer Blog","article_publisher":"https:\/\/www.facebook.com\/freelancermapInternational\/","article_modified_time":"2026-09-04T13:30:55+00:00","twitter_card":"summary_large_image","twitter_site":"@freelancer_INT","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/","url":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/","name":"Freelance Events & Conferences - Calendar 2026 | freelancermap","isPartOf":{"@id":"https:\/\/www.freelancermap.com\/blog\/#website"},"datePublished":"2026-09-03T09:15:41+00:00","dateModified":"2026-09-04T13:30:55+00:00","description":"Discover freelance events, conferences, meetups and networking opportunities worldwide. Find events by location, date, and format.","breadcrumb":{"@id":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.freelancermap.com\/blog\/freelance-events\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.freelancermap.com\/blog\/freelance-events\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.freelancermap.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Freelance Events &amp; Conferences 2026"}]},{"@type":"WebSite","@id":"https:\/\/www.freelancermap.com\/blog\/#website","url":"https:\/\/www.freelancermap.com\/blog\/","name":"Freelancer Blog","description":"Tips &amp; Practical Advice for Freelancers and IT professionals","publisher":{"@id":"https:\/\/www.freelancermap.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.freelancermap.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.freelancermap.com\/blog\/#organization","name":"freelancermap.com","url":"https:\/\/www.freelancermap.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.freelancermap.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.freelancermap.com\/blog\/wp-content\/uploads\/2025\/02\/freelancermap-black-logo@4x.png","contentUrl":"https:\/\/www.freelancermap.com\/blog\/wp-content\/uploads\/2025\/02\/freelancermap-black-logo@4x.png","width":1044,"height":145,"caption":"freelancermap.com"},"image":{"@id":"https:\/\/www.freelancermap.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/freelancermapInternational\/","https:\/\/x.com\/freelancer_INT","https:\/\/www.linkedin.com\/company\/freelancermap-gmbh\/","https:\/\/www.instagram.com\/freelancermap_int\/"]}]}},"taxonomy_info":[],"featured_image_src_large":false,"author_info":{"display_name":"Jan Weickmann","author_link":"https:\/\/www.freelancermap.com\/blog\/author\/jan-weickmannsellwerk-de\/"},"comment_info":0,"_links":{"self":[{"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/pages\/48833"}],"collection":[{"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/users\/3156"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/comments?post=48833"}],"version-history":[{"count":33,"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/pages\/48833\/revisions"}],"predecessor-version":[{"id":48887,"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/pages\/48833\/revisions\/48887"}],"wp:attachment":[{"href":"https:\/\/www.freelancermap.com\/blog\/wp-json\/wp\/v2\/media?parent=48833"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}