<?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: Lakshitha Deshan</title>
    <description>The latest articles on DEV Community by Lakshitha Deshan (@itzmeready).</description>
    <link>https://dev.to/itzmeready</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%2F4157885%2Fd639377a-7349-4766-896f-99dbf6e6645f.png</url>
      <title>DEV Community: Lakshitha Deshan</title>
      <link>https://dev.to/itzmeready</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itzmeready"/>
    <language>en</language>
    <item>
      <title>I built ClientScout to help find the next client</title>
      <dc:creator>Lakshitha Deshan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:50:51 +0000</pubDate>
      <link>https://dev.to/itzmeready/i-built-clientscout-to-help-find-the-next-client-2im5</link>
      <guid>https://dev.to/itzmeready/i-built-clientscout-to-help-find-the-next-client-2im5</guid>
      <description>&lt;p&gt;You can build a website for a business. Finding the business to build it for is where things get a little harder.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6kpe41lp9228x4s3leaz.gif" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6kpe41lp9228x4s3leaz.gif" alt="ClientScout walkthrough" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I built ClientScout to give freelancers somewhere to start. You tell it what you do, who you want to help, and where to look. It finds businesses that could be a fit and puts the useful details in one place.&lt;/p&gt;

&lt;p&gt;The pitch is simple: &lt;strong&gt;I find you clients. You do your thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;ClientScout helps freelancers and small agencies find potential business customers. Someone selling websites, photography, social media services, or bookkeeping can describe their offer and get a shortlist to work through.&lt;/p&gt;

&lt;p&gt;For example, you could search for guesthouses around Galle that might be relevant to a direct-booking website service. Each profile shows the business, its location, public contact details when available, and why it could fit your offer.&lt;/p&gt;

&lt;p&gt;The idea is to make the research before outreach easier. Instead of keeping a dozen search tabs open and copying details into a spreadsheet, you can review the businesses together and keep the ones that interest you.&lt;/p&gt;

&lt;p&gt;Open a profile to see the evidence, a possible opening, and what you still need to check. A relevant business isn't necessarily looking to buy, so the app keeps that distinction visible.&lt;/p&gt;

&lt;p&gt;You can save prospects in your browser, filter the shortlist, export a CSV, or prepare an introduction. The introduction is editable, and nothing gets sent automatically.&lt;/p&gt;

&lt;p&gt;I think this could be useful to someone who needs a few relevant businesses to approach each week. I haven't tested paid demand yet, but that's the problem I'd want a paid version to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&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%2F51ifej5ipip5dvpoftlp.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%2F51ifej5ipip5dvpoftlp.png" alt="ClientScout home" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://clientscout-akrc.onrender.com" rel="noopener noreferrer"&gt;Try ClientScout&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try describing an offer, choosing a type of business and a location, then running a search. Open a profile, check its sources, and save a business you'd want to look into.&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%2Fljt8no0gpyu52zihutzv.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%2Fljt8no0gpyu52zihutzv.png" alt="A shortlist in ClientScout" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The GIF and workspace screenshots use the app's labelled fictional example. You can open it with &lt;strong&gt;Take a look first&lt;/strong&gt; to explore without using search quota. Live searches use public business listings.&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%2F3e3bc6lpomts032rdlcf.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%2F3e3bc6lpomts032rdlcf.png" alt="Preparing an introduction" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The hosted demo has a small shared search allowance. It's on Render's free service, so it can take a little longer to wake up after being idle.&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/notlakshitha" rel="noopener noreferrer"&gt;
        notlakshitha
      &lt;/a&gt; / &lt;a href="https://github.com/notlakshitha/clientscout" rel="noopener noreferrer"&gt;
        clientscout
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      I find you clients/customers — Next.js prospect discovery powered by Gemini and Google Search grounding
    &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;ClientScout&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;I find you clients. You do your thing.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can know exactly what you want to sell and still have no idea who to offer it to. ClientScout takes your offer, a type of business, and a location, then builds a small shortlist of potential customers with a reason to look closer.&lt;/p&gt;
