<?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: Kingsmichaei</title>
    <description>The latest articles on DEV Community by Kingsmichaei (@kingsmichaei).</description>
    <link>https://dev.to/kingsmichaei</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%2F3821835%2F717e585e-93da-449d-af45-e64874e3e550.jpeg</url>
      <title>DEV Community: Kingsmichaei</title>
      <link>https://dev.to/kingsmichaei</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kingsmichaei"/>
    <language>en</language>
    <item>
      <title>OyaGo: Asking for Bus Directions in Lagos, Where No Map Knows the Routes</title>
      <dc:creator>Kingsmichaei</dc:creator>
      <pubDate>Fri, 09 Oct 2026 06:38:44 +0000</pubDate>
      <link>https://dev.to/kingsmichaei/oyago-asking-for-bus-directions-in-lagos-where-no-map-knows-the-routes-4pia</link>
      <guid>https://dev.to/kingsmichaei/oyago-asking-for-bus-directions-in-lagos-where-no-map-knows-the-routes-4pia</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OyaGo&lt;/strong&gt; is a web app that tells you how to get around Lagos, Nigeria by public transport. You ask in plain English or Nigerian Pidgin, and it gives you bus-by-bus directions written the way a local would give them.&lt;br&gt;
&lt;code&gt;hint:&lt;/code&gt; &lt;code&gt;Oya Go means "Let's Go" in Nigerian Pidgin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The problem, for anyone who has never been to Lagos&lt;/p&gt;

&lt;p&gt;Lagos is one of the largest cities in Africa, with well over 15 million people. Most of them move around on a transport system that no map app really understands:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Danfo: yellow minibuses that run fixed routes but have no printed timetable or route map. A conductor hangs out of the door shouting the destination.&lt;/p&gt;

&lt;p&gt;BRT: a bus rapid transit system with dedicated lanes on some major roads.&lt;/p&gt;

&lt;p&gt;Keke (motorised tricycles) and okada (motorcycle taxis) for the last stretch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Directions here are passed on by word of mouth, and they sound like this:&lt;/p&gt;

&lt;p&gt;"Enter Oshodi bus. When you reach under-bridge, drop, cross to the other side, then enter Yaba bus."&lt;/p&gt;

&lt;p&gt;If you're new to the city, a student, a young graduate posted here for national service, or just going somewhere unfamiliar, this knowledge is hard to come by. Google Maps will happily tell you to drive. It won't tell you which danfo to board, what the conductor will shout, or roughly how much the fare is.&lt;/p&gt;

&lt;p&gt;So people stay home, take expensive ride-hailing cars like uber and bolt, or rely on whoever they can call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OyaGo does
&lt;/h2&gt;

&lt;p&gt;Ask how to get from A to B. "How I go reach Yaba from Ikotun?" works just as well as "How do I get from Ikotun to Yaba?" ("How I go reach..." is Pidgin for "How do I get to...").&lt;br&gt;
Get numbered steps: where to board, what the conductor shouts, where to get off, which landmarks to look for, and a fare range.&lt;br&gt;
Save your places (Home, Work, Church) once, then just ask "Take me go work."&lt;br&gt;
Add a route you know. Every trip someone shares makes the app better for the next person.&lt;br&gt;
How it gets people off the screen&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OyaGo&lt;/strong&gt; is designed to be the shortest part of your trip. You spend thirty seconds reading the steps at the bus stop, then you put the phone away and go. The goal is confidence: if you know how to get there, you're far more likely to go to the market across town, visit a friend on the mainland, or finally go to the beach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;🔗 Live app: &lt;a href="https://oyago-web.onrender.com" rel="noopener noreferrer"&gt;https://oyago-web.onrender.com&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%2Fm0zgxc23etv4x9ssgisf.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%2Fm0zgxc23etv4x9ssgisf.jpeg" alt="Home Screen" width="591" height="1280"&gt;&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%2Fev9l42xlzj6rpy5mncwj.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%2Fev9l42xlzj6rpy5mncwj.jpeg" alt="A real answer to a question" width="591" height="1280"&gt;&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%2F99odi2l2nlei4iurc2si.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%2F99odi2l2nlei4iurc2si.jpeg" alt="" width="591" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Kingsmichaei/oyago.git" rel="noopener noreferrer"&gt;https://github.com/Kingsmichaei/oyago.git&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;The architecture&lt;br&gt;
Phone (React PWA)&lt;br&gt;
     │  "How I go reach Yaba from Ikotun?"&lt;br&gt;
     ▼&lt;br&gt;
FastAPI backend&lt;br&gt;
     │  1. Fetch the user's saved places (Backboard memory)&lt;br&gt;
     │  2. Send the question + places to the model&lt;br&gt;
     ▼&lt;br&gt;
Backboard&lt;br&gt;
     │  3. Retrieve the matching route notes (RAG over the route documents)&lt;br&gt;
     │  4. Open-weight model writes the answer, grounded in those notes&lt;br&gt;
     ▼&lt;br&gt;
Numbered, landmark-based directions back on the phone&lt;/p&gt;

