<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Stavleak</title>
    <description>The latest articles on DEV Community by Stavleak (stavleak-hackathons).</description>
    <link>https://dev.to/stavleak-hackathons</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F15004%2F98e12672-eff0-4864-969e-efded9c1374c.png</url>
      <title>DEV Community: Stavleak</title>
      <link>https://dev.to/stavleak-hackathons</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stavleak-hackathons"/>
    <language>en</language>
    <item>
      <title>Git на хакатоне: как объединять код и не потерять демо</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Wed, 07 Oct 2026 11:48:35 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/git-na-khakatonie-kak-obiediniat-kod-i-nie-potieriat-diemo-576f</link>
      <guid>https://dev.to/stavleak-hackathons/git-na-khakatonie-kak-obiediniat-kod-i-nie-potieriat-diemo-576f</guid>
      <description>&lt;p&gt;На хакатоне Git помогает хранить общую историю проекта и соединять работу участников. Для небольшой команды достаточно простого порядка: основная ветка запускается, изменения делаются небольшими порциями, а перед объединением кто-то проверяет результат. Сложную модель ветвления лучше не вводить в середине соревнования.&lt;/p&gt;

&lt;p&gt;Git хранит версии файлов. GitHub и другие сервисы добавляют совместную работу, обсуждения и управление доступом. Команда может выбрать любой разрешённый инструмент, но всем нужно знать, где находится общий репозиторий и какая версия считается готовой для демонстрации.&lt;/p&gt;

&lt;h2&gt;
  
  
  Проверьте доступы до первой задачи
&lt;/h2&gt;

&lt;p&gt;Создайте репозиторий в аккаунте или организации, которые команда согласовала использовать. Добавьте участников с нужными правами и убедитесь, что приглашения приняты. Одно отправленное приглашение ещё не означает, что другой человек может получить и отправить изменения.&lt;/p&gt;

&lt;p&gt;Выберите видимость по условиям события и характеру материалов. Закрытый репозиторий может потребовать отдельного доступа жюри. Открытый репозиторий не должен содержать персональные данные, закрытые наборы или секретные ключи. Если организатор требует публикацию, подготовьте проект к ней до финального часа.&lt;/p&gt;

&lt;p&gt;Добавьте короткую инструкцию запуска и файл исключений для локальных настроек, временных файлов и установленных зависимостей. Образец конфигурации должен описывать необходимые параметры без настоящих секретов. Не полагайтесь на то, что случайно попавший в историю ключ исчезнет после удаления строки в новом изменении.&lt;/p&gt;

&lt;h2&gt;
  
  
  Договоритесь о рабочей основной ветке
&lt;/h2&gt;

&lt;p&gt;Пусть основная ветка содержит версию, которую можно запустить по инструкции. Незавершённые эксперименты сохраняйте отдельно. Команда должна понимать, что получение последней основной версии не превращает рабочее приложение в неизвестное состояние.&lt;/p&gt;

&lt;p&gt;Перед началом задачи получите актуальные изменения. Назовите ветку по работе, например &lt;code&gt;fix-upload-error&lt;/code&gt; или &lt;code&gt;add-results-screen&lt;/code&gt;. Название не обязано быть длинным; оно должно помогать связать изменение с задачей и человеком, который его делает.&lt;/p&gt;

&lt;p&gt;Не храните один огромный набор изменений до конца события. Если задача занимает несколько часов, выделяйте законченные шаги, которые можно проверить отдельно. Так проще заметить несовместимость раньше, чем несколько участников перестроят общие файлы.&lt;/p&gt;

&lt;h2&gt;
  
  
  Перед объединением объясните поведение
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/pull-requests/get-started/about-pull-requests" rel="noopener noreferrer"&gt;Документация GitHub о pull requests&lt;/a&gt; описывает предложение, обсуждение и объединение изменений. На хакатоне описание может быть коротким: что изменилось, как проверить и какое ограничение осталось. Для экрана полезен снимок, для обработки данных пример входа и выхода.&lt;/p&gt;

&lt;p&gt;Проверяющий проходит изменённый сценарий и смотрит, не затронуты ли общие границы. Автор лучше знает свою задачу, но другой участник может заметить недоступную переменную окружения или ошибку, которую локальные данные скрывали.&lt;/p&gt;

&lt;p&gt;Не требуйте длинной формальной проверки для каждой подписи. Сосредоточьтесь на изменениях, которые влияют на запуск, формат данных, доступы и демонстрацию. При этом даже маленький исправленный файл должен попасть в общую версию, а не остаться только в сообщении чата.&lt;/p&gt;

&lt;h2&gt;
  
  
  Разделяйте работу по файлам и интерфейсам
&lt;/h2&gt;

&lt;p&gt;Если двое одновременно меняют один большой компонент, конфликты вероятнее. Договоритесь о границах: один участник работает с загрузкой, другой с экраном результата. Общую схему данных согласуйте до начала параллельной работы.&lt;/p&gt;

&lt;p&gt;Изменение общей зависимости или структуры проекта сообщайте заранее. Обновление инструмента может затронуть запуск у всех участников. Во время короткого события у такой работы должен быть конкретный повод, а не желание привести весь репозиторий к личным предпочтениям.&lt;/p&gt;

&lt;p&gt;Когда конфликт всё же возник, не выбирайте автоматически «нашу» или «их» версию. Прочитайте обе правки и выясните, какое поведение каждая добавляла. Если смысл неясен, позовите автора. Случайно удалить чужую обработку ошибки легче, чем заметить потерю при быстром просмотре.&lt;/p&gt;

&lt;h2&gt;
  
  
  Проверяйте проект после соединения частей
&lt;/h2&gt;

&lt;p&gt;Отдельно успешные изменения могут не работать вместе. После объединения запустите проект и выполните главный пользовательский путь. Если есть подходящие автоматические проверки, запускайте их. Не добавляйте сложную систему тестирования только ради отчёта, если команда не успеет ею воспользоваться.&lt;/p&gt;