&lt;p&gt;Think websites for guesthouses in Galle, photography for cafés in Colombo, or bookkeeping for independent shops. It helps with the research before the first conversation. It doesn't promise anyone wants to buy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://clientscout-akrc.onrender.com" rel="nofollow noopener noreferrer"&gt;Open ClientScout&lt;/a&gt; · &lt;a href="https://clientscout-akrc.onrender.com/app?demo=1" rel="nofollow noopener noreferrer"&gt;Explore the example workspace&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/notlakshitha/clientscout/docs/preview.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fnotlakshitha%2Fclientscout%2FHEAD%2Fdocs%2Fpreview.png" alt="ClientScout landing page"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Try it&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;The landing page is at &lt;code&gt;/&lt;/code&gt;. The workspace is at &lt;code&gt;/app&lt;/code&gt;. Choose &lt;strong&gt;Take a look first&lt;/strong&gt; for an example with clearly labelled fictional businesses. That works without API keys.&lt;/p&gt;
&lt;p&gt;For live searches:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm ci
cp .env.example .env.local
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Add your own server-side API keys to .env.local&lt;/span&gt;
npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="nofollow noopener noreferrer"&gt;localhost:3000&lt;/a&gt;. Use Node.js…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/notlakshitha/clientscout" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It's built with Next.js, React, TypeScript, and plain CSS. The code is MIT licensed, with setup instructions in the repository.&lt;/p&gt;

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

&lt;p&gt;SerpApi searches Google Maps for the requested business type and location. That gives the app public listing details to work with, including names, addresses, websites, and phone numbers when listed.&lt;/p&gt;

&lt;p&gt;Gemini reads those listings alongside the user's offer and turns them into structured profiles. The server matches each profile back to a listing and takes the contact details from that record. It drops unmatched business names and doesn't let the model fill missing contacts with guesses. The listing search doesn't collect email addresses.&lt;/p&gt;

&lt;p&gt;Gemma 4 reviews how each business fits the offer. It suggests a possible opening and explains what's still unknown, such as the business's current setup or interest in the service. That assessment is separate from the factual contact fields.&lt;/p&gt;

&lt;p&gt;The hosted app uses &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt; through Google's API. A live test returned three guesthouses around Galle with public listing phone numbers and source links.&lt;/p&gt;

&lt;p&gt;Render hosts the Next.js app and its server routes. API keys stay on the server. Saved prospects stay in browser storage, so you don't need an account to try the workspace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;I wanted to keep the part that decides what makes a useful prospect easy to change. Gemma is an open-weight model, and its review is a separate stage with its own prompt and model setting.&lt;/p&gt;

&lt;p&gt;That lets me change how it assesses an offer without changing where business details come from. During testing, I switched from the 31B model to the 26B model after the larger endpoint failed on a full review. The listing and contact handling stayed the same.&lt;/p&gt;

&lt;p&gt;The available weights also leave room to serve or adapt that model later. This version uses hosted inference, so it still needs an internet connection and sends the brief to the configured providers. Local inference isn't implemented yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — Gemma 4 reviews business relevance and suggests an opening while keeping unknowns visible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of SerpApi&lt;/strong&gt; — Finds public business listings through live Google Maps search.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Render&lt;/strong&gt; — Hosts the Next.js app and server routes, with API keys configured on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Hope Comes From It
&lt;/h2&gt;

&lt;p&gt;I'd like someone who's good at their work but stuck on finding clients to get a useful starting point from this.&lt;/p&gt;

&lt;p&gt;The next step is to put it in front of freelancers and see which prospects they keep, which they skip, and whether it saves them time. Finding the next client still takes a conversation. I want ClientScout to make it easier to get to that conversation.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I built Night Sky, Literally...</title>
      <dc:creator>Lakshitha Deshan</dc:creator>
      <pubDate>Fri, 09 Oct 2026 07:44:44 +0000</pubDate>
      <link>https://dev.to/itzmeready/i-built-night-sky-literally-4eb1</link>
      <guid>https://dev.to/itzmeready/i-built-night-sky-literally-4eb1</guid>
      <description>&lt;p&gt;What better way to get people to touch grass than showing them what they're missing when they never look up?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcr9ik5p11jvxocwdw20q.gif" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcr9ik5p11jvxocwdw20q.gif" alt="NightSky demo" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I built NightSky to get people interested in the night sky and give them something to look for when they go outside. With NightSky you can explore a total of 88 constellations, learn about them, and make a short plan to find one from where you live.&lt;/p&gt;

