<?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: Tenath Dilusha</title>
    <description>The latest articles on DEV Community by Tenath Dilusha (@dilusha_chandrasiri).</description>
    <link>https://dev.to/dilusha_chandrasiri</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%2F4158887%2Fbf768a55-1f36-4e11-aee2-83d56788a89d.jpg</url>
      <title>DEV Community: Tenath Dilusha</title>
      <link>https://dev.to/dilusha_chandrasiri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dilusha_chandrasiri"/>
    <language>en</language>
    <item>
      <title>Echoes of Lanka - A Sri Lankan historical roleplay altar powered by open-weight AI</title>
      <dc:creator>Tenath Dilusha</dc:creator>
      <pubDate>Fri, 30 Oct 2026 13:48:59 +0000</pubDate>
      <link>https://dev.to/dilusha_chandrasiri/echoes-of-lanka-a-sri-lankan-historical-roleplay-altar-powered-by-open-weight-ai-4i4f</link>
      <guid>https://dev.to/dilusha_chandrasiri/echoes-of-lanka-a-sri-lankan-historical-roleplay-altar-powered-by-open-weight-ai-4i4f</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Echoes of Lanka&lt;/strong&gt; is a Sri Lankan historical roleplay altar powered by &lt;strong&gt;open-weight AI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You sit with imagined voices from the island's past — King Kashyapa on Sigiriya, anonymous fresco painters, Anuradhapura stupa masons, Sanghamittā Therī, Parākramabāhu I, and coastal cinnamon traders — while &lt;strong&gt;verified claims stay visibly separate from fiction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Week 4 asked for something spooky &lt;em&gt;or&lt;/em&gt; something that honors the past in the spirit of Día de los Muertos. I chose remembrance over jump-scares: when the line between past and present feels thin, we should still know which side of the altar is candlelight and which is stone.&lt;/p&gt;