&lt;p&gt;Полезен короткий список ручной проверки: приложение открывается, ввод принимается, результат отображается, ошибка понятна. Список должен соответствовать вашему прототипу. Для устройства или обработки файлов понадобятся другие действия.&lt;/p&gt;

&lt;p&gt;Назначьте человека, который следит за общей сборкой. Это не означает, что только он имеет право объединять код. Его задача замечать, когда команда перестала понимать текущее состояние, и остановить новые изменения до восстановления рабочего сценария.&lt;/p&gt;

&lt;h2&gt;
  
  
  Сохраните версию для защиты
&lt;/h2&gt;

&lt;p&gt;Перед записью демо обозначьте готовое состояние тегом или другим понятным способом фиксации версии. Запишите, какой набор данных использовался и какие ограничения известны. Если после записи вы исправили поведение, проверьте, соответствует ли видео обновлённому проекту.&lt;/p&gt;

&lt;p&gt;Не переписывайте общую историю без согласования с командой. Принудительная отправка изменений может нарушить работу у остальных. Если случайно добавлены секреты, ограничьтесь не только очисткой файлов: отзовите скомпрометированный доступ по правилам соответствующего сервиса и сообщите ответственному участнику.&lt;/p&gt;

&lt;p&gt;Учебный пример сбоя: один разработчик добавил новый параметр, но не обновил инструкцию. На его компьютере всё работает, у докладчика запуск падает. Проверка на втором устройстве обнаруживает это до финала. Именно поэтому завершение задачи включает воспроизводимый запуск, а &lt;a href="https://info.stavleak.com/ru/guides/sdacha-proekta-na-hakaton" rel="noopener noreferrer"&gt;сдача проекта&lt;/a&gt; включает проверку доступа к нужной версии.&lt;/p&gt;

&lt;p&gt;Перед отправкой репозитория найдите требования выбранного события через &lt;a href="https://www.stavleak.com/ru/hackathons?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=git-komanda-hakaton" rel="noopener noreferrer"&gt;каталог Stavleak&lt;/a&gt;. Сверьте состав материалов и срок, до которого жюри нужен доступ.&lt;/p&gt;

</description>
      <category>git</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>AI hackathon: how to test a solution before the final pitch</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Wed, 07 Oct 2026 10:34:03 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/ai-hackathon-how-to-test-a-solution-before-the-final-pitch-ghk</link>
      <guid>https://dev.to/stavleak-hackathons/ai-hackathon-how-to-test-a-solution-before-the-final-pitch-ghk</guid>
      <description>&lt;p&gt;A team shows a successful model response. A judge changes the input text and gets a different result: a date disappears, an invented city appears or the request hangs. To investigate before the presentation, the organizer needs an evaluation protocol: which examples to test, what to compare the answers against and what to save after each run.&lt;/p&gt;

&lt;p&gt;Prepare it before development starts. Teams will know the evaluation format, and judges will receive material they can use to repeat a run and inspect an error. Below, we build that protocol for a single illustrative AI prototype.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Define the result you will test
&lt;/h2&gt;

&lt;p&gt;Our illustrative task is a service that extracts a city, an event format and a registration deadline from a short announcement. All announcements are fictional. The expected response is JSON with the fields &lt;code&gt;city&lt;/code&gt;, &lt;code&gt;format&lt;/code&gt; and &lt;code&gt;deadline&lt;/code&gt;. Missing values must be &lt;code&gt;null&lt;/code&gt;; the format can be &lt;code&gt;online&lt;/code&gt;, &lt;code&gt;offline&lt;/code&gt; or &lt;code&gt;hybrid&lt;/code&gt;; dates use &lt;code&gt;YYYY-MM-DD&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An example input is “Almaty, online. Register by 18 October 2026.” The expected values are &lt;code&gt;Almaty&lt;/code&gt;, &lt;code&gt;online&lt;/code&gt; and &lt;code&gt;2026-10-18&lt;/code&gt;. “Register tomorrow” without a publication date does not establish a definite deadline. The expected value in that case is &lt;code&gt;null&lt;/code&gt;, rather than a guess.&lt;/p&gt;

&lt;p&gt;Before the event, agree on accepted city name variants and rules for incomplete dates and ambiguous wording. Record them in the &lt;a href="https://info.stavleak.com/en/guides/brif-zadachi-hakatona" rel="noopener noreferrer"&gt;challenge brief&lt;/a&gt;. If two reviewers disagree about the correct answer, fix the task description and labels first.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Separate development from the held-out evaluation
&lt;/h2&gt;

&lt;p&gt;To demonstrate the protocol, we will use 30 artificial announcements: 18 are available to teams and 12 are held out. These are chosen illustrative conditions, not a recommended sample size or a universal ratio. This set is too small to establish performance on real incoming data.&lt;/p&gt;

&lt;p&gt;Teams use the available examples to refine the prompt, text processing and approach. If a team trains a model, its development data needs separate training and validation subsets. Keep the held-out test set for the final evaluation. &lt;a href="https://developers.google.com/machine-learning/crash-course/overfitting/dividing-datasets" rel="noopener noreferrer"&gt;Google explains this separation&lt;/a&gt;: choosing changes based on test answers turns the test into part of the tuning process.&lt;/p&gt;

&lt;p&gt;Appoint an owner for the held-out set. Until solutions are frozen, that person keeps inputs and expected answers separately from the teams. Group repeated announcements about the same event so their variants cannot land on opposite sides of the split. For our example, include Russian and Kazakh texts, missing fields and ambiguous dates chosen in advance.&lt;/p&gt;

&lt;p&gt;If a preprocessing step learns from data, fit it only on the training subset. The &lt;a href="https://scikit-learn.org/stable/common_pitfalls.html#data-leakage" rel="noopener noreferrer"&gt;scikit-learn documentation&lt;/a&gt; specifically warns about leakage through preprocessing. This also applies to steps that appear to be simple data preparation.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Prepare a simple baseline
&lt;/h2&gt;