&lt;p&gt;The idea is to make stargazing easy for anyone to get into. You don't need to know the names of a hundred stars or own a telescope. Just pick a constellation that interests you, follow the guide, and spend a few minutes looking for it in the sky.&lt;/p&gt;

&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;NightSky lets you explore the sky and discover many constellations. Click a star pattern to read its story, a bit of its history, how to recognise it, and what else you might see nearby. Some have a galaxy you can look for with binoculars. Others are worth learning just for their shape or the story behind their name.&lt;/p&gt;

&lt;p&gt;The idea is to let curiosity do some of the work. If a constellation catches your attention, the next question should be: how can I see this for myself?&lt;/p&gt;

&lt;p&gt;That's what the Sky guide is for. Set your location and time, and the Sky compass shows the patterns above your horizon. The scrolling Star Map is for exploring; the compass gives you directions for the real sky.&lt;/p&gt;

&lt;p&gt;The “Plan to see it” button in a description takes that constellation straight to the observing planner. You can choose a 10, 15, or 20-minute session and whether you're using your eyes, binoculars, or a telescope. If the constellation isn't suitable at that place and time, the app tells you instead of pretending it'll be visible.&lt;/p&gt;

&lt;p&gt;Gemma can personalise the plan's instructions. You can then download it and take it outside. Afterwards, My observations tab lets you record what you found, what you partly found, or what you'll try again another night. Not finding it the first time still counts as getting outside and having a look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&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%2Fcrtw9rgdil55r5s8t3ts.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%2Fcrtw9rgdil55r5s8t3ts.png" alt="explore page" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nightsky-41wc.onrender.com/" rel="noopener noreferrer"&gt;Try NightSky&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try opening a constellation that interests you, reading its finding tips, and pressing “Plan to see it.” Set your location and an evening time, then create a plan. You can explore the catalogue without sharing your location.&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/notlakshitha" rel="noopener noreferrer"&gt;
        notlakshitha
      &lt;/a&gt; / &lt;a href="https://github.com/notlakshitha/NightSky" rel="noopener noreferrer"&gt;
        NightSky
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Explore constellations and plan time outside with an open-model sky guide
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It's built with HTML, CSS, JavaScript, Canvas, WebGL and Three.js, with a small Node server for the connected features.&lt;/p&gt;

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

&lt;p&gt;The interactive sky uses Three.js and WebGL for rendering, with D3 Celestial providing constellation coordinates and star data.&lt;/p&gt;

&lt;p&gt;Astronomy Engine handles the astronomical calculations, including constellation positions, directions, and visibility based on the selected location and time.&lt;/p&gt;

&lt;p&gt;OpenSource models, connected through ollama, generates personalised observing instructions using the calculated targets and selected equipment.&lt;/p&gt;

&lt;p&gt;The generated instructions are checked against the astronomical calculations, so the app keeps the calculated directions and altitudes rather than relying on the model for those values.&lt;/p&gt;

&lt;p&gt;Each constellation also has its own finding notes with specific stars and landmarks to help users recognise it.&lt;/p&gt;

&lt;p&gt;For location related features, NightSky uses Open-Meteo for city lookup and SerpApi for finding nearby observatories and astronomy events&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;I wanted the AI part to be something people could change. Gemma is an open-weight model, and Settings lets you switch to your own Ollama endpoint and an installed model. You aren't stuck with the app's hosted connection or the model I picked.&lt;/p&gt;

&lt;p&gt;With a local Ollama setup, the model requests can stay on your machine. Observation notes stay in your browser too. The same target checks apply whichever model you use, and the calculated planner works without AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — Gemma 4 personalises short observing plans around constellations calculated for the selected location and time.&lt;/p&gt;

&lt;p&gt;Best Use of SerpApi — Finds nearby stargazing spots, astronomy clubs, and events through live search.&lt;/p&gt;

