<?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: AmeliaDrag</title>
    <description>The latest articles on DEV Community by AmeliaDrag (@ameliadrag).</description>
    <link>https://dev.to/ameliadrag</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%2Fuser%2Fprofile_image%2F4245688%2Fa193546f-e170-4ac5-bcd6-e322ed2c318d.png</url>
      <title>DEV Community: AmeliaDrag</title>
      <link>https://dev.to/ameliadrag</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ameliadrag"/>
    <language>en</language>
    <item>
      <title>Buburu: A Women's Safety App Built in 48 Hours, Born From a Walk We Never Forgot.</title>
      <dc:creator>AmeliaDrag</dc:creator>
      <pubDate>Sun, 15 Nov 2026 10:32:38 +0000</pubDate>
      <link>https://dev.to/ameliadrag/buburu-a-womens-safety-app-built-in-48-hours-born-from-a-walk-we-never-forgot-4j9m</link>
      <guid>https://dev.to/ameliadrag/buburu-a-womens-safety-app-built-in-48-hours-born-from-a-walk-we-never-forgot-4j9m</guid>
      <description>&lt;p&gt;This is a submission for the MLH x DEV Writing Challenge.&lt;/p&gt;

&lt;p&gt;Buburu is an app for women’s safety that we decided to create to help women feel safe during their walks. We named the app &lt;strong&gt;Buburu&lt;/strong&gt; and its users &lt;strong&gt;ladybugs&lt;/strong&gt; because there is not only one ladybug who saves Paris: we are all ladybugs who can save the world. The interface follows that theme, and users can choose their own colors. 🐞&lt;/p&gt;

&lt;p&gt;We built the frontend with &lt;strong&gt;Java Script&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt; and &lt;strong&gt;Leaflet&lt;/strong&gt;, used &lt;strong&gt;Java, Spring Boot&lt;/strong&gt; for the backend, and stored our data in &lt;strong&gt;H2&lt;/strong&gt;. &lt;strong&gt;Auth0&lt;/strong&gt; handled sign-in, &lt;strong&gt;OpenStreetMap&lt;/strong&gt; provided the map, and &lt;strong&gt;OpenRouteService&lt;/strong&gt; calculated walking routes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AmeliaDrag/UNIHACK2026" rel="noopener noreferrer"&gt;https://github.com/AmeliaDrag/UNIHACK2026&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5dfr7flow7ksaxoa8jbw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5dfr7flow7ksaxoa8jbw.jpeg" alt=" " width="384" height="817"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1z4bxcxszkfofbaj5x1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1z4bxcxszkfofbaj5x1.jpeg" alt=" " width="388" height="807"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwuewddimquokxikxka2k.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwuewddimquokxikxka2k.jpeg" alt=" " width="398" height="824"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fze4d8p59t4rjdvbebaka.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fze4d8p59t4rjdvbebaka.jpeg" alt=" " width="382" height="816"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F34z2eaxhzkg49cgbzb9e.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F34z2eaxhzkg49cgbzb9e.jpeg" alt=" " width="800" height="1422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we built it&lt;/strong&gt;&lt;br&gt;
During our first week at university in Timișoara, we went out to explore the city and get to know each other. A naked man started following us. A stranger who was walking his dog noticed what was happening, stayed with us, and walked us home.&lt;br&gt;
That story had a happy ending only because the man walking his dog had good intentions. It could have been much worse, and for many women it is. In a survey of 1,694 women in Romania aged 18 to 65, 95% said they had been harassed on the street (as reported by F-Sides). Across the EU, about three in ten women aged 18 to 29 (28.3%) reported having experienced stalking in 2021 (Eurostat).&lt;br&gt;
After that night, I wanted an app where my mom, my friends, and the girls I know could look out for each other. At our hackathon, we had 48 hours to build a first version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How we built it, step by step&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Sketch the flows.&lt;/em&gt;&lt;/strong&gt; We drew the main screens on paper and worked out how people would move between the map, reporting, the account page, and SOS.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Split the work.&lt;/em&gt;&lt;/strong&gt; One teammate owned the Java backend. We divided the frontend by screen so we could work in parallel.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Prototype the interface.&lt;/em&gt;&lt;/strong&gt; After the team discussed what each screen should do, I laid out the pages. We used Canva, Figma, and AI tools to explore the design and develop the ladybug theme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Build the screens and connect the API.&lt;/em&gt;&lt;/strong&gt; We used React 18 with JSX, Vite for local development and builds, Leaflet and React Leaflet for the map, the Auth0 React SDK for sign-in, and plain CSS for styling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6aapam8waz9gm1qbl1ra.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6aapam8waz9gm1qbl1ra.jpeg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The backend, in the words of the teammate who built it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I built the backend with &lt;strong&gt;Java 21 and Spring Boot&lt;/strong&gt;, using &lt;strong&gt;H2&lt;/strong&gt; to store users, trusted contacts, incident reports, and SOS alerts. Each report stores its coordinates, type, and expiry time. Trusted contacts are directional. If Ana invites Maria and Maria accepts, Maria receives Ana’s SOS alerts. For Ana to receive Maria’s alerts, Maria needs to invite her separately.&lt;/p&gt;