&lt;p&gt;Build a baseline using a city dictionary, explicit event format indicators and recognition of fully specified dates. It also returns &lt;code&gt;null&lt;/code&gt; when information is insufficient. Freeze the dictionary version and rules before running the held-out evaluation.&lt;/p&gt;

&lt;p&gt;Test the baseline and the AI solution on identical inputs with identical comparison rules. This shows where the model performs better than a simple approach and where it introduces errors. &lt;a href="https://developers.google.com/machine-learning/guides/rules-of-ml" rel="noopener noreferrer"&gt;Google's ML guidance&lt;/a&gt; recommends starting with a simple solution and defining what to measure in advance.&lt;/p&gt;

&lt;p&gt;Check fields separately: city, format, deadline and handling of missing data. Save the count of correct answers alongside the number of fields checked. Do not combine them into a single “accuracy” figure if the number hides what you counted. Agree how these checks contribute to the overall assessment through the &lt;a href="https://info.stavleak.com/en/guides/kriterii-ocenki-hakatona" rel="noopener noreferrer"&gt;judging criteria&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Save a record of every run
&lt;/h2&gt;

&lt;p&gt;Before revealing the held-out inputs, freeze the solution commit and evaluation settings. Ask each team for a short run record containing these fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run identifier, commit and held-out dataset version.&lt;/li&gt;
&lt;li&gt;Model: name and available API version, or local checkpoint identifier.&lt;/li&gt;
&lt;li&gt;Prompt version, response schema and preprocessing rules.&lt;/li&gt;
&lt;li&gt;Runtime and dependency versions, generation settings and seed where applicable.&lt;/li&gt;
&lt;li&gt;Each example's identifier, raw response, status and run time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An API version does not always freeze an external service's internal state. Record what the provider allows you to pin and which conditions the team cannot control. Keep keys, tokens and real user data out of the record.&lt;/p&gt;

&lt;p&gt;Save responses before repairing their format. Otherwise, you cannot tell whether the model returned valid JSON or the application recovered it after an error. Record separately the processed result shown to the user.&lt;/p&gt;

&lt;p&gt;For a nondeterministic solution, agree the number of repeats in advance and save every result. Do not pick a successful run after evaluation. A fixed seed alone does not guarantee identical output: &lt;a href="https://docs.pytorch.org/docs/2.14/notes/randomness.html" rel="noopener noreferrer"&gt;PyTorch warns&lt;/a&gt; about differences across releases, platforms and CPU/GPU execution. For an external API, also account for its provider's limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Inspect errors example by example
&lt;/h2&gt;

&lt;p&gt;A judge needs a log with one record per input per run. Use this template: &lt;code&gt;run_id&lt;/code&gt;, &lt;code&gt;example_id&lt;/code&gt;, input text, expected fields, raw response, processed response, error type, run status and reviewer's note.&lt;/p&gt;

&lt;p&gt;In our example, distinguish a missing date, an invented city, invalid JSON, a correct &lt;code&gt;null&lt;/code&gt; and a missing response caused by a failure. Correctly declining to guess differs from an extraction error. An API access problem also needs a separate status.&lt;/p&gt;

&lt;p&gt;Do not remove stalled requests or missing responses from the report. Show the number of all planned examples, completed runs and failures. If a label is wrong, record the correction and recalculate both solutions using the same rule. Once a team tunes its solution against held-out errors, that set no longer provides an independent test of the next version.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Let a judge repeat the evaluation
&lt;/h2&gt;

&lt;p&gt;First, check whether the submitted package runs according to its instructions. For access, a fixed version and a fallback demo, use the &lt;a href="https://info.stavleak.com/en/guides/hackathon-submission-acceptance-checklist" rel="noopener noreferrer"&gt;submission acceptance checklist&lt;/a&gt;. Run unreviewed code in a disposable isolated environment without work secrets, using a separate test account.&lt;/p&gt;

&lt;p&gt;Then a judge selects examples from the agreed held-out set and repeats the run with the recorded settings. Compare the raw responses with the saved ones. If they differ, record the difference, the conditions and the team's explanation. A video documents the result shown, but does not replace this run.&lt;/p&gt;

&lt;p&gt;Before the pitch, give the judges the solution version, run record, baseline comparison and error log. State the size and composition of the evaluation, untested input types, external service dependencies and where a human must check the result. Judges can refer to specific responses and failures when the team explains what the prototype can already do and which evaluation it needs next.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>testing</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Your first hackathon: prepare well and get your project to a working demo</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Mon, 05 Oct 2026 20:21:02 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/your-first-hackathon-prepare-well-and-get-your-project-to-a-working-demo-44ao</link>
      <guid>https://dev.to/stavleak-hackathons/your-first-hackathon-prepare-well-and-get-your-project-to-a-working-demo-44ao</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fapi.stavleak.com%2Fstorage%2Fv1%2Frender%2Fimage%2Fpublic%2Fcovers%2Farticles%2Finfo-2026-09-29%2Fpervyy-hakaton-55e5560a4ef5.webp%3Fwidth%3D2560%26quality%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fapi.stavleak.com%2Fstorage%2Fv1%2Frender%2Fimage%2Fpublic%2Fcovers%2Farticles%2Finfo-2026-09-29%2Fpervyy-hakaton-55e5560a4ef5.webp%3Fwidth%3D2560%26quality%3D75" alt="Your first hackathon: prepare well and get your project to a working demo" width="1600" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go into your first hackathon with a task you can finish and explain. For a beginner, a good result is concrete: your team builds a working user flow, submits the required materials on time and understands what to improve. The judges decide who wins. The scope of your project, access to your files and readiness to demonstrate it depend largely on you.&lt;/p&gt;