&lt;p&gt;The open-source AI at the core&lt;br&gt;
&lt;strong&gt;Model:&lt;/strong&gt; Gemma, Google's open-weight model gemma-3-27b-it, served through [Backboard / OpenRouter]. It turns route notes into clear directions and replies in the user's own style: Pidgin if you wrote in Pidgin, plain English otherwise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieval (RAG) through Backboard.&lt;/strong&gt; The model doesn't "know" Lagos bus routes, and I didn't want it guessing. Wrong directions in a real city are worse than no directions. So every answer is grounded in a route document I wrote from routes I've actually travelled, plus routes the community adds. The system prompt tells the model to use only what it retrieves, and to say "I don't have this route yet" instead of inventing bus stops or fares.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory through Backboard.&lt;/strong&gt; Each user gets their own small memory store for saved places. That's what turns "take me go work" into a real trip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rest of the stack&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python + FastAPI, structured into config, schemas, services, and thin endpoints. It has a pytest suite that mocks Backboard, so every endpoint and failure case (model down, memory down, missing config) is tested without spending API credits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend:&lt;/strong&gt; React + Vite + Tailwind CSS, built as an installable PWA. The design borrows from the danfo itself: yellow with a black stripe, and big touch targets for one-handed use at a crowded bus stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hosting:&lt;/strong&gt; Both services deploy to Render from a single render.yaml blueprint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A constraint that shaped the build&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I built this on a 2011 HP ProBook laptop. Running a model locally on it wasn't realistic, so I used a hosted open-weight model while developing. That turned out to be a good test of the "open" promise: nothing in OyaGo depends on that particular host. More on that below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Why Does Open Innovation Matter?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The knowledge belongs to the community, not a platform. The most valuable part of OyaGo isn't the code or the model. It's the route knowledge that lives in Lagosians' heads. Keeping it in plain, open documents means no company can lock it away, change the terms, or switch it off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I can change the model without rebuilding the app. The model is one line of configuration. Because Gemma's weights are open, the exact same model can run on a hosted API today, on a cheap GPU server tomorrow, or fully offline on a phone or laptop in the future. With a closed API, I'd be one pricing change or a regional restriction away from losing the core of the product.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can be taught to speak like Lagos. Open weights mean I can fine-tune the model on real Lagos directions (landmarks, conductor calls, Pidgin) so it sounds like a local instead of a translated tourist guide. Closed models rarely allow that level of control. This is the next thing I want to build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cost matters here. Many of the people this is for are students and young workers watching every naira. An app that's cheap to run can stay free to use. Open models make that realistic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offline is the real goal. Mobile data is expensive in Nigeria and signal drops at the worst moments. A small open model running on the phone, with route notes cached locally, could give directions with no connection at all. A closed API can never do that.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What's Next
&lt;/h3&gt;

&lt;p&gt;Honest limitations, and where I'd take it:&lt;/p&gt;

&lt;p&gt;Route verification. Community routes currently go live immediately. Next I'll add a review step so a route needs confirmation before the AI uses it.&lt;br&gt;
Fine-tuning a small open model on Lagos-style directions, then comparing it with the base model.&lt;br&gt;
Offline mode, running a small open model on the device.&lt;br&gt;
More cities. Accra, Nairobi, and many other cities run on informal transport that no map understands. The approach transfers directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prize Categories
&lt;/h3&gt;

&lt;p&gt;Best Use of Backboard: RAG over community route documents, plus per-user memory for saved places&lt;br&gt;
Best Use of Gemma: the open-weight model behind every answer [only keep this if you used Gemma]&lt;br&gt;
Best Use of Render: frontend and API both deployed from one render.yaml blueprint&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you've ever been lost in a city where the map app didn't help, I'd love to hear about it in the comments. And if you know Lagos routes, come and add one. 🚌__&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>Reviving an Abandoned Django Attendance Tracker: From ModuleNotFound to Production Ready | GitHub Finish-Up-A-Thon</title>
      <dc:creator>Kingsmichaei</dc:creator>
      <pubDate>Sun, 07 Jun 2026 00:24:52 +0000</pubDate>
      <link>https://dev.to/kingsmichaei/reviving-an-abandoned-django-attendance-tracker-from-modulenotfound-to-production-ready-github-57jj</link>
      <guid>https://dev.to/kingsmichaei/reviving-an-abandoned-django-attendance-tracker-from-modulenotfound-to-production-ready-github-57jj</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I revived an abandoned Employee Attendance and Leave Management application. What started as a rushed, barely-functional proof of concept is now a secure, single app Django system with role based authentication, mobile responsive UI, and production ready database configurations. It allows employees to self-manage leave requests and clock in, while giving staff a full dashboard for attendance tracking and exports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Github Repository &lt;br&gt;