&lt;p&gt;So every reply splits into two panels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Verified Echoes&lt;/strong&gt; — curated facts retrieved &lt;em&gt;without&lt;/em&gt; an LLM (keyword scoring over a small corpus, tagged &lt;code&gt;chronicle&lt;/code&gt; / &lt;code&gt;archaeology&lt;/code&gt; / &lt;code&gt;scholarship&lt;/code&gt;, with sources)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Living Voice&lt;/strong&gt; — Gemma roleplay, explicitly labeled as &lt;strong&gt;imagined dialogue&lt;/strong&gt;, constrained to those facts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The LLM never decides what is true. It only speaks beside the record.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voices you can meet
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Echo&lt;/th&gt;
&lt;th&gt;Who they are&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;King Kashyapa I&lt;/td&gt;
&lt;td&gt;Lord of the Lion Rock, Sigiriya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The Fresco Painter&lt;/td&gt;
&lt;td&gt;Anonymous hand of the Mirror Wall&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Stupa Mason&lt;/td&gt;
&lt;td&gt;Brick courses of Anuradhapura&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sanghamittā Therī&lt;/td&gt;
&lt;td&gt;Bearer of the Bodhi sapling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parākramabāhu I&lt;/td&gt;
&lt;td&gt;The great irrigator-king&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A Cinnamon Trader&lt;/td&gt;
&lt;td&gt;Coastal exchange and spice routes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/TenathDilusha/Echoes-of-Lanka" rel="noopener noreferrer"&gt;https://github.com/TenathDilusha/Echoes-of-Lanka&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
&lt;/span&gt;ollama serve          &lt;span class="c"&gt;# if not already running&lt;/span&gt;
ollama pull gemma3:4b &lt;span class="c"&gt;# or gemma3:1b on smaller machines&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env.local   &lt;span class="c"&gt;# optional&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;, pick a character, ask something like &lt;em&gt;"Why did you build on the rock?"&lt;/em&gt; or &lt;em&gt;"How did you mix your colors?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You'll see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Curated claims + confidence tags + sources on one side&lt;/li&gt;
&lt;li&gt;First-person atmospheric dialogue on the other — clearly marked as imagined&lt;/li&gt;
&lt;li&gt;A status chip for whether Ollama/Gemma is reachable; if the model is down, a &lt;strong&gt;fact-grounded fallback voice&lt;/strong&gt; still answers so the altar never goes fully silent&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;MIT-licensed Next.js app. The open pieces that make it work:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Gemma&lt;/strong&gt; (&lt;code&gt;gemma3:4b&lt;/code&gt; via Ollama)&lt;/td&gt;
&lt;td&gt;Living Voice — local open-weight chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deterministic retrieval&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Verified Echoes — no embeddings, no LLM ranking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;System prompt rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Dialogue may only lean on retrieved facts; gaps stay gaps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fallback template&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Offline / Ollama-down path still grounded in facts&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The critical design choice is in the system prompt: the model is told its reply is &lt;strong&gt;imagined dialogue only&lt;/strong&gt;, and concrete historical claims must come from the retrieved fact block — or it must admit the chronicles are silent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;CRITICAL&lt;/span&gt; &lt;span class="nx"&gt;RULES&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;open&lt;/span&gt; &lt;span class="nx"&gt;historical&lt;/span&gt; &lt;span class="nx"&gt;honesty&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="nx"&gt;Your&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;IMAGINED&lt;/span&gt; &lt;span class="nx"&gt;DIALOGUE&lt;/span&gt; &lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;creative&lt;/span&gt; &lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;primary&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&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;You&lt;/span&gt; &lt;span class="nx"&gt;may&lt;/span&gt; &lt;span class="nx"&gt;ONLY&lt;/span&gt; &lt;span class="nx"&gt;lean&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;VERIFIED&lt;/span&gt; &lt;span class="nx"&gt;FACTS&lt;/span&gt; &lt;span class="nx"&gt;listed&lt;/span&gt; &lt;span class="nx"&gt;below&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;concrete&lt;/span&gt; &lt;span class="nx"&gt;historical&lt;/span&gt; &lt;span class="nx"&gt;claims&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;asked&lt;/span&gt; &lt;span class="nx"&gt;something&lt;/span&gt; &lt;span class="nx"&gt;outside&lt;/span&gt; &lt;span class="nx"&gt;those&lt;/span&gt; &lt;span class="nx"&gt;facts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;say&lt;/span&gt; &lt;span class="nx"&gt;you&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;remember&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;chronicles&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;silent&lt;/span&gt;
   &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;fabricate&lt;/span&gt; &lt;span class="nx"&gt;battles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;monuments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retrieval is intentionally boring and auditable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** Deterministic keyword retrieval — no LLM involved in FACT selection. */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;retrieveFacts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;characterId&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;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That split is the whole product thesis: &lt;strong&gt;open models for presence; open, inspectable data for truthfulness.&lt;/strong&gt;&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js&lt;/strong&gt; + TypeScript UI (character grid → chat)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; serving &lt;strong&gt;Google Gemma 3&lt;/strong&gt; locally (&lt;code&gt;OLLAMA_URL&lt;/code&gt; / &lt;code&gt;OLLAMA_MODEL&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A curated fact bank with confidence labels and source lines&lt;/li&gt;
&lt;li&gt;Keyword scoring so fact selection is reproducible and cheap&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User question
    │
    ├─► retrieveFacts()  ── deterministic score over curated corpus
    │         │
    │         └─► VERIFIED ECHOES (claims + sources + confidence)
    │
    └─► Ollama / Gemma  ── roleplay only, constrained to retrieved facts
              │
              └─► LIVING VOICE (explicitly imagined)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Theme interpretation
&lt;/h3&gt;

&lt;p&gt;Día de los Muertos is about ofrendas — offerings that keep memory warm without confusing the living for the dead. Echoes of Lanka treats historical AI the same way: the Living Voice is the marigold and candle; the Verified Echoes panel is the photograph and the name card. You can feel the presence &lt;em&gt;and&lt;/em&gt; still read the label.&lt;/p&gt;

&lt;p&gt;Halloween's "ghost in the machine" angle still fits: the model is a simulation that refuses to pretend it's possession or a primary source.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Open Innovation Matters
&lt;/h2&gt;

&lt;p&gt;National memory and family-adjacent stories should not require shipping every prompt to a closed API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open worked better here than closed would have:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Runs on a laptop&lt;/strong&gt; — once Gemma is pulled, chat does not need a cloud key. Cost to run the dialogue path is electricity + hardware you already own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works when the network is gone&lt;/strong&gt; — Ollama local; fallback voice if the daemon is down. Cultural exploration does not stop at a captive portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can swap the model&lt;/strong&gt; — &lt;code&gt;OLLAMA_MODEL=gemma3:1b&lt;/code&gt; (or another Ollama tag) without rewriting the product. Closed APIs lock voice, pricing, and availability together.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facts stay under human control&lt;/strong&gt; — retrieval is deterministic code over a curated corpus. A closed RAG stack would still let the model blur "source" and "story"; we refused that blur on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nothing culturally sensitive has to leave the machine&lt;/strong&gt; — educational roleplay about heritage should not depend on a vendor that might change terms, disappear, or train on every whispered question.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Community builders have been saying the same thing about local open-weight tooling for privacy and offline use — for example &lt;a href="https://dev.to/tamizuddin/building-a-privacy-first-local-ai-assistant-a-developers-guide-to-open-weight-models-334m"&gt;Building a Privacy-First Local AI Assistant&lt;/a&gt; and &lt;a href="https://dev.to/suresh_kumar_de3920bedd1c/day-16-local-model-execution-running-open-weight-llms-securely-with-ollama-and-vllm-212i"&gt;Day 16: Local Model Execution with Ollama&lt;/a&gt;. Echoes of Lanka applies that lesson to &lt;strong&gt;historical honesty&lt;/strong&gt;, not only to secrets and code.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Moment It Landed
&lt;/h2&gt;

&lt;p&gt;The first time I asked the fresco painter &lt;em&gt;"Who were the women you painted?"&lt;/em&gt; and watched Verified Echoes light up with scholarship-tagged claims while the Living Voice answered in pigment and plaster — without inventing a royal romance the corpus did not support — that was the ofrenda click.&lt;/p&gt;

&lt;p&gt;The second time: I stopped Ollama on purpose. The altar still answered from the fact bank and admitted the mist. That mattered more to me than a prettier hallucination.&lt;/p&gt;

&lt;p&gt;This is an educational simulation. Chronicle narratives are literary as well as historical. Imagined dialogue is fiction grounded by a small curated fact bank — not a substitute for academic research or living cultural authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code: &lt;a href="https://github.com/TenathDilusha/Echoes-of-Lanka" rel="noopener noreferrer"&gt;github.com/TenathDilusha/Echoes-of-Lanka&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading — if you try an echo, tell me which voice answered back.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built My Friend a Private Coach That Says What to Fix Before Applying to Jobs. No more applying, waiting, silence.</title>
      <dc:creator>Tenath Dilusha</dc:creator>
      <pubDate>Mon, 05 Oct 2026 04:46:44 +0000</pubDate>
      <link>https://dev.to/dilusha_chandrasiri/i-built-my-friend-a-private-coach-that-says-what-to-fix-before-applying-to-jobs-no-more-applying-2jcj</link>
      <guid>https://dev.to/dilusha_chandrasiri/i-built-my-friend-a-private-coach-that-says-what-to-fix-before-applying-to-jobs-no-more-applying-2jcj</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;If you are a university student, you probably know this loop:&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%2Fij7xoh7xkies2v5yl4iu.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%2Fij7xoh7xkies2v5yl4iu.png" alt=" " width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem isn't effort. It's feedback. Nobody tells you which skills you're missing, which project you should lead with, or what the interviewer will ask.&lt;/p&gt;

&lt;p&gt;The obvious fix is to paste your CV into an AI chatbot. But a CV holds your name, phone number, home address, university and GPA. My friend didn't want to send that to a server they can't see inside. Honestly, neither would I.&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%2Fb1s7yt6z3nwa52492686.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%2Fb1s7yt6z3nwa52492686.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: JobPilot 🧭
&lt;/h2&gt;

&lt;p&gt;JobPilot is a private AI career coach that runs entirely on your own laptop. You give it your CV and a job you want, and it tells you exactly what to fix before you apply.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your CV never leaves your laptop. The AI is Gemma 3, running locally with Ollama.&lt;/li&gt;
&lt;li&gt;Free. No subscription, no API bill, no sign-up.&lt;/li&gt;
&lt;li&gt;Works offline. Everything except live job search works with Wi-Fi off.&lt;/li&gt;
&lt;li&gt;Honest. It doesn't invent skills, experience or fake numbers, and the code checks that (more on that below).&lt;/li&gt;
&lt;li&gt;Made for Sri Lankan students. It understands internships, trainee roles, GPA, A/L results, and keeps the English simple.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To show what it does, I'll use a sample student, Nimali: a Computer Science undergrad at UCSC with three projects (a React club website, a paddy price predictor in Python, and a Java library system). She's applying for a Software Engineering Intern role in Colombo.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. 🎯 Match &amp;amp; gaps: "How close am I?"
&lt;/h2&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%2Famvfaf5vixlgd110hwxq.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%2Famvfaf5vixlgd110hwxq.png" alt=" " width="800" height="751"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One click compares her CV with the job.&lt;/p&gt;

&lt;p&gt;First, an instant skills match appears. No AI here, just a fast keyword scan: she has 4 of the 17 skills the job lists (JavaScript, SQL, React, Git).&lt;/p&gt;

&lt;p&gt;Then Gemma reads both documents properly and gives:&lt;/p&gt;

&lt;p&gt;An overall fit score (65%) and a two-line summary&lt;/p&gt;

&lt;p&gt;Her strengths, with proof copied word for word from her CV, like JavaScript · "Languages: Python, Java, JavaScript, SQL"&lt;/p&gt;

&lt;p&gt;Missing skills ranked by importance, each with a concrete way to learn it. Top of the list: Node.js &amp;amp; Express.js (HIGH): "Build a simple API using Node.js and Express.js with a small dataset."&lt;/p&gt;

&lt;p&gt;CV edits that only use things she actually did&lt;/p&gt;

&lt;p&gt;Five interview questions tailored to her projects and this job&lt;/p&gt;

&lt;p&gt;Match and gaps: keyword match, AI fit score, strengths with CV quotes, ranked skill gaps and interview questions&lt;/p&gt;

&lt;h2&gt;
  
  
  2. 🎤 Interview practice: "Would that answer land?"
&lt;/h2&gt;

&lt;p&gt;Click Practice on any question, type your answer the way you'd say it, and JobPilot plays the interviewer.&lt;/p&gt;

&lt;p&gt;Nimali answered a question about her Library Management System with "...The hard part was the tables for borrowing, but we fixed it." JobPilot gave her a 4/10, and told her exactly why:&lt;br&gt;
"Needs more detail: what tables did you design? What were the key fields?"&lt;br&gt;
"Avoid vague phrasing like 'we fixed it'."&lt;/p&gt;

&lt;p&gt;Then it wrote a stronger answer in her own voice, using only her CV and what she said.&lt;/p&gt;

&lt;p&gt;Interview practice: tailored questions, the student's answer, a 4/10 score, what worked, how to improve and a stronger answer&lt;/p&gt;
&lt;h2&gt;
  
  
  3. ✍️ Rewrite: from "made a website" to a CV bullet
&lt;/h2&gt;

&lt;p&gt;Most students describe projects like this:&lt;/p&gt;

&lt;p&gt;Made a website for our university club where members can register for events and get reminders. Used React and Firebase.&lt;/p&gt;

&lt;p&gt;JobPilot turns it into a polished description and CV bullets like "Utilized Firebase to manage event registrations and send automated reminders to club members."&lt;/p&gt;

&lt;p&gt;The important part is what it doesn't do. It never makes up numbers. Instead, it asks the student to fill in the truth: "Quantify the impact, for example 'Supported [X] club members'."&lt;/p&gt;

&lt;p&gt;Rewrite: a one-line project description turned into a polished paragraph, CV bullets and suggestions&lt;/p&gt;
&lt;h2&gt;
  
  
  4. 💬 Ask JobPilot: a coach who has read your CV
&lt;/h2&gt;

&lt;p&gt;A chat that already knows your CV and the job. The answer streams in word by word, so you're not staring at a spinner.&lt;/p&gt;

&lt;p&gt;I asked "Which of my projects should I highlight for this job?" and it picked Campus Event Hub (the React one, matching the job's stack) and explained why the other two are weaker fits for this particular role.&lt;/p&gt;

&lt;p&gt;Ask JobPilot chat recommending the Campus Event Hub project for a React internship&lt;/p&gt;
&lt;h2&gt;
  
  
  5. 📈 Find jobs: "What should I learn next?"
&lt;/h2&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%2Fd5nlm2w43fzyvv1r18c5.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%2Fd5nlm2w43fzyvv1r18c5.png" alt=" " width="800" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the feature I'm proudest of. Search for real jobs (live from Google Jobs via SerpApi), and JobPilot:&lt;/p&gt;

&lt;p&gt;Ranks every posting by how well it matches your CV, and shows what's missing for each one.&lt;/p&gt;

&lt;p&gt;Counts which skills employers are asking for across all the postings. Blue bars are on your CV; yellow bars aren't yet.&lt;/p&gt;

&lt;p&gt;Asks Gemma to turn that chart into a learning plan: the most-requested skills you're missing, each with a first step you can do this weekend.&lt;/p&gt;

&lt;p&gt;When I searched "software engineering intern" in Sri Lanka, it pulled 17 real postings (Softmint, LSEG, Fidenz, Codimite and more). The results were eye-opening:&lt;/p&gt;

&lt;p&gt;Problem Solving was asked for in 10 of 17 postings, more than any programming language.&lt;/p&gt;

&lt;p&gt;JavaScript and React were in 8 of 17.&lt;/p&gt;

&lt;p&gt;Gemma's plan for Nimali: learn OOP (6 of 17), then Node.js (5 of 17), then Agile (4 of 17), and put Python, Java and SQL at the top of her CV.&lt;/p&gt;

&lt;p&gt;That's the kind of advice a senior would give you, except it's based on this week's real job posts.&lt;/p&gt;

&lt;p&gt;Find jobs: employer skill demand chart across 17 live postings, a Gemma learning plan, and job cards ranked by CV match&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/TenathDilusha" rel="noopener noreferrer"&gt;
        TenathDilusha
      &lt;/a&gt; / &lt;a href="https://github.com/TenathDilusha/jobpilot" rel="noopener noreferrer"&gt;
        jobpilot
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Private AI career coach for Sri Lankan students. Compares your CV with a job, finds skill gaps, and preps you for interviews, using Gemma running locally.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;JobPilot: Career Assistant for Sri Lankan Students&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;JobPilot is a private AI career coach for Sri Lankan
university students applying for internships and entry-level jobs. Upload your CV, paste a job
description, and ask:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;"What skills am I missing for this internship?"&lt;/li&gt;
&lt;li&gt;"Rewrite my project description."&lt;/li&gt;
&lt;li&gt;"What questions might they ask me?"&lt;/li&gt;
&lt;li&gt;"Compare my CV with this job description."&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything runs on your own laptop with an open-weight &lt;strong&gt;Gemma&lt;/strong&gt; model served by &lt;strong&gt;Ollama&lt;/strong&gt;
Your CV is never uploaded to a cloud AI service.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tab&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Match &amp;amp; gaps&lt;/td&gt;
&lt;td&gt;Instant keyword skill match, then Gemma's analysis: fit score, strengths with evidence quoted from the CV, missing skills ranked by importance with how to learn each, CV edits, and tailored interview questions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rewrite&lt;/td&gt;
&lt;td&gt;Turns a rough project description into a polished paragraph and action-verb CV bullets, using &lt;code&gt;[X%]&lt;/code&gt; placeholders instead of invented numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interview practice&lt;/td&gt;
&lt;td&gt;Answer a question&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/TenathDilusha/jobpilot" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;MIT licensed. Python + FastAPI backend, plain HTML/CSS/JavaScript frontend, 29 tests. Setup is three commands (see the README).&lt;/p&gt;

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

&lt;p&gt;Here's the whole system on one page:&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%2Fhcobzwmfrfzx4yrpz0ck.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%2Fhcobzwmfrfzx4yrpz0ck.png" alt=" " width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JobPilot architecture: CV and job description go into the laptop, through text extraction and a skill scanner, into Gemma 3 in Ollama, out to five features. SerpApi only receives the search words.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend&lt;/strong&gt;: FastAPI. It reads PDFs (pypdf) and Word files (python-docx), and exposes one endpoint per feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI&lt;/strong&gt;: Gemma 3 through Ollama's /api/chat, with JSON-schema structured outputs for every analysis and token streaming for chat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skill scanner&lt;/strong&gt;: 100 skills with aliases (ReactJS, React.js and react all count, but Java never matches JavaScript).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job search&lt;/strong&gt;: SerpApi's Google Jobs engine, two pages of results, cached for 6 hours so free search credits last.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: no framework. Every piece of model output is inserted as text, never as HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: a small model needs guardrails, not just instructions 🛡️
&lt;/h2&gt;

&lt;p&gt;Gemma 3 4B is impressive for its size, but small models love to make things up. In my early tests, it praised Nimali for "maintaining a website using Git" (her CV never says that) and suggested adding "Developed REST APIs with Node.js" to her Python project.&lt;/p&gt;

&lt;p&gt;Telling the model "never invent things" in the prompt helped, but it still ignored the rule sometimes. So I stopped trusting the prompt alone and built five layers:&lt;/p&gt;

&lt;p&gt;Keeping a 4B model honest: read the documents, scan skills without AI, prompt Gemma with rules, force a JSON schema, then check the answer in code&lt;/p&gt;

&lt;p&gt;The last step is a few lines of plain Python. A "strength" only survives if its quote really appears in the CV, and any CV tip or rewritten bullet that names a skill you don't have gets dropped. The model can be creative; the code makes sure it's never dishonest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: design for a slow laptop 🐢
&lt;/h2&gt;

&lt;p&gt;I built and tested this on my own laptop: 8 GB of RAM, no GPU. Gemma 3 4B writes about 3-4 words per second there, so every design choice was about making waiting feel OK:&lt;/p&gt;

&lt;p&gt;The skills match is instant (no AI), so you see something useful in under a second.&lt;/p&gt;

&lt;p&gt;Analysis and interview questions are separate, smaller calls that appear one after another, each with a live timer.&lt;/p&gt;

&lt;p&gt;Chat streams word by word.&lt;/p&gt;

&lt;p&gt;Outputs are deliberately short. Every extra word costs time.&lt;/p&gt;

&lt;p&gt;A ⚡ Fast mode switch swaps to Gemma 3 1B when you're in a hurry.&lt;/p&gt;

&lt;p&gt;A cloud model would be faster. But for something you do once per application, a few minutes is a fair price for keeping your CV private.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Open Matters
&lt;/h2&gt;

&lt;p&gt;A typical AI CV tool sends your CV to someone else's server. JobPilot keeps it on your laptop, and SerpApi only sees the search words.&lt;/p&gt;

&lt;p&gt;This project only works because Gemma is open:&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%2Fe0ke2hmq1p04xuok969i.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%2Fe0ke2hmq1p04xuok969i.png" alt=" " width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Privacy by design, not by promise. The model runs on the student's own machine, so there's no "we don't store your data" policy to trust. The data just never leaves.&lt;/p&gt;

&lt;p&gt;Free forever. Students can check every single application without paying per request.&lt;/p&gt;

&lt;p&gt;Offline. Patchy campus Wi-Fi or no mobile data? Everything except job search still works.&lt;/p&gt;

&lt;p&gt;Swap the model. 4B for quality, 1B for speed, or point it at a bigger Gemma on a stronger machine with one setting.&lt;/p&gt;

&lt;p&gt;Even the job search is private. The only thing sent to SerpApi is the search words, like "software engineering intern, Sri Lanka". Matching postings against your CV happens locally.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built with ❤️ for a friend during Hacktoberfest 2026. I'm a 3rd-year Computer Science and Engineering student at the University of Moratuwa. If you're job hunting too, give JobPilot a try and tell me what it caught on your CV.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
    </item>
    <item>
      <title>First post</title>
      <dc:creator>Tenath Dilusha</dc:creator>
      <pubDate>Sun, 04 Oct 2026 05:04:15 +0000</pubDate>
      <link>https://dev.to/dilusha_chandrasiri/first-post-5b8</link>
      <guid>https://dev.to/dilusha_chandrasiri/first-post-5b8</guid>
      <description></description>
    </item>
  </channel>
</rss>