&lt;p&gt;A hackathon is usually a time-limited event where participants build solutions and present the result. Requirements vary: some events expect working code; others accept research, a hardware prototype or a mockup. Preparation starts with the rules of your chosen event, rather than a list of popular technologies.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njr2v"&gt;Start with the participation rules&lt;/h2&gt;
&lt;p&gt;Open the event page and save the rules. Look for requirements covering age, team composition, place of residence and attendance in person. Check the start time, the submission deadline's time zone and the presentation format. A multi-day online round and a short in-person final may have different conditions.&lt;/p&gt;
&lt;p&gt;Write down exactly what you need to submit. A repository link, a deployed application, slides and a video each require different preparation. If the organizer expects a video, test your microphone and recording setup before the event. For a hardware project, ask about bringing equipment and the available power supply.&lt;/p&gt;
&lt;p&gt;Ask the organizer a specific question with enough context: "We want to use a library we wrote earlier. Do we need to list it separately?" Save the answer with the rules. A verbal agreement with a volunteer may never reach the person reviewing submissions.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njs2z"&gt;Set up your tools before building the solution&lt;/h2&gt;
&lt;p&gt;Before the event, install the tools you already know how to use. Check that you can sign in to your editor, repository and hosting service. Make a test screen recording, open it on another device and listen to the audio. None of this requires solving the competition task in advance.&lt;/p&gt;
&lt;p&gt;You can practise by building a small learning project. Whether you can reuse its code at the hackathon depends on the rules. Learning a tool, preparing a template and developing the competition entry ahead of time are different activities. If the boundary is unclear, ask before starting the work.&lt;/p&gt;
&lt;p&gt;Bring your charger and any adapters you need. For an in-person event, find out where you can rest and eat, how to reach the venue and when it closes. Do not make an unfamiliar laptop, someone else's account or temporary access to a paid service the foundation of your project.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njs33"&gt;Describe your skills honestly&lt;/h2&gt;
&lt;p&gt;"I can build two screens and connect a form to an existing API" is more useful to your team than "I'll handle the entire frontend." Explain what you have done independently, what you have followed in a tutorial and what you want to learn. This helps you choose a scope that does not rely on discovering a missing skill in the middle of the night.&lt;/p&gt;
&lt;p&gt;A participant without programming experience can research the problem, test the interface, prepare data, record the demo or write the project description. Each task needs a result the team can check. "Helping with the product" is hard to assess; "I'll prepare five examples of user errors by lunchtime" can go into the plan.&lt;/p&gt;
&lt;p&gt;If you are coming alone, find the team-matching channel and any meetup for prospective teammates. Introduce your skills, available time and the problem you want to work on. Do not promise to work all night just to get an invitation. Agree on realistic participation before the event rather than disappearing after the first stage.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njs37"&gt;Choose one path from problem to result&lt;/h2&gt;
&lt;p&gt;Consider a practice example: your team is building a consultation-booking tool. A complete product might include a calendar, payments, messages, reviews and user accounts. For the first demo, one path is enough: a person picks an available time, sends a request and receives a clear confirmation.&lt;/p&gt;
&lt;p&gt;Write down that path and sketch a few screens. Then identify the riskiest part. The calendar might look simple, but your team may not know how to retrieve available time slots. Test that dependency before designing an attractive landing page.&lt;/p&gt;
&lt;p&gt;In a &lt;a href="https://www.reddit.com/r/hackathon/comments/1rbq3qx/my_first_ever_online_hackathon_experience_was_an/" rel="noopener noreferrer nofollow"&gt;Reddit discussion about a first online hackathon&lt;/a&gt;, a participant describes a project that the rest of the team could not run. It is one person's account, but it suggests a useful check: at least two teammates should be able to run the working version well before the presentation.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njs3b"&gt;Agree on checkpoints&lt;/h2&gt;
&lt;p&gt;Replace a long feature list with a few visible results. First, the team can explain the problem. Next, the application completes the main flow using test data. Then another person checks the startup instructions, and the presenter rehearses the demo with a timer.&lt;/p&gt;
&lt;p&gt;Give each checkpoint an owner. They do not have to do all the work themselves, but they know its status and report blockers. Keep the discussion short: what is ready, what prevents the next step and which part of the idea you should drop.&lt;/p&gt;
&lt;p&gt;If you are behind, cut additional flows. Removing an optional filter is usually safer than skipping a link check or rehearsal. The &lt;a href="https://info.stavleak.com/ru/guides/plan-hakatona-48-chasov" rel="noopener noreferrer nofollow"&gt;48-hour hackathon plan, in Russian&lt;/a&gt; gives a more detailed example of time allocation. Adapt its intervals to your event's schedule.&lt;/p&gt;
&lt;h2 id="guide-section-bmung2njs3f"&gt;Start submitting before the final hour&lt;/h2&gt;
&lt;p&gt;Create a draft submission once you know the project's name and purpose. Update the description as you work. &lt;a href="https://help.devpost.com/article/125-tips-for-planning-your-project" rel="noopener noreferrer nofollow"&gt;Devpost's project-planning guide&lt;/a&gt; also recommends starting with the rules and a draft entry. Check the actual fields and submission confirmation process for your hackathon.&lt;/p&gt;
&lt;p&gt;Leave time to upload the video, process files and fix access. Open every link in a browser without signing in to your account. If the materials must remain private, test the organizer's approved access method for judges rather than making them public.&lt;/p&gt;
&lt;p&gt;After submitting, save the confirmation. Then have a short team debrief: which step was harder than expected, what did you learn and what small project could you build again on your own? That will help at your next hackathon more than a vague promise to "prepare better next time."&lt;/p&gt;
&lt;p&gt;For your first attempt, choose an event in the &lt;a href="https://www.stavleak.com/en/hackathons?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=pervyy-hakaton" rel="noopener noreferrer nofollow"&gt;Stavleak hackathon catalog&lt;/a&gt;: read the participation rules and check the application deadlines.&lt;/p&gt;

</description>
      <category>hackathon</category>
    </item>
    <item>
      <title>Check a parsed JSON response before rendering demo items</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Sat, 03 Oct 2026 02:40:29 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/check-a-parsed-json-response-before-rendering-demo-items-4n21</link>
      <guid>https://dev.to/stavleak-hackathons/check-a-parsed-json-response-before-rendering-demo-items-4n21</guid>
      <description>&lt;p&gt;Validate the structure of parsed JSON before your hackathon demo tries to render its items.&lt;/p&gt;