&lt;p&gt;For each walking route request, the backend queries active reports and converts their circular map zones into polygons for &lt;strong&gt;OpenRouteService&lt;/strong&gt;. Computing those polygons on demand means expired reports are automatically excluded from the next request. If no route is found, the backend retries once without the avoidance polygons and returns &lt;code&gt;avoidsReports: false&lt;/code&gt;, which the frontend uses to warn that the fallback route may cross reported areas.&lt;/p&gt;

&lt;p&gt;For the demo, the backend loaded a local &lt;strong&gt;OpenStreetMap&lt;/strong&gt; export at startup to populate the 24/7 shop layer without a live data request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwjnbwd4jey9w0bv0saov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwjnbwd4jey9w0bv0saov.png" alt=" " width="798" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The hardest bug: Debugging the sign-in flow&lt;/strong&gt;&lt;br&gt;
Clicking Sign in sent us back to the first page. In one attempt, the Account screen displayed Invalid state. While sign-in was broken, we couldn't test incident submission or SOS through an authenticated account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwokfg76bqyd73o2ehkyh.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwokfg76bqyd73o2ehkyh.jpeg" alt=" " width="341" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We first added type="button" to rule out an accidental form submission. The buttons were already outside a form, so we moved on to the app’s session state and the Auth0 callback.&lt;/p&gt;

&lt;p&gt;Stale guest state. A leftover guest flag could hide the sign-in controls. The app now checks that guest mode is actually enabled before honoring the flag.&lt;/p&gt;

&lt;p&gt;Two callback handlers. Both main.jsx and Auth0Provider handled the redirect. We removed the one in main.jsx so the provider owns the callback.&lt;/p&gt;

&lt;p&gt;API authorization. We fixed the app’s API authorization in the Auth0 dashboard and surfaced sign-in errors in the UI.&lt;/p&gt;

&lt;p&gt;Stale callback parameters. A failed attempt could leave error and state in the URL. We now clear them after handling the error, so a reload starts from a clean URL.&lt;/p&gt;

&lt;p&gt;Why “Invalid state”? Before redirecting to Auth0, the SDK stores a random state value (together with the PKCE verifier) in the browser. On return, it compares the state in the URL with the stored one and throws Invalid state if they don’t match. The stored value is consumed by the first successful callback, so a second handler, or an old ?code=…&amp;amp;state=… replayed on reload, finds nothing to match. Authorization failures look different: Auth0 redirects back with error and error_description, and if the app never reads them, it just looks like a silent redirect.&lt;/p&gt;

&lt;p&gt;The fix (simplified sketch, variable names are illustrative): let Auth0Provider handle the callback alone, read error / error_description from the URL, show them in the UI, then strip all callback parameters with history.replaceState.&lt;/p&gt;

&lt;p&gt;We also saw API requests fail during troubleshooting. The backend needed its auth profile to start, so we treated backend startup and the browser callback as separate checks.&lt;/p&gt;

&lt;p&gt;For a clean retest, we opened the app in an incognito window and clicked Sign in once from the Account tab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other issues we ran into&lt;/strong&gt;&lt;br&gt;
We resolved two Git merge conflicts by choosing a version as the starting point and applying the changes we needed to keep. We also had to align local . e n v configuration across the team and address a layout issue that left the SOS screen taking up only half the available space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hackathon Experience&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;UniHack Timișoara was an experience I’d happily do again. I loved seeing how much we could learn from each other in one weekend. Working with technologies like Auth0 and OpenRouteService gave us a chance to learn by trying things out, asking questions, and figuring out what to do when something broke. I left tired, proud of our team, and already excited for the next hackathon. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's next&lt;/strong&gt;&lt;br&gt;
We want to let users rate how safe they feel walking alone in different areas.If you have ever walked home with your keys between your fingers, this one is for you. What feature would make you feel safer? Tell us in the comments.&lt;/p&gt;

&lt;p&gt;Built by Drăgănescu Amelia-Rahela, Drăgănescu Daniela-Estera, Raț Răzvan-Andrei, and Cîmpan Miriam at UNIHACK TIMIȘOARA 2026.&lt;/p&gt;

</description>
      <category>mlhacks</category>
      <category>devchallenge</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