&lt;p&gt;Best Use of Render — Hosts the app and Node.js API, keeping API keys secure on the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Hope Comes From It
&lt;/h2&gt;

&lt;p&gt;I'd like someone who normally walks past the night sky without thinking about it to recognise one constellation. Maybe they come back to find another. Maybe they get a friend to look for it with them.&lt;/p&gt;

&lt;p&gt;That's the goal of NightSky: make the sky interesting enough that people want to go outside and see it for themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/cosinekitty/astronomy" rel="noopener noreferrer"&gt;Astronomy Engine&lt;/a&gt; for calculations.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/ofrohn/d3-celestial" rel="noopener noreferrer"&gt;D3 Celestial&lt;/a&gt; for constellation coordinates and star data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;Three.js&lt;/a&gt; for WebGL rendering.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open-meteo.com/" rel="noopener noreferrer"&gt;Open-Meteo&lt;/a&gt; for city lookup.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;Gemma&lt;/a&gt; and &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; for the model options.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://serpapi.com/" rel="noopener noreferrer"&gt;SerpApi&lt;/a&gt; for the nearby search integration.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>mlhacks</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built Inkwell So My Friend Would Stop Retyping Lecture Notes into LaTeX</title>
      <dc:creator>Lakshitha Deshan</dc:creator>
      <pubDate>Sun, 04 Oct 2026 22:08:38 +0000</pubDate>
      <link>https://dev.to/itzmeready/i-built-inkwell-so-my-friend-would-stop-retyping-lecture-notes-into-latex-50b3</link>
      <guid>https://dev.to/itzmeready/i-built-inkwell-so-my-friend-would-stop-retyping-lecture-notes-into-latex-50b3</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Inkwell turns messy, plain-text lecture notes into a clean study guide, with the math properly typeset and a sharp vector PDF at the end. You paste in whatever you typed during the lecture, an AI model sorts out the structure, and KaTeX renders the formulas. It's open source under the MIT license.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who I Built It For
&lt;/h2&gt;

&lt;p&gt;Inkwell is for me and my friend Asuna, a second-year engineering and CS student.&lt;/p&gt;

&lt;p&gt;In classes like Linear Algebra, Differential Equations and Machine Learning, the professor talks and writes at full speed, so we type whatever we can into Notepad or a quick Markdown file. The result looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eigenvalues and eigenvectors
linear transformation Av = lambda v where lambda is eigenvalue, v is non zero eigenvector
to find lambda solve characteristic equation det(A - lambda I) = 0
example 2x2 matrix with row 1: 2, 1 and row 2: 1, 2
find eigenvalues: det is (2 - lambda)^2 - 1 = lambda^2 - 4lambda + 3 = 0
factor it: (lambda - 3)(lambda - 1) = 0 so lambda1 = 3 and lambda2 = 1
since A is symmetric eigenvectors are guaranteed to be orthogonal
formula for roots: x = (-b +- sqrt(b^2 - 4ac)) / (2a)
key takeaway: matrix powers can be computed easily via A^k = P * D^k * P^-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By the end of class it's a wall of text. Shorthand like &lt;code&gt;Av = lambda v&lt;/code&gt; or &lt;code&gt;[[2,1],[1,2]]&lt;/code&gt; is fine while you're typing, but it's miserable to study from. We were spending 3 to 4 hours every weekend retyping everything into LaTeX or Notion just to make it readable, which is a silly way to spend a weekend.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Inkwell Fixes That
&lt;/h2&gt;

&lt;p&gt;You paste in the raw notes, pick a layout, and hit "Clean &amp;amp; Format Notes."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It recognizes the math.&lt;/strong&gt; Plain-text equations and matrices become KaTeX automatically. &lt;code&gt;Av = lambda v&lt;/code&gt; becomes 

&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, &lt;code&gt;det(A - lambda I) = 0&lt;/code&gt; becomes 
&lt;span class="katex-element"&gt;
  &lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mop"&gt;det&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;λ&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