&lt;p&gt;A response can contain valid JSON and still have the wrong shape for your screen. A resource list might expect an object with an items array, while the endpoint returns null, an error object, or a string. Parsing alone does not prove that each item has the fields your component needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  State the small contract
&lt;/h2&gt;

&lt;p&gt;This illustrative contract requires an items array, and every item needs a string id and a string label. Reject unexpected shapes before updating the visible list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Expected an object with an items array&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Each item needs string id and label fields&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The helper returns only the fields this screen needs. It accepts an empty array as a valid empty result. That decision is part of this example's contract; change it if your workflow requires at least one item. It does not require unique IDs or a particular maximum number of items. Add those checks if your application depends on them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Know which check answers which question
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse" rel="noopener noreferrer"&gt;MDN's JSON.parse reference&lt;/a&gt; covers converting JSON text to a JavaScript value. That value can have several types. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray" rel="noopener noreferrer"&gt;MDN's Array.isArray reference&lt;/a&gt; describes the explicit array check. The null checks are deliberate because typeof null is object.&lt;/p&gt;

&lt;p&gt;In a fetch workflow, check the HTTP response, parse the body, validate this shape, then render. Give the user a readable failure message if the shape is wrong. Keep diagnostic details in an appropriate development log, without credentials or personal data. Client checks do not replace server-side validation or authorization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse the bad shapes
&lt;/h2&gt;

&lt;p&gt;Use fictional fixtures for null, an empty object, items as a string, a valid empty array, one valid item, and one item missing a label. Try a numeric ID to confirm that it fails this string-only contract. Verify that the previous valid screen is handled according to your chosen replacement behavior.&lt;/p&gt;

&lt;p&gt;Put the expected outcomes beside those fixtures in your README. The &lt;a href="https://info.stavleak.com/en" rel="noopener noreferrer"&gt;English Stavleak guides&lt;/a&gt; provide project preparation material to help your team document a reproducible demonstration.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Preserve plus signs and ampersands in demo search URLs</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Sat, 03 Oct 2026 02:35:15 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/preserve-plus-signs-and-ampersands-in-demo-search-urls-2ejb</link>
      <guid>https://dev.to/stavleak-hackathons/preserve-plus-signs-and-ampersands-in-demo-search-urls-2ejb</guid>
      <description>&lt;p&gt;Build search parameters from raw values with URLSearchParams so a plus sign or ampersand in the user's input survives the round trip.&lt;/p&gt;

&lt;p&gt;A prototype may work with a single word and fail with a team name such as C++ &amp;amp; design. Concatenating that value into a query string gives punctuation another job: an ampersand can separate parameters, and a plus sign in form-style query syntax can be decoded as a space. Rehearse a value that contains both characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the URL object serialize the value
&lt;/h2&gt;

&lt;p&gt;Use a URL object for the full address, then set the unencoded input value on its searchParams. Do not percent-encode the value first and then feed the encoded string to set.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C++ &amp;amp; design&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.org/search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shared&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This uses a reserved example domain and sends no request. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams" rel="noopener noreferrer"&gt;MDN's URLSearchParams documentation&lt;/a&gt; describes serialization and percent encoding. Supply decoded keys and values to its methods; serialization handles their representation in the query string.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test what your product actually reads
&lt;/h2&gt;

&lt;p&gt;Check the generated link and the restored value rather than judging the URL's visual appearance. A space may appear as a plus sign in serialized form. That representation can still restore to the correct space. A literal plus in the value needs to restore as a plus.&lt;/p&gt;

&lt;p&gt;The set method represents one value for the named parameter. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/set" rel="noopener noreferrer"&gt;MDN's set reference&lt;/a&gt; says it replaces additional values for that name. If your product supports multiple filters under the same key, decide that contract separately; do not silently reduce a multi-selection to one item.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try a useful fixture list
&lt;/h2&gt;

&lt;p&gt;Test C++, research &amp;amp; design, a value with spaces, Russian or Kazakh letters, an empty value, and a literal percent sign. Share each generated URL with a teammate and inspect the value after parsing it. Confirm that the UI also displays the restored selection rather than only parsing it into an unused variable.&lt;/p&gt;

&lt;p&gt;Keep query handling separate from HTML rendering. Correct URL serialization does not make arbitrary text safe to insert as HTML. Render text through your framework's normal text output, and validate any server-side meaning such as allowed filters independently.&lt;/p&gt;

&lt;p&gt;For an event to practise on, visit the &lt;a href="https://www.stavleak.com/en/hackathons" rel="noopener noreferrer"&gt;English Stavleak hackathon catalog&lt;/a&gt;. Read the selected event's requirements before shaping a prototype around it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Keep an older search response from replacing the latest results</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Sat, 03 Oct 2026 02:30:08 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/keep-an-older-search-response-from-replacing-the-latest-results-29ae</link>
      <guid>https://dev.to/stavleak-hackathons/keep-an-older-search-response-from-replacing-the-latest-results-29ae</guid>
      <description>&lt;p&gt;Give each search request a sequence number and only render the result that belongs to the latest search.&lt;/p&gt;

&lt;p&gt;A hackathon demo can look fine when typing slowly. During a presentation, a short query may take longer than the next query. If every response updates the screen, the older request can replace the results for the words currently in the input. The user then sees results that belong to a different question.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide which result owns the screen
&lt;/h2&gt;

&lt;p&gt;Keep the counter beside the search workflow. Increase it before starting each request, then compare the saved number after every asynchronous step that can finish later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;latestRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;latestRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Search failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;latestRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;latestRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;leaveSearch&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;latestRequest&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The endpoint and callbacks are illustrative. The counter invalidates both old successful results and old failures. Calling leaveSearch prevents pending requests from changing a screen that the user has left. Keep the counter scoped to this search instance so two unrelated search boxes do not invalidate each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guard loading as well as results
&lt;/h2&gt;