&lt;a href="https://github.com/Kingsmichaei/attendance.git" rel="noopener noreferrer"&gt;https://github.com/Kingsmichaei/attendance.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Live link:&lt;br&gt;
&lt;a href="https://attendance-njst.onrender.com/attendance/" rel="noopener noreferrer"&gt;https://attendance-njst.onrender.com/attendance/&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.amazonaws.com%2Fuploads%2Farticles%2F8ng5kdvm55yunvrkjnol.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.amazonaws.com%2Fuploads%2Farticles%2F8ng5kdvm55yunvrkjnol.jpeg" alt="Dashboard" width="800" height="407"&gt;&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.amazonaws.com%2Fuploads%2Farticles%2F9yb0kurl4idqg9inv3sf.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.amazonaws.com%2Fuploads%2Farticles%2F9yb0kurl4idqg9inv3sf.jpeg" alt="Clock in/ Clock out page" width="800" height="450"&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Ffgxwcfynrb7zfm6f2sob.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.amazonaws.com%2Fuploads%2Farticles%2Ffgxwcfynrb7zfm6f2sob.png" alt="Mobile View" width="800" height="1731"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;The Broken "Before" State&lt;br&gt;
When I dusted off this legacy project, it was trapped under a mountain of critical technical debt and architectural fragmentation:&lt;br&gt;
 Crashing on Startup: The project split logic unnecessarily between an ⁠accounts⁠ app and an ⁠attendance⁠ app. To make matters worse, a simple filename typo (⁠accounts/url.py⁠ singular instead of ⁠urls.py⁠) and a missing project-level ⁠include⁠ import caused immediate ⁠ModuleNotFoundError⁠ crashes.&lt;br&gt;
 Infinite Loops: The application’s routing was caught in a recursive logic trap. The sub-app URLs were trying to include themselves, creating an infinite routing loop that paralyzed the Django server.&lt;br&gt;
 Security &amp;amp; Configuration Vulnerabilities: The setup script was a security hazard—featuring a hardcoded ⁠SECRET_KEY⁠, ⁠DEBUG = True⁠ left wide open, completely empty ⁠ALLOWED_HOSTS⁠, and zero environment tracking. On top of that, every single frontend form entirely lacked csrf_token tags, making the application completely vulnerable to cross-site request forgery.&lt;br&gt;
 Rigid Database: The data layout was hard-coded exclusively for local SQLite development, making it impossible to scale or run reliably in a production container ecosystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Transformation Arc
&lt;/h2&gt;

&lt;p&gt;I decided to execute a complete architectural pivot and code overhaul to transform this project into a secure, cohesive application:&lt;br&gt;
1 Architectural Consolidation: I gutted the broken dual-app dependency and moved all core entities including the user flows, dashboard access, and tracking metrics directly into a streamlined, single-app setup under ⁠attendance⁠.&lt;br&gt;
2 Environment Isolation: I integrated ⁠python-decouple⁠ to completely isolate application secrets. The application settings now dynamically assess the runtime environment: executing on lightweight local SQLite files when ⁠DEBUG=True⁠ and effortlessly scaling out to a robust production PostgreSQL cluster when ⁠DEBUG=False⁠.&lt;br&gt;
3 Ironclad Access Control &amp;amp; Security: I systematically refactored the URL configurations to be completely linear, explicit, and non-recursive. Every single user facing form now contains explicit CSRF protection, and user logout routes are strictly bound to secure POST methods. I isolated public kiosk views entirely away from sensitive staff management views using explicit role checks.&lt;br&gt;
4 Feature Expansion &amp;amp; Responsive UI: I introduced an entirely new ⁠LeaveRequest⁠ data layer to support self-service employee leave management alongside regular clock-in tasks. Finally, the interface received a major design upgrade—featuring data layouts adapted for small screens and an interactive mobile navigation engine powered by a sleek glassmorphic hamburger dropdown menu.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;My Experience with GitHub Copilot&lt;br&gt;
GitHub Copilot was an invaluable asset during this intense refactoring process, acting as an agile pair programmer that significantly accelerated the path to completion.&lt;br&gt;
Smashed Through Debugging Blocks&lt;br&gt;
The absolute highlight of working with Copilot was diagnosing the broken legacy routing configuration. When I was tracking down why the server was locking up on launch, Copilot instantly highlighted the recursive dependency in ⁠attendance/urls.py⁠ and provided the clean, linear Django path code to resolve the circular loop. It also immediately picked up on the singular ⁠url.py⁠ naming mismatch across the workspace, saving me hours of tracking down obscure traceback logs.&lt;br&gt;
Effortless Configuration Boilerplate&lt;br&gt;
Switching an entire application from standard hardcoded settings to environment variables using ⁠python-decouple⁠ usually requires a lot of tedious copy pasting. Copilot predicted my implementation pattern perfectly. The second I imported ⁠config⁠ from decouple into ⁠settings.py⁠, Copilot automatically suggested the complete, production-hardened variable fallbacks for my PostgreSQL configuration, database credentials, and dynamic ⁠ALLOWED_HOSTS⁠ listings.&lt;/p&gt;

&lt;p&gt;Rapid Prototyping for Front-End Interactions&lt;br&gt;
Writing standard vanilla JavaScript to toggle navigation containers and handle UI transitions can be repetitive. Copilot helped draft the event listeners and class-toggling scripts required for the mobile hamburger navigation bar. It let me focus entirely on refining the CSS glassmorphism styles and layout responsiveness, while it quietly handled the structural element selectors behind the scenes.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>django</category>
    </item>
  </channel>
</rss>