, and &lt;code&gt;[[2, 1], [1, 2]]&lt;/code&gt; becomes:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="minner"&gt;&lt;span class="mopen delimcenter"&gt;&lt;span class="delimsizing size1"&gt;[&lt;/span&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mtable"&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="arraycolsep"&gt;&lt;/span&gt;&lt;span class="col-align-c"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose delimcenter"&gt;&lt;span class="delimsizing size1"&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;It has three layouts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single page, for reading everything through&lt;/li&gt;
&lt;li&gt;Two-column cheat sheet, for last-minute exam review&lt;/li&gt;
&lt;li&gt;Cornell notes, with cue questions, key takeaways and a summary block&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You can draw on it.&lt;/strong&gt; A canvas overlay gives you a pen, highlighter, eraser and movable text boxes, so you can sketch a diagram, circle the formula that's definitely going to be on the exam, or scribble in the margins right on top of the rendered math.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It exports a real vector PDF.&lt;/strong&gt; The math fonts stay sharp and your annotations come along with them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&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%2Fo9c980y98rzcrgic4j3p.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%2Fo9c980y98rzcrgic4j3p.png" alt="Inkwell with the raw eigenvalue notes on the left and the formatted study guide with rendered math on the right" width="799" height="320"&gt;&lt;/a&gt;&lt;br&gt;
Try it here: &lt;a href="https://inkwell-frontend-net1.onrender.com/" rel="noopener noreferrer"&gt;Inkwell on Render&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few things to try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type on the left and watch the math render on the right&lt;/li&gt;
&lt;li&gt;Switch between the Dark Slate, Minimal Grid and Clean Academic themes&lt;/li&gt;
&lt;li&gt;Annotate over the notes, then export to PDF&lt;/li&gt;
&lt;/ul&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/itzmeReadY" rel="noopener noreferrer"&gt;
        itzmeReadY
      &lt;/a&gt; / &lt;a href="https://github.com/itzmeReadY/inkwell" rel="noopener noreferrer"&gt;
        inkwell
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Inkwell: Clean, structured note generation with LaTeX formulas powered by Gemma open-weight models. Built for Hacktoberfest 2026.
    &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;Inkwell&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Inkwell is an open-source, AI-powered tool that transforms messy, raw, plain-text lecture notes into beautifully formatted, structured PDFs with precisely rendered mathematical formulas. By combining the power of Gemma open-weight models with modern rendering technologies, Inkwell automatically distills chaotic class notes into elegant, highly readable documents and study materials.&lt;/p&gt;
&lt;p&gt;Built for students, researchers, and engineers who type fast during lectures and need clean, structured outputs without spending hours manually formatting LaTeX.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Messy Text to Structured PDF:&lt;/strong&gt; Paste your frantic lecture notes, and let AI structure them with headings, bold definitions, and clear bullet points.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic LaTeX Rendering:&lt;/strong&gt; Plain text equations like &lt;code&gt;A v = lambda v&lt;/code&gt; are automatically detected, converted to KaTeX &lt;code&gt;$$A \mathbf{v} = \lambda \mathbf{v}$$&lt;/code&gt;, and rendered in perfect mathematics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple PDF Themes &amp;amp; Layouts:&lt;/strong&gt; Choose from Dark Slate, Minimal Grid, Clean, and layouts like Two-Column Cheat Sheet or Cornell Notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector PDFs &amp;amp; Pen&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/itzmeReadY/inkwell" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI:&lt;/strong&gt; Google's Gemma open-weight models (&lt;code&gt;gemma-4-31b-it&lt;/code&gt;, &lt;code&gt;gemma-4-26b-a4b-it&lt;/code&gt;, &lt;code&gt;gemma-2-27b-it&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; FastAPI, Python 3.12, Playwright for PDF rendering, Python-Markdown with KaTeX extensions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React 18, TypeScript, Vite, ReactMarkdown, Rehype-KaTeX, and a custom HTML5 canvas annotation layer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosting:&lt;/strong&gt; Render&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  1. Gemma does the cleanup
&lt;/h3&gt;

&lt;p&gt;Inkwell is built around the Gemma family. I wrote a STEM-focused prompt in &lt;code&gt;llm.py&lt;/code&gt; that asks the model to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;turn messy math notation (&lt;code&gt;lambda&lt;/code&gt;, &lt;code&gt;alpha&lt;/code&gt;, &lt;code&gt;a/b&lt;/code&gt;, summations, matrix rows) into valid LaTeX, using &lt;code&gt;$...$&lt;/code&gt; inline and &lt;code&gt;$$...$$&lt;/code&gt; for blocks&lt;/li&gt;
&lt;li&gt;reorganize stream-of-consciousness text into headings, bold terms and short bullets&lt;/li&gt;
&lt;li&gt;adjust to the chosen layout: Cornell mode gets &lt;code&gt;**CUE:**&lt;/code&gt; prompts, explanations and a &lt;code&gt;## Summary&lt;/code&gt;, while two-column mode gets short, dense bullets that split well across columns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. MathGuard, so the model doesn't "fix" the math
&lt;/h3&gt;

&lt;p&gt;LLMs like to get creative, and I didn't want my formulas rewritten. &lt;code&gt;backend/math_guard.py&lt;/code&gt; uses regex heuristics to find raw equations (like &lt;code&gt;A v = lambda v&lt;/code&gt;) and swaps them for placeholders (&lt;code&gt;⟦EQ1⟧&lt;/code&gt;, &lt;code&gt;⟦EQ2⟧&lt;/code&gt;). Then it checks that every placeholder survives the trip through the model and puts the formatted KaTeX back afterward.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Drawing and sticky notes
&lt;/h3&gt;

&lt;p&gt;Engineering notes aren't just text. You need to draw axes, circle things, and write in the margins. &lt;code&gt;DrawingCanvas.tsx&lt;/code&gt; and &lt;code&gt;TextBoxLayer.tsx&lt;/code&gt; give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smooth freehand drawing with adjustable color and stroke width&lt;/li&gt;
&lt;li&gt;a semi-transparent highlighter&lt;/li&gt;
&lt;li&gt;text boxes you can move and resize, sitting right above the rendered equations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. A PDF engine that doesn't mangle math
&lt;/h3&gt;

&lt;p&gt;Inkwell doesn't render your notes a second time on the server. The preview on your screen is the source of truth, and the PDF is a snapshot of it. When you hit export, the React frontend serializes its live DOM, with the KaTeX math already rendered, and sends it to &lt;code&gt;/api/compile-pdf&lt;/code&gt;. The backend wraps that HTML in print CSS and hands it to Playwright's headless Chromium, which produces a multi-page vector PDF.&lt;/p&gt;

&lt;p&gt;That means the math fonts stay crisp, your annotations come along, and there's no second rendering pipeline to drift out of sync with what you were looking at. It's also why Inkwell skips &lt;code&gt;window.print()&lt;/code&gt;, which tends to rasterize or clip equations.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Putting it on Render
&lt;/h3&gt;

&lt;p&gt;Gemma does the thinking, and Render hosts the part people actually open. The frontend is deployed on Render, so Asuna (or anyone else) can use Inkwell from a link, with nothing to install and no setup before a study session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cost.&lt;/strong&gt; Many AI study tools sit behind closed APIs and monthly subscriptions that a lot of students can't justify. Open-weight models like Gemma make a tool like this possible without that price tag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy.&lt;/strong&gt; Lecture notes can include unpublished research, lab data or personal study logs, and some hosted AI services may use prompts for training. Because Gemma's weights are open, the same model can run on your own machine through Ollama or vLLM, so your notes don't have to leave your laptop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Freedom to tinker.&lt;/strong&gt; Since Inkwell is MIT-licensed, anyone can change the LaTeX rules, add chemistry support with mhchem, build a theme for their university's thesis format, or self-host it offline in a lecture hall with no Wi-Fi.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Inkwell is built around Google's open-weight Gemma models, which turn raw STEM notes into clean Markdown and accurate LaTeX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render:&lt;/strong&gt; Inkwell is a hybrid deployment on Render. The React frontend runs as a Static Site and the FastAPI backend runs as a Docker Web Service, which lets Playwright's headless Chromium render the PDFs. The live demo above runs there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I made this to fix a real problem for Asuna and me, and to give back those hours of manual LaTeX every weekend.&lt;/p&gt;

&lt;p&gt;Made with ❤️ for Hacktoberfest 2026.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