&lt;p&gt;Set loading for the new request and clear it only if that request is still current. If an old request clears loading while a newer request is pending, the screen can claim it has finished too early. Apply the same ownership check to any empty-state message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;MDN's Fetch guide&lt;/a&gt; explains that HTTP errors require a response-status check. A sequence number handles which result is current; it does not validate the response data, cancel traffic, or provide a timeout. You can add cancellation to save work while retaining a result-ownership check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Force the wrong completion order
&lt;/h2&gt;

&lt;p&gt;Use fictional fixtures or a local stub with two named queries. Make the first response finish after the second. Confirm that the second result stays visible. Repeat with the old request failing after the newer request succeeds. Then test the latest request failing and the user leaving while either is pending.&lt;/p&gt;

&lt;p&gt;Write down the input and expected visible result for each case. For more rehearsal material, open the &lt;a href="https://info.stavleak.com/en" rel="noopener noreferrer"&gt;English Stavleak guides&lt;/a&gt; and adapt the project preparation steps to your prototype.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Cancel a demo request when the user leaves its screen</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Sat, 03 Oct 2026 02:22:48 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/cancel-a-demo-request-when-the-user-leaves-its-screen-47c7</link>
      <guid>https://dev.to/stavleak-hackathons/cancel-a-demo-request-when-the-user-leaves-its-screen-47c7</guid>
      <description>&lt;p&gt;Cancel a screen's pending request when the user leaves it, and keep that deliberate cancellation out of the visible error state.&lt;/p&gt;

&lt;p&gt;A hackathon prototype may load a resource list when a panel opens. If the user closes the panel, the request can keep running. Define what should happen to loading, success, and failure after that panel is gone. Treat the request as belonging to that particular visit, rather than to every future visit to the panel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give each visit its own controller
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController" rel="noopener noreferrer"&gt;MDN's AbortController reference&lt;/a&gt; describes a controller that can abort asynchronous operations, including fetch requests and response-body consumption. Pass its signal to the operation you want to cancel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;openPanel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/demo-resources&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Resource request failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aborted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a lifecycle sketch. The endpoint is illustrative, and the caller supplies the real rendering functions. Keep error details suitable for a participant; do not print credentials or raw internal responses to the screen. Set the loading state when opening the panel and end it on the appropriate active success or failure path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distinguish leaving from failing
&lt;/h2&gt;

&lt;p&gt;The active flag prevents a finished operation from updating a closed panel. The signal stops work that supports cancellation. Create a new controller when reopening; a previously aborted signal stays aborted. Link the returned close function to the actual component or panel cleanup in your framework.&lt;/p&gt;

&lt;p&gt;Aborting a request does not guarantee that the server undid a write. This example concerns a read. A submission or payment needs a separate server contract for its outcome. Never tell a user that their submission vanished because the browser stopped waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse the lifecycle
&lt;/h2&gt;

&lt;p&gt;Try opening and immediately closing the panel, opening it again, allowing a successful read, and causing a genuine failure while it stays open. Also close after the response arrives. Verify that the second visit can load normally and that the closed panel never receives a late update.&lt;/p&gt;

&lt;p&gt;Keep these cases in the team's rehearsal notes. The &lt;a href="https://org.stavleak.com/en#toolkit" rel="noopener noreferrer"&gt;English Stavleak organizer toolkit&lt;/a&gt; provides checklists that you can adapt when planning a demonstration.&lt;/p&gt;

</description>
      <category>abotwrotethis</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Handle partial failures in optional widgets with Promise.allSettled()</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Sat, 03 Oct 2026 02:06:51 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/handle-partial-failures-in-optional-widgets-with-promiseallsettled-153d</link>
      <guid>https://dev.to/stavleak-hackathons/handle-partial-failures-in-optional-widgets-with-promiseallsettled-153d</guid>
      <description>&lt;p&gt;Use &lt;code&gt;Promise.allSettled()&lt;/code&gt; for independent optional widgets so one failed request does not hide the other widgets' successful results.&lt;/p&gt;

&lt;p&gt;A hackathon dashboard might show a required project result plus optional weather and resource cards. Decide which pieces the user needs to finish the task. An unavailable optional card should have its own failure state, while the required result should follow its own loading and failure contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep independent outcomes separate
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled" rel="noopener noreferrer"&gt;MDN documents &lt;code&gt;Promise.allSettled()&lt;/code&gt;&lt;/a&gt; as waiting for all input promises to settle and returning their outcomes in input order. Each outcome has either a fulfilled value or a rejection reason. Completion order does not change which slot belongs to which request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;widgets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resources&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weather&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unavailable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outcomes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allSettled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;outcomes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fulfilled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Could not load this optional widget.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These tasks are deterministic fixtures, not calls to an actual weather service. Replace the console output with a separate UI update for each named widget. Keep the name mapping beside the request list so later edits cannot swap two results accidentally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make real requests reject when appropriate
&lt;/h2&gt;

&lt;p&gt;When replacing the fixture with &lt;code&gt;fetch()&lt;/code&gt;, inspect &lt;code&gt;response.ok&lt;/code&gt; before parsing. &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;MDN's Fetch guide&lt;/a&gt; explains why an HTTP error can otherwise appear as a fulfilled response. &lt;code&gt;allSettled()&lt;/code&gt; classifies promise outcomes; it does not decide whether an HTTP response meets your application's success contract.&lt;/p&gt;

&lt;p&gt;It also does not provide a timeout or cancel requests. A request that remains pending keeps the combined wait pending. Design request cancellation and time limits explicitly for the real services you use. If widgets need to appear as soon as each completes, update them individually instead of waiting for the entire group to finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test partial availability
&lt;/h2&gt;

&lt;p&gt;Rehearse both successful widgets, each single failure, and both failures. Confirm that a failed card names its own problem and that successful content remains visible. Add one deliberately slow fixture to see whether the loading state matches your intended experience.&lt;/p&gt;

&lt;p&gt;Keep a required submission request outside this optional-widget group when its failure must stop the workflow. Write that dependency in the README. For planning a rehearsal, the &lt;a href="https://org.stavleak.com/en#toolkit" rel="noopener noreferrer"&gt;English Stavleak organizer toolkit&lt;/a&gt; offers checklists and templates that you can adapt to your event.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Validate demo uploads beyond the file input accept attribute</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Fri, 02 Oct 2026 02:52:02 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/validate-demo-uploads-beyond-the-file-input-accept-attribute-35fa</link>
      <guid>https://dev.to/stavleak-hackathons/validate-demo-uploads-beyond-the-file-input-accept-attribute-35fa</guid>
      <description>&lt;p&gt;Treat a file input's &lt;code&gt;accept&lt;/code&gt; attribute as a picker hint and validate the selected upload separately before a hackathon demo depends on it.&lt;/p&gt;

&lt;p&gt;A prototype that requests a CSV can still receive the wrong kind of file. The browser's chooser helps the user find an expected format, but the application needs its own rules for size, contents, and what happens after rejection. A successful chooser interaction does not prove the file can be processed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Describe the expected selection
&lt;/h2&gt;

&lt;p&gt;Use a visible label and a narrow hint that matches the formats your implementation supports. This example names CSV explicitly; it does not promise to import spreadsheets or every text file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"demo-data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Demo data (CSV)&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"demo-data"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;accept=&lt;/span&gt;&lt;span class="s"&gt;".csv,text/csv"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept" rel="noopener noreferrer"&gt;MDN's &lt;code&gt;accept&lt;/code&gt; documentation&lt;/a&gt; states that the attribute guides selection rather than validating the file type. It also calls for server-side validation. A filename extension or client-provided media type alone is not a trustworthy security boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the product contract
&lt;/h2&gt;

&lt;p&gt;For a local rehearsal, write down the accepted column names, encoding assumptions, and a size limit that your team has actually chosen. Explain that limit in the UI. Do not invent a universal CSV maximum or silently accept a file that the parser cannot handle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maximumBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Choose a file first.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;maximumBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;File exceeds this demo limit.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helper only checks presence and size. It does not validate CSV syntax, required columns, or whether the upload is safe. Use a CSV parser that handles the dialect your product supports, and validate the parsed structure before adding data to the visible results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse rejection without losing the user's work
&lt;/h2&gt;

&lt;p&gt;Prepare fictional fixtures for a valid file, a file missing a required column, a malformed file, an oversized file, and an empty file. Try cancelling the chooser as well. Keep the previous valid data visible until the replacement passes your checks, if that matches the product's intended behavior.&lt;/p&gt;

&lt;p&gt;For every rejected fixture, show a specific reason and let the user choose another file. Confirm that the loading state ends, the error is readable, and the next valid upload succeeds. A presenter should not need to reload the entire app after one mistaken selection.&lt;/p&gt;

&lt;p&gt;Apply authorization and validation again wherever files reach the server. Keep the demo fixtures free of real identities. The &lt;a href="https://www.stavleak.com/en/hackathons" rel="noopener noreferrer"&gt;English Stavleak hackathon catalog&lt;/a&gt; can help you find a challenge; read that event's data rules before bringing any external dataset into the project.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Format event times with an explicit Intl.DateTimeFormat time zone</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Fri, 02 Oct 2026 02:50:30 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/format-event-times-with-an-explicit-intldatetimeformat-time-zone-2bb</link>
      <guid>https://dev.to/stavleak-hackathons/format-event-times-with-an-explicit-intldatetimeformat-time-zone-2bb</guid>
      <description>&lt;p&gt;Pass an explicit &lt;code&gt;timeZone&lt;/code&gt; to &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; when a demo must display the same event time on teammates' computers.&lt;/p&gt;

&lt;p&gt;The locale controls presentation conventions, while the time zone determines which local clock time represents an instant. Choosing English labels does not specify the event's zone. During a rehearsal, two people can format the same timestamp and see different hours if their runtime defaults differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with an unambiguous instant
&lt;/h2&gt;

&lt;p&gt;Use a timestamp that includes an offset, such as the fictional example below. Keep the event's actual zone as separate configuration. This example uses UTC to make the formatting behavior easy to inspect and does not announce a real event deadline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-10-02T12:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formatter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;dateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timeZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UTC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;instant&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolvedOptions&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;timeZone&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UTC&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat" rel="noopener noreferrer"&gt;MDN's &lt;code&gt;Intl.DateTimeFormat&lt;/code&gt; reference&lt;/a&gt; shows explicit time zone options and locale-sensitive formatting. The output is human-facing text. Keep the original timestamp for storage and comparisons rather than parsing the formatted label back into a date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the zone visible to the reader
&lt;/h2&gt;

&lt;p&gt;A time such as “12:00” needs context on a schedule card or confirmation screen. Include a visible label for the configured zone. If you want the formatter to include a zone name, use individual date and time components with &lt;code&gt;timeZoneName&lt;/code&gt; rather than mixing that component option into this style-based example.&lt;/p&gt;

&lt;p&gt;When an organizer changes the event zone, update the configuration and the explanatory label together. Do not change the stored instant merely to make the displayed hour look familiar. First establish whether the change concerns presentation or the actual scheduled moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the formatting contract
&lt;/h2&gt;

&lt;p&gt;Run the same instant on two machines with different system zones and compare the displayed event time. Then try an instant near midnight so a date change becomes visible. Confirm that the screen and any copied confirmation text use the same zone setting.&lt;/p&gt;

&lt;p&gt;Avoid asserting an entire localized string in a portable test unless you control the runtime data and formatting environment. The resolved zone and selected date/time parts are more targeted checks. Leave room for different punctuation and translated month names.&lt;/p&gt;

&lt;p&gt;Record the configured zone next to your fixture timestamp so a teammate can reproduce the result. If you are building an event schedule, the &lt;a href="https://org.stavleak.com/en#toolkit" rel="noopener noreferrer"&gt;English Stavleak organizer toolkit&lt;/a&gt; provides planning materials; confirm the real event time with its organizer before replacing the fictional fixture.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Check Fetch HTTP status before treating a demo request as successful</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Fri, 02 Oct 2026 02:41:48 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/check-fetch-http-status-before-treating-a-demo-request-as-successful-34ph</link>
      <guid>https://dev.to/stavleak-hackathons/check-fetch-http-status-before-treating-a-demo-request-as-successful-34ph</guid>
      <description>&lt;p&gt;Check &lt;code&gt;response.ok&lt;/code&gt; before parsing a Fetch response so an HTTP error cannot enter the success path of your hackathon demo.&lt;/p&gt;

&lt;p&gt;A request can reach the server and receive a 404 or 500 response while the JavaScript promise still fulfills. If a prototype treats every fulfilled promise as successful data, the UI may display an error document as a result or fail later during JSON parsing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate response status from transport failure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;MDN's Fetch guide&lt;/a&gt; explains that HTTP error responses do not automatically reject &lt;code&gt;fetch()&lt;/code&gt;. The application must inspect the status. A rejection means the request could not complete normally, but it does not identify one specific cause such as being offline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helper also lets a JSON parsing failure reject the returned promise. It assumes a successful endpoint returns JSON. A 204 response with no body needs a different branch; document that contract instead of applying this helper to every endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the interface an honest next step
&lt;/h2&gt;

&lt;p&gt;Keep the technical error useful for development while showing a short message the presenter can act on. For a read-only lookup, that might be “Could not load the result. Try again.” Avoid claiming the internet is down when you have only observed a failed request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;readJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/demo-result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;renderResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;renderRetryMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rendering functions here are application placeholders. Replace them with your actual UI updates. Do not put tokens, private response bodies, or personal data into the displayed message or a public rehearsal recording.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test three different failures
&lt;/h2&gt;

&lt;p&gt;Use a controlled local fixture to return a 404 JSON response, a 500 response, and a 200 response containing malformed JSON. Confirm that none shows a successful result. Then simulate a rejected request in your test double and confirm the same recovery control remains available.&lt;/p&gt;

&lt;p&gt;Also test a valid 200 JSON response. Otherwise a change that sends every case to the failure screen can appear to fix the original problem. Check that the loading indicator stops in both success and failure, and that a retry starts a new request rather than replaying stale success content.&lt;/p&gt;

&lt;p&gt;For a live pitch, write down the endpoint and its expected response format with the teammate running the backend. Organizer checklists in the &lt;a href="https://org.stavleak.com/en#toolkit" rel="noopener noreferrer"&gt;English Stavleak toolkit&lt;/a&gt; can help structure the rehearsal; the event's own submission instructions still decide what you must deliver.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
    <item>
      <title>Read repeated URL query parameters with URLSearchParams.getAll()</title>
      <dc:creator>Stavleak</dc:creator>
      <pubDate>Fri, 02 Oct 2026 02:39:51 +0000</pubDate>
      <link>https://dev.to/stavleak-hackathons/read-repeated-url-query-parameters-with-urlsearchparamsgetall-26ac</link>
      <guid>https://dev.to/stavleak-hackathons/read-repeated-url-query-parameters-with-urlsearchparamsgetall-26ac</guid>
      <description>&lt;p&gt;Read repeated query parameters with &lt;code&gt;URLSearchParams.getAll()&lt;/code&gt; before a hackathon demo loses one of the user's selections.&lt;/p&gt;

&lt;p&gt;A prototype might send two selected skills as &lt;code&gt;skill=design&amp;amp;skill=javascript&lt;/code&gt;. A teammate who reads only the first value can show an incomplete summary even though the browser sent both. Make the representation part of the interface contract before connecting the form to the results screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the complete list
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/getAll" rel="noopener noreferrer"&gt;MDN documents &lt;code&gt;getAll()&lt;/code&gt;&lt;/a&gt; as returning an array of strings for the requested key. A missing key produces an empty array. Use that shape consistently instead of switching between a string and an array depending on how many selections exist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skill=design&amp;amp;skill=javascript&amp;amp;note=a%2Bb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;design&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;missing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a hackathon registration prototype, document whether repeated values preserve a deliberate ranking or represent an unordered selection. That choice belongs to your application. Do not silently remove duplicates if two entries can carry different meaning elsewhere in the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the same representation
&lt;/h2&gt;

&lt;p&gt;Keep the serializer beside the parser during the rehearsal. Start with an empty parameter object and append one entry for each selected value. This example uses fictional skills rather than an event's actual registration rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;skill&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skill&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams" rel="noopener noreferrer"&gt;&lt;code&gt;URLSearchParams&lt;/code&gt; reference&lt;/a&gt; explains encoding and iteration. Prefer its serializer to manually joining unescaped user text with ampersands. Decide which values your server accepts separately; correctly encoded input can still be invalid for the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rehearse the boundary cases
&lt;/h2&gt;

&lt;p&gt;Run the demo with no selections, one selection, two different selections, and the same value twice. Compare the visible summary with the parsed array. Add a value containing a space, then one containing a literal plus sign through &lt;code&gt;append()&lt;/code&gt;, and check the round trip.&lt;/p&gt;

&lt;p&gt;Ask the teammate implementing the receiving endpoint to repeat those cases. Save the expected representation in the README so the next person does not replace it with a comma-separated string during the final hour. Keep private contact details out of URLs, which people may copy into screenshots and browser history.&lt;/p&gt;

&lt;p&gt;When choosing a project to rehearse, browse the &lt;a href="https://www.stavleak.com/en/hackathons" rel="noopener noreferrer"&gt;English Stavleak hackathon catalog&lt;/a&gt;, then check the selected event's own requirements before adapting the example.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>hackathon</category>
      <category>abotwrotethis</category>
    </item>
  </channel>
</rss>
