<?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: Ovi ren</title>
    <description>The latest articles on DEV Community by Ovi ren (@iamovi).</description>
    <link>https://dev.to/iamovi</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3704504%2F06ba0620-8521-4111-8ac6-5187ca3c4164.png</url>
      <title>DEV Community: Ovi ren</title>
      <link>https://dev.to/iamovi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/iamovi"/>
    <language>en</language>
    <item>
      <title>I Built an AI Website Roaster — Paste a URL, Get Absolutely Destroyed</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sun, 12 Apr 2026 10:39:46 +0000</pubDate>
      <link>https://dev.to/iamovi/i-built-an-ai-website-roaster-paste-a-url-get-absolutely-destroyed-3053</link>
      <guid>https://dev.to/iamovi/i-built-an-ai-website-roaster-paste-a-url-get-absolutely-destroyed-3053</guid>
      <description>&lt;p&gt;&lt;strong&gt;Kooked is an AI-powered website roaster built with Next.js, Supabase Edge Functions and LLaMA 3.3 70B. Paste any URL and get a brutally sarcastic, shareable roast.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You know that feeling when you look at a website and think &lt;em&gt;"who approved this?"&lt;/em&gt; — well, now you don't have to silently suffer. I built &lt;strong&gt;Kooked&lt;/strong&gt;, an AI-powered website roaster that does the judging for you.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Live app:&lt;/strong&gt; &lt;a href="https://kooked.vercel.app" rel="noopener noreferrer"&gt;kooked.vercel.app&lt;/a&gt;&lt;br&gt;
🐙 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/iamovi/kooked" rel="noopener noreferrer"&gt;github.com/iamovi/kooked&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is Kooked?
&lt;/h2&gt;

&lt;p&gt;Paste any URL. Kooked scrapes the site's content, feeds it to &lt;strong&gt;LLaMA 3.3 70B&lt;/strong&gt;, and delivers a long, ferociously sarcastic, deeply detailed critique — complete with a &lt;strong&gt;shareable link&lt;/strong&gt; to the full roast.&lt;/p&gt;

&lt;p&gt;Yes, it ends with at least one kind thing to say. Sometimes.&lt;/p&gt;


&lt;h2&gt;
  
  
  Features at a Glance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Brutal AI Roasts&lt;/strong&gt; — Three extensive roast paragraphs explicitly prompted for maximum sarcasm and word count&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shareable Roast Pages&lt;/strong&gt; — Every roast gets a unique URL (&lt;code&gt;/roast/[id]&lt;/code&gt;) you can send to anyone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global History Feed&lt;/strong&gt; — A live sidebar showing all websites roasted in the last 24 hours, powered by Supabase Realtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Favicon Fetching&lt;/strong&gt; — Each roast card shows the target site's real favicon via Icon.Horse&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark / Light Mode&lt;/strong&gt; — Clean monochrome design with a single fiery orange accent&lt;/li&gt;
&lt;/ul&gt;


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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tech&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Next.js 15 (App Router), React, Tailwind CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI Primitives&lt;/td&gt;
&lt;td&gt;Radix UI Dialog&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend API&lt;/td&gt;
&lt;td&gt;Supabase Edge Functions (Deno)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Model&lt;/td&gt;
&lt;td&gt;Groq API — Meta LLaMA 3.3 70B Versatile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Scraping&lt;/td&gt;
&lt;td&gt;Jina Reader API (&lt;code&gt;r.jina.ai&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;Supabase PostgreSQL + Realtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Favicon Service&lt;/td&gt;
&lt;td&gt;Icon.Horse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Icons&lt;/td&gt;
&lt;td&gt;Lucide React&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Here's the flow from paste to roast:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User pastes URL
      ↓
Next.js calls Supabase Edge Function
      ↓
Edge Function fetches page content via Jina Reader
      ↓
Content sent to Groq (LLaMA 3.3 70B) with a spicy system prompt
      ↓
Roast saved to Supabase PostgreSQL
      ↓
Unique shareable URL generated
      ↓
Global feed updated via Supabase Realtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the things I'm most happy about: &lt;strong&gt;the AI prompt and Groq API key live entirely inside the Supabase Edge Function&lt;/strong&gt; — they're never exposed to the browser. The client only ever talks to the Edge Function endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Prompt Engineering
&lt;/h2&gt;

&lt;p&gt;Getting LLaMA 3.3 to be &lt;em&gt;actually&lt;/em&gt; funny and &lt;em&gt;actually&lt;/em&gt; brutal took some iteration. The final prompt explicitly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Demands three long, detailed paragraphs (no lazy one-liners)&lt;/li&gt;
&lt;li&gt;Specifies maximum sarcasm and roast depth&lt;/li&gt;
&lt;li&gt;Requires ending with at least one genuine compliment (balance is key 😅)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Running It Locally
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Clone &amp;amp; install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/iamovi/kooked.git
&lt;span class="nb"&gt;cd &lt;/span&gt;kooked
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Set up environment
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;.env.local&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_SUPABASE_URL=https://your_project_id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Set up the database
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx supabase db push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Deploy the Edge Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx supabase login
npx supabase &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--project-ref&lt;/span&gt; your_project_ref
npx supabase secrets &lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_groq_api_key
npx supabase functions deploy roast
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Start the dev server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;&lt;strong&gt;Supabase Edge Functions are underrated.&lt;/strong&gt; Running Deno-based serverless functions that sit right next to your database, handle secrets properly, and deploy in seconds is a genuinely great developer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jina Reader is a cheat code for web scraping.&lt;/strong&gt; Prefixing any URL with &lt;code&gt;r.jina.ai/&lt;/code&gt; returns clean, readable markdown from any webpage — no Puppeteer, no parsing headaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Groq + LLaMA 3.3 70B is fast.&lt;/strong&gt; Inference is quick enough that the roast feels snappy, which matters a lot for user experience.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;A few ideas I'm considering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Rating/voting on roasts&lt;/li&gt;
&lt;li&gt;[ ] Roast categories (design, copy, performance, etc.)&lt;/li&gt;
&lt;li&gt;[ ] Side-by-side website comparison roasts&lt;/li&gt;
&lt;li&gt;[ ] A "defend your site" mode where the AI argues the opposite&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It &amp;amp; Contribute
&lt;/h2&gt;

&lt;p&gt;The project is open source under the MIT License.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;&lt;a href="https://kooked.vercel.app" rel="noopener noreferrer"&gt;kooked.vercel.app&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;&lt;a href="https://github.com/iamovi/kooked" rel="noopener noreferrer"&gt;github.com/iamovi/kooked&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go roast something. Your competitor's landing page is waiting. 🔥&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Stop Writing Bad Commit Messages — The Complete Conventional Commits Guide</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sun, 15 Mar 2026 13:49:41 +0000</pubDate>
      <link>https://dev.to/iamovi/stop-writing-bad-commit-messages-the-complete-conventional-commits-guide-mjo</link>
      <guid>https://dev.to/iamovi/stop-writing-bad-commit-messages-the-complete-conventional-commits-guide-mjo</guid>
      <description>&lt;p&gt;I'll be honest — I used to write terrible commit messages.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;fixed stuff&lt;/code&gt;. &lt;code&gt;update&lt;/code&gt;. &lt;code&gt;ok now it works&lt;/code&gt;. Sound familiar?&lt;/p&gt;

&lt;p&gt;It wasn't until I came back to one of my own projects after a few months and had absolutely no idea what I'd done or why, that I realized I was basically leaving myself (and anyone else) completely in the dark.&lt;/p&gt;

&lt;p&gt;So I went deep on Conventional Commits, built this guide as a reference for myself, and now I'm sharing it here. It's the most complete version I could put together. Bookmark it, share it with your team — and let's never write a useless commit message again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does This Even Matter?
&lt;/h2&gt;

&lt;p&gt;You might be thinking — &lt;em&gt;it's just a commit message, who cares?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's the thing. Three months from now, you will care. A new teammate will care. The person reviewing your PR will care.&lt;/p&gt;

&lt;p&gt;Bad commit history 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;fixed stuff
update
wip
changes
ok now it works
final final FINAL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells you nothing. Good commit history looks like a story — you can scroll through it and actually understand what happened, when, and why.&lt;/p&gt;

&lt;p&gt;On top of that, good commits unlock real automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic changelog generation&lt;/li&gt;
&lt;li&gt;Automatic semantic versioning&lt;/li&gt;
&lt;li&gt;CI/CD tools that understand your history&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git bisect&lt;/code&gt; that actually helps you find bugs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is also the standard used by Angular, Vue, Electron, ESLint, and thousands of other major open source projects. Once you get it, you won't go back.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Format
&lt;/h2&gt;

&lt;p&gt;It's simpler than it looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Category of change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scope&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Area of the codebase affected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;description&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Short summary of the change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;body&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;What changed and why&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;footer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Breaking changes, issue refs, co-authors&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A couple of rules to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always leave a blank line between the description and body&lt;/li&gt;
&lt;li&gt;Always leave a blank line between the body and footers&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;!&lt;/code&gt; symbol after type/scope means it's a breaking change&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Types — What Goes Where
&lt;/h2&gt;

&lt;p&gt;This is the part most people get wrong. Let me break down every type so there's no guessing.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;feat&lt;/code&gt; — New Feature
&lt;/h3&gt;

&lt;p&gt;Something new that users or API consumers can actually see or use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: add dark mode toggle
feat(auth): add OAuth2 login support
feat(api): add pagination to /users endpoint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ &lt;strong&gt;MINOR&lt;/strong&gt; version bump (&lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;1.1.0&lt;/code&gt;)&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;fix&lt;/code&gt; — Bug Fix
&lt;/h3&gt;

&lt;p&gt;Something was broken. Now it isn't.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix: resolve crash on empty search input
fix(cart): correct total price calculation
fix(mobile): fix nav menu not closing on tap
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ &lt;strong&gt;PATCH&lt;/strong&gt; version bump (&lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;1.0.1&lt;/code&gt;)&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;chore&lt;/code&gt; — Maintenance
&lt;/h3&gt;

&lt;p&gt;All the boring-but-necessary stuff that doesn't touch production behavior or tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chore: update dependencies
chore: remove unused imports
chore: clean up .gitignore
chore(deps): bump lodash from 4.17.20 to 4.17.21
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;docs&lt;/code&gt; — Documentation
&lt;/h3&gt;

&lt;p&gt;README updates, inline comments, JSDoc, wikis, changelogs — anything that's purely documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docs: add installation guide to README
docs(api): document rate limiting behavior
docs: fix broken links in CONTRIBUTING.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;style&lt;/code&gt; — Code Formatting
&lt;/h3&gt;

&lt;p&gt;Whitespace, semicolons, import ordering — the stuff your formatter handles. Nothing that changes how the code actually runs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;style: format files with prettier
style(button): fix inconsistent spacing
style: remove trailing whitespace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Don't confuse this with CSS or visual UI changes. Use &lt;code&gt;feat&lt;/code&gt; or &lt;code&gt;fix&lt;/code&gt; for those.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;refactor&lt;/code&gt; — Code Restructuring
&lt;/h3&gt;

&lt;p&gt;You rewrote something internally — cleaner, simpler, better organized — but the behavior didn't change and no bug was fixed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;refactor: extract validation into separate module
refactor(auth): simplify token refresh logic
refactor: replace forEach with map in data transform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;test&lt;/code&gt; — Tests
&lt;/h3&gt;

&lt;p&gt;Adding, fixing, or updating tests. No changes to production code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test: add unit tests for useAnimeList hook
test(api): add integration tests for /search endpoint
test: fix flaky timeout in auth tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;perf&lt;/code&gt; — Performance
&lt;/h3&gt;

&lt;p&gt;Made something faster without changing what it does.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;perf: debounce search input to reduce API calls
perf(images): add lazy loading to anime cards
perf: memoize expensive genre filter computation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ PATCH version bump in some configs.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;ci&lt;/code&gt; — CI/CD Config
&lt;/h3&gt;

&lt;p&gt;GitHub Actions, CircleCI, Jenkins workflows — anything that touches your pipeline config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ci: add automated deployment to Vercel
ci: fix failing lint step in GitHub Actions
ci(docker): update Node.js base image to 20-alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;build&lt;/code&gt; — Build System
&lt;/h3&gt;

&lt;p&gt;Webpack, Vite, tsconfig, package.json — anything related to how your project gets built.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build: migrate from CRA to Vite
build: add path aliases to tsconfig
build(deps): add recharts as dependency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ No version bump.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;revert&lt;/code&gt; — Reverting a Commit
&lt;/h3&gt;

&lt;p&gt;Something went wrong. You're going back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revert: revert "feat: add experimental offline mode"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always mention the hash in the body so others know exactly what was undone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revert: revert "feat: add experimental offline mode"

Reverts commit a1b2c3d.
Caused a regression in the login flow on Safari.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Extended Types
&lt;/h3&gt;

&lt;p&gt;These aren't universal, but you'll see them in larger codebases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Patching a security vulnerability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hotfix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Urgent production fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i18n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Internationalization changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a11y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Accessibility improvements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;infra&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Infrastructure changes (Terraform, Docker, K8s)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;init&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Initial project setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wip&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Work in progress — should never stay on &lt;code&gt;main&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Scopes — Be Specific About What You Touched
&lt;/h2&gt;

&lt;p&gt;Scopes are optional, but once your codebase grows past a certain point, they become really valuable. They tell you &lt;em&gt;where&lt;/em&gt; the change happened at a glance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(auth): add JWT refresh logic
fix(navbar): resolve dropdown z-index issue
chore(deps): update react to 18.3.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A few rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lowercase only&lt;/li&gt;
&lt;li&gt;One or two words max&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick one name and stick to it&lt;/strong&gt; — &lt;code&gt;auth&lt;/code&gt; and &lt;code&gt;authentication&lt;/code&gt; being used interchangeably is confusing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common patterns:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# By feature
feat(auth), feat(chat), feat(search), feat(dashboard)

# By layer
fix(api), fix(ui), fix(db), fix(hooks)

# By platform
fix(mobile), fix(ios), fix(web)

# By component
style(AnimeCard), refactor(useAnimeList), test(anilist)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Writing a Good Description
&lt;/h2&gt;

&lt;p&gt;This is where most people slip up. The description is the short summary after the colon — and there are a few rules that matter more than you'd think.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ feat: add login page
❌ feat: Added login page
❌ feat: adding login page.
❌ feat: Add Login Page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imperative mood&lt;/strong&gt; — write it like a command. &lt;code&gt;add&lt;/code&gt;, not &lt;code&gt;added&lt;/code&gt; or &lt;code&gt;adding&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lowercase&lt;/strong&gt; the first word (unless it's a proper noun)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No period&lt;/strong&gt; at the end&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Under 72 characters&lt;/strong&gt; — so it doesn't get cut off in terminals or GitHub&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be specific&lt;/strong&gt; — &lt;code&gt;fix episode count not updating after progress change&lt;/code&gt; is infinitely more useful than &lt;code&gt;fix bug&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Commit Body — Use It More Than You Do
&lt;/h2&gt;

&lt;p&gt;Most people skip the body entirely. That's a mistake.&lt;/p&gt;

&lt;p&gt;The body is where you explain &lt;em&gt;why&lt;/em&gt; you made the change — and that's the part that's actually hard to figure out later. The diff already shows &lt;em&gt;what&lt;/em&gt; changed.&lt;/p&gt;

&lt;p&gt;Here's a good example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(chat): wire recommendations through AniList API

Previously recommendations were pulled from a static local array
of 20 hardcoded titles. Every user got the same suggestions
regardless of what genres they asked for.

Now recommendations query the AniList GraphQL API directly,
filtering by genre and sorting by popularity. Results are
dynamic and always current.

Note: adds a 300-500ms delay on recommendation requests.
Debounced to avoid hammering the endpoint.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Future you will thank present you for this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Footers — Small Details That Matter
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Closes #42
Fixes #17
BREAKING CHANGE: description of what broke
Co-authored-by: Jane Doe &amp;lt;jane@example.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Closes #42&lt;/code&gt; is worth the two seconds it takes to type — GitHub and GitLab will automatically close the linked issue when the commit lands on your default branch. It creates a clean paper trail between the code and the original task or bug report.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breaking Changes
&lt;/h2&gt;

&lt;p&gt;Two ways to flag them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Method 1 — The &lt;code&gt;!&lt;/code&gt; symbol:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat!: change exportList to return Promise
feat(api)!: remove deprecated v1 endpoints
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Method 2 — Footer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api): update authentication flow

BREAKING CHANGE: API tokens are no longer accepted as query params.
All requests must include the Authorization header instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Both together (best option for clarity):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(api)!: remove query param authentication

BREAKING CHANGE: API tokens are no longer accepted as query params.
All requests must include the Authorization header instead.
Migration guide: https://docs.example.com/migration/v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ &lt;strong&gt;MAJOR&lt;/strong&gt; version bump (&lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;2.0.0&lt;/code&gt;)&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Everyday commits
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat: add anime search bar to header
fix: resolve infinite scroll triggering on page load
chore: remove console.log statements
style: format components with prettier
docs: add JSDoc to useAnimeList hook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  With scope
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(chat): add quick action buttons for common queries
feat(stats): add genre breakdown pie chart
fix(card): fix episode progress bar overflow on mobile
fix(anilist): handle null description from API gracefully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full commit with body and footer
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix(anilist): handle rate limiting from AniList API

AniList enforces a 90 requests/minute rate limit. Under heavy
search usage (fast typing), the app was hitting this and showing
blank results with a cryptic 429 error in the console.

Added exponential backoff retry logic with a max of 3 attempts.
Added a user-facing toast notification when retries are exhausted.

Closes #12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking change
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feat(export)!: change exportList format from array to object

Previously exportList returned a raw array of Anime objects.
It now returns an AnimeListState object with `animes` and
`lastUpdated` fields, consistent with the internal state shape.

BREAKING CHANGE: importList now expects an AnimeListState object.
Old JSON backups using the array format will no longer import correctly.
Run the migration script at scripts/migrate-backup.js on old files.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What NOT to Do
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vague descriptions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bad
fix: fix
feat: update
chore: stuff

# Good
fix: prevent crash when anime list is empty
feat: add episode progress tracking to anime cards
chore: remove unused StatusBadge variant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrong type
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bad — this is a fix, not a style change
style: fix broken layout on mobile

# Bad — this is a feat, not a refactor
refactor: add search history dropdown

# Good
fix: fix broken layout on mobile
feat: add search history dropdown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Too many changes in one commit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bad
feat: add dark mode, fix mobile nav, update README

# Good — three separate commits
feat: add dark mode toggle
fix(nav): fix mobile menu not closing on route change
docs: update README with dark mode usage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Uppercase or period
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Bad
feat: Add new search functionality.

# Good
feat: add new search functionality
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How This Connects to Versioning
&lt;/h2&gt;

&lt;p&gt;This is where it gets really powerful. Conventional Commits maps directly to Semantic Versioning (&lt;code&gt;MAJOR.MINOR.PATCH&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Commit Type&lt;/th&gt;
&lt;th&gt;Version Bump&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MINOR — &lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;1.1.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;New feature added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PATCH — &lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;1.0.1&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Bug fixed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;perf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PATCH — &lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;1.0.1&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Performance improved&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;BREAKING CHANGE&lt;/code&gt; or &lt;code&gt;!&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;MAJOR — &lt;code&gt;1.0.0&lt;/code&gt; → &lt;code&gt;2.0.0&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;API changed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Everything else&lt;/td&gt;
&lt;td&gt;No bump&lt;/td&gt;
&lt;td&gt;Docs, chores, style, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Tools like &lt;code&gt;semantic-release&lt;/code&gt; and &lt;code&gt;release-please&lt;/code&gt; can read your commit history and automatically bump the version, generate a changelog, tag a release, and publish to npm — all without you touching a single config value manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up commitlint
&lt;/h2&gt;

&lt;p&gt;You shouldn't rely on willpower to keep commit messages clean. Automate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&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; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @commitlint/cli @commitlint/config-conventional
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// commitlint.config.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@commitlint/config-conventional&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"feat: add login page"&lt;/span&gt; | npx commitlint
&lt;span class="c"&gt;# ✅ passes&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"added login page"&lt;/span&gt; | npx commitlint
&lt;span class="c"&gt;# ❌ fails with error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Add Git Hooks with Husky
&lt;/h2&gt;

&lt;p&gt;Now wire it up so it runs automatically on every commit:&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; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; husky
npx husky init
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"npx --no -- commitlint --edit &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;1"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .husky/commit-msg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. From this point on, any commit that doesn't follow the convention gets rejected before it even goes through. No more sneaky &lt;code&gt;fix: stuff&lt;/code&gt; messages slipping in.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commitizen — For Teams That Need a Guided Prompt
&lt;/h2&gt;

&lt;p&gt;If your team keeps forgetting the format, commitizen gives everyone an interactive prompt instead:&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; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; commitizen cz-conventional-changelog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commitizen"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cz-conventional-changelog"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;npx cz&lt;/code&gt; instead of &lt;code&gt;git commit&lt;/code&gt; and you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? Select the type of change:
❯ feat:     A new feature
  fix:      A bug fix
  docs:     Documentation only changes
  style:    Changes that do not affect meaning
  refactor: A code change that neither fixes a bug nor adds a feature
  perf:     A code change that improves performance
  test:     Adding missing tests or correcting existing tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No memorizing required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips for Teams
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Agree on scopes upfront.&lt;/strong&gt; Pick a list, write it down somewhere, and stick to it. Consistency matters more than the specific names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One change per commit.&lt;/strong&gt; If your description needs the word "and", split it into two commits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Commit often, squash before merging.&lt;/strong&gt; Work in messy WIP commits locally, then clean them up into proper conventional commits before opening a PR.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Body = why, not what.&lt;/strong&gt; The diff shows what changed. The body is for context that won't be obvious six months from now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Reference issues every time.&lt;/strong&gt; &lt;code&gt;Closes #42&lt;/code&gt; takes two seconds and creates a permanent connection between your code and the original task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Enforce with tooling, not discipline.&lt;/strong&gt; People forget. Linters don't. Set up commitlint + Husky and take it off your plate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Cheatsheet
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FORMAT
──────────────────────────────────────────────────────────
&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;description&amp;gt;

[optional body]

[optional footer(s)]


TYPES
──────────────────────────────────────────────────────────
feat        New feature                → MINOR version bump
fix         Bug fix                    → PATCH version bump
chore       Maintenance, no app change → no bump
docs        Documentation only         → no bump
style       Formatting, no logic       → no bump
refactor    Restructure, no behavior   → no bump
test        Tests only                 → no bump
perf        Performance improvement    → PATCH version bump
ci          CI/CD config               → no bump
build       Build system / deps        → no bump
revert      Revert a commit            → depends
feat! / BREAKING CHANGE  Breaking API  → MAJOR version bump


DESCRIPTION RULES
──────────────────────────────────────────────────────────
✅ Imperative mood   → "add feature" not "added feature"
✅ Lowercase start   → "fix bug" not "Fix bug"
✅ No period at end  → "update config" not "update config."
✅ Under 72 chars    → keep it short and specific


FOOTER TOKENS
──────────────────────────────────────────────────────────
Closes #42
Fixes #17
BREAKING CHANGE: description of what broke
Co-authored-by: Name &amp;lt;email&amp;gt;


EXAMPLES
──────────────────────────────────────────────────────────
feat: add anime search by genre
feat(chat): wire recommendations through AniList API
fix: resolve crash on empty input
fix(anilist): handle null description gracefully
chore(deps): bump vite from 5.4.0 to 5.4.19
docs: add setup instructions to README
style: format files with prettier
refactor: extract query strings into constants
test: add unit tests for useAnimeList hook
perf: debounce search input to reduce API calls
ci: add GitHub Actions deploy workflow
build: migrate bundler from webpack to vite
revert: revert "feat: add experimental offline mode"
feat!: rename AnimeStatus values to uppercase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Useful Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Changelog Generation
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/conventional-changelog/conventional-changelog" rel="noopener noreferrer"&gt;conventional-changelog&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Generate changelogs from commit history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/orhun/git-cliff" rel="noopener noreferrer"&gt;git-cliff&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Highly configurable changelog generator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/googleapis/release-please" rel="noopener noreferrer"&gt;release-please&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Google's automated release PR tool&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Automated Releases
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/semantic-release/semantic-release" rel="noopener noreferrer"&gt;semantic-release&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Fully automated versioning and publishing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://github.com/conventional-changelog/standard-version" rel="noopener noreferrer"&gt;standard-version&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Versioning using semver and conventional commits&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Editor Integrations
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Editor&lt;/th&gt;
&lt;th&gt;Extension&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VS Code&lt;/td&gt;
&lt;td&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VS Code&lt;/td&gt;
&lt;td&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=KnisterPeter.vscode-commitizen" rel="noopener noreferrer"&gt;Commitizen Support&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JetBrains&lt;/td&gt;
&lt;td&gt;Built-in conventional commit support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vim/Neovim&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/neoclide/coc-git" rel="noopener noreferrer"&gt;coc-git&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.conventionalcommits.org/" rel="noopener noreferrer"&gt;conventionalcommits.org&lt;/a&gt; — Official specification&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://semver.org/" rel="noopener noreferrer"&gt;semver.org&lt;/a&gt; — Semantic versioning spec&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://commitlint.js.org/" rel="noopener noreferrer"&gt;commitlint.js.org&lt;/a&gt; — Linting rules and config&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://semantic-release.gitbook.io/" rel="noopener noreferrer"&gt;semantic-release docs&lt;/a&gt; — Automated release pipeline&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/angular/angular/blob/main/CONTRIBUTING.md#-commit-message-format" rel="noopener noreferrer"&gt;Angular commit guidelines&lt;/a&gt; — Where the convention originated&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Read this blog on my &lt;a href="https://iamovi.github.io/blog/commit-like-a-pro" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Ovi ren&lt;/em&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>i built a social platform where everything vanishes after 24 hours</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Tue, 03 Mar 2026 04:44:50 +0000</pubDate>
      <link>https://dev.to/iamovi/i-built-a-social-platform-where-everything-vanishes-after-24-hours-3imk</link>
      <guid>https://dev.to/iamovi/i-built-a-social-platform-where-everything-vanishes-after-24-hours-3imk</guid>
      <description>&lt;p&gt;genjutsu is a fast-paced, developer-focused social network where everything vanishes every 24 hours. share code, connect with fellow builders, and stay in the loop without the clutter of a permanent history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;live link&lt;/strong&gt;: &lt;a href="https://genjutsu-social.vercel.app/" rel="noopener noreferrer"&gt;genjutsu-social.vercel.app&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;source code&lt;/strong&gt;: &lt;a href="https://github.com/iamovi/genjutsu" rel="noopener noreferrer"&gt;github.com/iamovi/genjutsu&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  screenshots
&lt;/h3&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%2F3mr1pjap9fozc7xhp962.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%2F3mr1pjap9fozc7xhp962.png" alt="app preview 1" 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%2F91ru5fhmf9r2kl50t4wc.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%2F91ru5fhmf9r2kl50t4wc.png" alt="app preview 2" 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%2Fhi7n4q0485xcwqbt245d.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%2Fhi7n4q0485xcwqbt245d.png" alt="app preview 3" 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%2F3t57yrqrlec5d2j46mgu.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%2F3t57yrqrlec5d2j46mgu.png" alt="app preview 4" 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%2Fsq31xcn1uunu75n1bq4q.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%2Fsq31xcn1uunu75n1bq4q.png" alt="app preview 5" 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%2F25nna0ygbvxobf31tet1.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%2F25nna0ygbvxobf31tet1.png" alt="app preview 6" 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%2Fw634qclh55wnoonrdbbr.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%2Fw634qclh55wnoonrdbbr.png" alt="app preview 7" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in a world of digital permanence, genjutsu offers a temporary space for ephemeral thoughts. whether it's a quick code snippet, a late-night epiphany, or a daily progress update, it lives for 24 hours and then disappears—leaving no trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;24-hour lifespan: every post, comment, and interaction has a strictly enforced 24-hour timer.&lt;/li&gt;
&lt;li&gt;developer first: optimized for sharing code and technical insights.&lt;/li&gt;
&lt;li&gt;real-time connection: built for instant engagement with a community of builders.&lt;/li&gt;
&lt;li&gt;manga aesthetic: a clean, high-contrast visual style inspired by japanese manga.&lt;/li&gt;
&lt;li&gt;zero clutter: start every day with a fresh feed and a clean slate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  why genjutsu?
&lt;/h3&gt;

&lt;p&gt;most social platforms are designed for the long term, which often leads to performance anxiety or a fear of being "on the record" forever. i designed genjutsu to remove that pressure. it's a place to be experimental, raw, and authentically you, knowing that your mistakes or half-baked ideas won't follow you around for years. &lt;/p&gt;

&lt;h3&gt;
  
  
  the tech stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;frontend&lt;/strong&gt;: react with vite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;styling&lt;/strong&gt;: tailwind css for that crisp manga look&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;animations&lt;/strong&gt;: framer motion for smooth transitions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backend&lt;/strong&gt;: supabase for real-time magic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;deployment&lt;/strong&gt;: vercel&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  roadmap
&lt;/h3&gt;

&lt;p&gt;i am just getting started. some things on the horizon include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ephemeral messaging (whispers) that also vanish after 24 hours.&lt;/li&gt;
&lt;li&gt;social mini-games to play together within the platform.&lt;/li&gt;
&lt;li&gt;dynamic open graph images for better social sharing.&lt;/li&gt;
&lt;li&gt;progressive web app (pwa) support for a native feel.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  join the loop
&lt;/h3&gt;

&lt;p&gt;genjutsu is open source. i built this for the developer community, and i would love for you to be a part of it. whether you want to fix a bug, suggest a feature, or help with the manga-inspired design, your input is welcome.&lt;/p&gt;

&lt;p&gt;if you are interested in helping out, please check the &lt;a href="https://github.com/iamovi/genjutsu/blob/main/.github/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; file on github. let's build something ephemeral together.&lt;/p&gt;

&lt;p&gt;no archives, no legacy, just what's happening now.&lt;/p&gt;

</description>
      <category>socialmedia</category>
      <category>showdev</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>introducing KeysAndFingers, an open source multiplayer typing racer</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sun, 22 Feb 2026 11:51:13 +0000</pubDate>
      <link>https://dev.to/iamovi/introducing-keysandfingers-an-open-source-multiplayer-typing-racer-9gp</link>
      <guid>https://dev.to/iamovi/introducing-keysandfingers-an-open-source-multiplayer-typing-racer-9gp</guid>
      <description>&lt;p&gt;so, i built &lt;code&gt;Keys&amp;amp;Fingers&lt;/code&gt;, a multiplayer typing racer and practice solo, that runs in the browser and also ships as a windows desktop app. here's what it does and how it works.&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%2Ft14qo9o7n99y6bdeneo8.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%2Ft14qo9o7n99y6bdeneo8.png" alt="logo" width="96" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;vs racing mode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;the standout feature is vs mode — two players race each other in real-time using room codes. both players see each other's keystrokes as they happen. the race doesn't start until both players hit ready, so there's no scrambling. the winner get random anime waifu as a reward at the end of race.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solo mode&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;practice solo, enhance your typing skills, see typing history and keyboard heatmap to see your typing faults and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what else it does&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;keysandfingers covers the core typing test basics — real-time wpm, cpm, and accuracy tracking per keystroke. it's built with react, typescript, and vite. there's a live version at: &lt;a href="https://keysandfingers.vercel.app" rel="noopener noreferrer"&gt;https://keysandfingers.vercel.app&lt;/a&gt; and a windows desktop app available in the releases: &lt;a href="https://github.com/iamovi/KeysAndFingers/releases/" rel="noopener noreferrer"&gt;https://github.com/iamovi/KeysAndFingers/releases/&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%2Fjjq9s4gs5xtph3atszf1.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%2Fjjq9s4gs5xtph3atszf1.png" alt="exe" width="769" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;there's also a theme studio for full customization — fonts, colors, effects — with settings that persist automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tech stack&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;react + typescript&lt;/li&gt;
&lt;li&gt;vite for bundling&lt;/li&gt;
&lt;li&gt;real-time sync for vs mode via room codes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the codebase is lightweight by design. no unnecessary dependencies. the windows desktop app is packaged separately and runs on windows 10 and 11.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;why i made it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;most typing test tools are either too minimal to be interesting or too bloated to be fast. i wanted something that felt snappy, had a real multiplayer mode, and was fully open source. the project is under the mit license.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;live app: &lt;a href="https://keysandfingers.vercel.app" rel="noopener noreferrer"&gt;https://keysandfingers.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;docs: &lt;a href="https://iamovi.github.io/KeysAndFingers/" rel="noopener noreferrer"&gt;https://iamovi.github.io/KeysAndFingers/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;github: &lt;a href="https://github.com/iamovi/KeysAndFingers" rel="noopener noreferrer"&gt;github.com/iamovi/keysandfingers&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;download windows app: &lt;a href="https://github.com/iamovi/KeysAndFingers/releases/download/v1.1.0/KeysAndFingers-Setup-v1.1.0.exe" rel="noopener noreferrer"&gt;click here&lt;/a&gt; or, visit docs/ gh releases.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;contributions are open. fork it, make a branch, send a pull request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp56fs7quzmun3wnrzwu.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%2Ffp56fs7quzmun3wnrzwu.png" alt="window preview" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>react</category>
      <category>opensource</category>
    </item>
    <item>
      <title>anilogin: a reactive authentication ui with anime character gaze tracking</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Mon, 16 Feb 2026 14:38:28 +0000</pubDate>
      <link>https://dev.to/iamovi/anilogin-a-reactive-authentication-ui-with-anime-character-gaze-tracking-1nb9</link>
      <guid>https://dev.to/iamovi/anilogin-a-reactive-authentication-ui-with-anime-character-gaze-tracking-1nb9</guid>
      <description>&lt;h1&gt;
  
  
  authentication forms are usually boring. text fields, a submit button, maybe some validation messages. but what if your login page could feel alive? what if an anime character reacted to what you typed?
&lt;/h1&gt;

&lt;p&gt;that's exactly what anilogin does.&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%2Fko77tatxo6oa9rnsci7h.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%2Fko77tatxo6oa9rnsci7h.png" alt="preview" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  what is anilogin?
&lt;/h2&gt;

&lt;p&gt;anilogin is a reactive authentication interface that features an animated japanese anime character who responds to your typing in real-time. the character watches what you type in the email field, politely closes their eyes when you enter your password, blinks naturally, and displays contextual thought bubbles based on your interactions.&lt;/p&gt;

&lt;p&gt;you can try the live demo here: &lt;a href="https://iamovi.github.io/AniLogin/" rel="noopener noreferrer"&gt;https://iamovi.github.io/AniLogin/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  technical implementation
&lt;/h2&gt;

&lt;p&gt;the project is built with modern web technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;react with typescript for type safety and component architecture&lt;/li&gt;
&lt;li&gt;vite for blazing fast development and optimized builds&lt;/li&gt;
&lt;li&gt;tailwind css and shadcn/ui for consistent, responsive design&lt;/li&gt;
&lt;li&gt;custom animation logic for character interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  the character system
&lt;/h3&gt;

&lt;p&gt;the most interesting part of this project is the character animation system. it's not just a static image with some basic transforms. the implementation includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;context-aware eye animations&lt;/strong&gt;: the character's eyes respond to which input field you're focused on. when you type in the email field, the eyes track your text input. when you switch to the password field, the character respectfully closes their eyes with the thought bubble "I'm closing my eyes! I'm not seeing your pass! 🙈"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;frame-accurate eyelid blinking&lt;/strong&gt;: the character blinks naturally using physics-based timing. the blinks aren't random - they follow realistic patterns that make the character feel alive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cel-shaded anime aesthetic&lt;/strong&gt;: the character design follows authentic japanese animation principles with proper cel-shading techniques, giving it that classic anime look.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dynamic feedback system&lt;/strong&gt;: the thought bubble changes based on what you're doing. typing in different fields, submitting the form - each action triggers contextually relevant thoughts from the character.&lt;/p&gt;

&lt;h2&gt;
  
  
  the interaction algorithm
&lt;/h2&gt;

&lt;p&gt;the core of the interaction is input field tracking. here's how it works conceptually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;detect which input field currently has focus&lt;/li&gt;
&lt;li&gt;track the content being typed in real-time&lt;/li&gt;
&lt;li&gt;apply appropriate character animations based on field type&lt;/li&gt;
&lt;li&gt;for password fields, trigger eye-closing animation&lt;/li&gt;
&lt;li&gt;for email fields, show active watching state&lt;/li&gt;
&lt;li&gt;smooth transitions between states with easing functions&lt;/li&gt;
&lt;li&gt;sync the eyelid animations to maintain natural blinking patterns&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;the result is a character that genuinely seems to be paying attention to what you're typing, while respecting your privacy when entering sensitive information.&lt;/p&gt;

&lt;h2&gt;
  
  
  why build this?
&lt;/h2&gt;

&lt;p&gt;beyond the novelty factor, this project explores several interesting frontend challenges:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;real-time interaction design&lt;/strong&gt;: how do you make animations feel responsive without being distracting? how do you balance personality with privacy?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;performance optimization&lt;/strong&gt;: tracking input events and updating character animations needs to run smoothly without janking the rest of the ui.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;accessibility considerations&lt;/strong&gt;: animated interfaces need careful handling. the character provides visual feedback, but the form itself remains fully functional with or without the animations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;component architecture&lt;/strong&gt;: separating the character logic from the form logic while keeping them synchronized requires thoughtful component design.&lt;/p&gt;

&lt;h2&gt;
  
  
  getting started
&lt;/h2&gt;

&lt;p&gt;want to run it locally? the setup is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/iamovi/AniLogin.git
&lt;span class="nb"&gt;cd &lt;/span&gt;AniLogin
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the project uses a standard react + vite setup, so if you've worked with modern frontend tooling, you'll feel right at home.&lt;/p&gt;

&lt;h2&gt;
  
  
  potential use cases
&lt;/h2&gt;

&lt;p&gt;while this started as an experimental ui project, there are practical applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;engaging landing pages that need to stand out&lt;/li&gt;
&lt;li&gt;educational platforms where character interaction enhances learning&lt;/li&gt;
&lt;li&gt;gaming-related authentication where the aesthetic matches the product&lt;/li&gt;
&lt;li&gt;portfolio pieces for frontend developers specializing in interactive design&lt;/li&gt;
&lt;li&gt;prototyping tools for testing user engagement with animated interfaces&lt;/li&gt;
&lt;li&gt;privacy-conscious applications that visually demonstrate data protection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  technical details worth noting
&lt;/h2&gt;

&lt;p&gt;the project demonstrates several advanced frontend techniques:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;custom hooks for animation&lt;/strong&gt;: the character system uses custom react hooks to manage animation state, making it reusable and testable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;input event handling&lt;/strong&gt;: form field interactions trigger character state changes smoothly without blocking user input.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;responsive calculations&lt;/strong&gt;: the character animations work consistently across different screen sizes and viewport dimensions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;state management&lt;/strong&gt;: user interactions, character state, and form validation all need to stay synchronized. the architecture handles this without prop drilling or overly complex state patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  the privacy consideration
&lt;/h2&gt;

&lt;p&gt;one of the most thoughtful aspects of anilogin is how it handles password entry. when you focus on the password field, the character immediately closes their eyes and displays a reassuring message. this isn't just a cute animation - it's a visual metaphor for privacy and security that helps build trust with users.&lt;/p&gt;

&lt;h2&gt;
  
  
  final thoughts
&lt;/h2&gt;

&lt;p&gt;anilogin shows that authentication doesn't have to be purely functional. with thoughtful design and solid technical implementation, even something as mundane as a login form can become memorable and build user trust through personality.&lt;/p&gt;

&lt;p&gt;the code is open source under the mit license, so feel free to fork it, learn from it, or build something entirely new with the concepts.&lt;/p&gt;

&lt;p&gt;check out the live demo: &lt;a href="https://iamovi.github.io/AniLogin/" rel="noopener noreferrer"&gt;https://iamovi.github.io/AniLogin/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;grab the source: &lt;a href="https://github.com/iamovi/AniLogin" rel="noopener noreferrer"&gt;https://github.com/iamovi/AniLogin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;what would you add to make it even more engaging? drop your thoughts below.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>i built runtexts - a cli tool for automating message sending</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sun, 08 Feb 2026 15:29:53 +0000</pubDate>
      <link>https://dev.to/iamovi/i-built-runtexts-a-cli-tool-for-automating-message-sending-3g12</link>
      <guid>https://dev.to/iamovi/i-built-runtexts-a-cli-tool-for-automating-message-sending-3g12</guid>
      <description>&lt;p&gt;&lt;strong&gt;so i made this thing called &lt;code&gt;runtexts&lt;/code&gt;. it's a python cli tool that automates typing and sending messages. basically you tell it what to type, how many times, and how fast, and it does it for you.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  similar project with nodejs &lt;code&gt;ssspeedx&lt;/code&gt;
&lt;/h3&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%2Fy5fnnuzqotz1dj1s0x3t.gif" 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%2Fy5fnnuzqotz1dj1s0x3t.gif" alt="ssspeedx preview" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  what it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;sends messages automatically with custom delays&lt;/li&gt;
&lt;li&gt;simulates typing (fast bot mode or slow human mode)&lt;/li&gt;
&lt;li&gt;has both cli and gui interfaces&lt;/li&gt;
&lt;li&gt;can run infinitely or for a set number of times&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  why i built it
&lt;/h2&gt;

&lt;p&gt;honestly i got tired of manually testing chat interfaces during development. needed something quick to spam test messages without wearing out my keyboard. turned it into a proper package because why not.&lt;/p&gt;

&lt;h2&gt;
  
  
  how to use it
&lt;/h2&gt;

&lt;p&gt;install from pip:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;runtexts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or install manually from github:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/iamovi/project_runtexts.git
&lt;span class="nb"&gt;cd &lt;/span&gt;project_runtexts
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;runtexts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or use the gui:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;runtexts gui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;python&lt;/li&gt;
&lt;li&gt;pyautogui for keyboard automation&lt;/li&gt;
&lt;li&gt;tkinter for the gui&lt;/li&gt;
&lt;li&gt;packaged for pypi&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  legitimate use cases
&lt;/h2&gt;

&lt;p&gt;before someone asks - yes this can be misused. don't do that. use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing chat applications you're building&lt;/li&gt;
&lt;li&gt;automated testing scenarios&lt;/li&gt;
&lt;li&gt;learning automation basics&lt;/li&gt;
&lt;li&gt;any situation where you have permission to send bulk messages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  important
&lt;/h2&gt;

&lt;p&gt;don't use this for spam, harassment, or anything shady. only use it on platforms and applications where you have explicit permission. violating terms of service or annoying people isn't cool. this tool is for legitimate automation and testing purposes only.&lt;/p&gt;

&lt;h2&gt;
  
  
  what i learned
&lt;/h2&gt;

&lt;p&gt;dealing with cross-platform keyboard automation has its quirks. building a simple gui that doesn't look terrible takes more effort than expected. pyautogui behavior varies slightly across different operating systems.&lt;/p&gt;

&lt;p&gt;the code is on github if you want to check it out or contribute: &lt;a href="https://github.com/iamovi/project_runtexts" rel="noopener noreferrer"&gt;https://github.com/iamovi/project_runtexts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;that's it. hope someone finds it useful.&lt;/p&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>node</category>
    </item>
    <item>
      <title>snakension - a browser extension for playing snake when you're offline</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sat, 07 Feb 2026 09:15:42 +0000</pubDate>
      <link>https://dev.to/iamovi/snakension-a-browser-extension-for-playing-snake-when-youre-offline-1kfk</link>
      <guid>https://dev.to/iamovi/snakension-a-browser-extension-for-playing-snake-when-youre-offline-1kfk</guid>
      <description>&lt;p&gt;&lt;strong&gt;play snake when your internet dies with this extension,&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ever lost your internet connection and wished you had something to do? that's what snakension is for. it's a browser extension that gives you the classic snake game right in your browser, and it automatically notifies you to play when you go offline.&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%2Fu0tca3qgv9xp1j4vkb8z.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%2Fu0tca3qgv9xp1j4vkb8z.png" alt="snakension preview" width="488" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  what it does
&lt;/h2&gt;

&lt;p&gt;snakension is straightforward. it sits in your browser extensions and lets you play snake whenever you want. the neat part is that it detects when you lose your internet connection and sends you a notification suggesting you play the game while you wait for your connection to come back.&lt;/p&gt;

&lt;p&gt;the extension saves your high score locally, so you can keep track of your best performance. the game itself is clean and responsive with smooth controls.&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%2Ff28onen8ui4ulbqtkaun.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%2Ff28onen8ui4ulbqtkaun.png" alt="offline notification" width="492" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  how to install it
&lt;/h2&gt;

&lt;p&gt;since this isn't on the chrome web store yet, you'll need to install it manually. here's how:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;download the &lt;a href="https://github.com/iamovi/snakension/releases/latest" rel="noopener noreferrer"&gt;zip file&lt;/a&gt; from the latest release&lt;/li&gt;
&lt;li&gt;unzip the file somewhere on your computer&lt;/li&gt;
&lt;li&gt;open your browser's extensions page:

&lt;ul&gt;
&lt;li&gt;chrome: &lt;code&gt;chrome://extensions/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;edge: &lt;code&gt;edge://extensions/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;brave: &lt;code&gt;brave://extensions/&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;enable developer mode (usually a toggle in the top right)&lt;/li&gt;
&lt;li&gt;click "load unpacked"&lt;/li&gt;
&lt;li&gt;select the unzipped snakension folder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;that's it. the extension will now appear in your toolbar.&lt;/p&gt;

&lt;h2&gt;
  
  
  features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;offline detection that sends notifications when you lose internet&lt;/li&gt;
&lt;li&gt;saves your high score&lt;/li&gt;
&lt;li&gt;responsive controls for smooth gameplay&lt;/li&gt;
&lt;li&gt;clean, simple interface&lt;/li&gt;
&lt;li&gt;works on chrome, edge, and brave&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  what makes this different
&lt;/h2&gt;

&lt;p&gt;you might be thinking "i can just play snake in a browser tab." true, but here's why snakension is different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;automatic offline detection&lt;/strong&gt; - it actively notifies you when you go offline, turning a frustrating moment into an opportunity to play&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;always accessible&lt;/strong&gt; - it's pinned to your browser toolbar, no need to bookmark a site or remember a url&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;works completely offline&lt;/strong&gt; - unlike web-based games, this doesn't need any internet connection at all once installed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;no distractions&lt;/strong&gt; - just the game, no ads, no tracking, no unnecessary features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;it's about having something useful built right into your browser that's actually there when you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  what's coming next
&lt;/h2&gt;

&lt;p&gt;i'm planning to expand it into a mini arcade with more classic games added over time.&lt;br&gt;
the goal is to make this a go-to offline gaming hub in your browser. contributions are welcome - if you have suggestions for games or want to help build them, open an issue on github.&lt;/p&gt;

&lt;h2&gt;
  
  
  the tech
&lt;/h2&gt;

&lt;p&gt;it's built with vanilla javascript, html, and css. no frameworks, no dependencies. the game logic is classic snake - you move around collecting food, growing longer, and trying not to crash into yourself or the walls.&lt;/p&gt;

&lt;p&gt;the background script handles the offline detection by listening to the browser's connection status. when it detects you've gone offline, it triggers a notification that opens the game.&lt;/p&gt;

&lt;h2&gt;
  
  
  open source
&lt;/h2&gt;

&lt;p&gt;the whole thing is open source under the mit license. you can check out the code, fork it, modify it, or contribute on &lt;a href="https://github.com/iamovi/snakension" rel="noopener noreferrer"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;if you're interested in building browser extensions or just want a simple game to play when your internet drops, give it a try.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://iamovi.github.io/snakension/" rel="noopener noreferrer"&gt;visit the project page&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>i turned my portfolio into a bootable operating system (windows portfolio)</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Thu, 05 Feb 2026 12:58:05 +0000</pubDate>
      <link>https://dev.to/iamovi/i-turned-my-portfolio-into-a-bootable-operating-system-windows-portfolio-2h1f</link>
      <guid>https://dev.to/iamovi/i-turned-my-portfolio-into-a-bootable-operating-system-windows-portfolio-2h1f</guid>
      <description>&lt;h2&gt;
  
  
  tfish (a windows themed portfolio template with fully functional terminal and other features)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a portfolio that boots like an actual computer&lt;/strong&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%2F0f4c01bu7l0vzp5vn4ft.gif" 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%2F0f4c01bu7l0vzp5vn4ft.gif" alt="tfish demo" width="600" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;live demo:&lt;/strong&gt; &lt;a href="https://iamovi.github.io/tfish/" rel="noopener noreferrer"&gt;iamovi.github.io/tfish&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;source code:&lt;/strong&gt; &lt;a href="https://github.com/iamovi/tfish" rel="noopener noreferrer"&gt;github.com/iamovi/tfish&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  the backstory
&lt;/h2&gt;

&lt;p&gt;i wanted to make a portfolio. but not just any portfolio. i wanted something that would make people go "wait, what?" when they opened it.&lt;/p&gt;

&lt;p&gt;so i built tfish - a fully interactive terminal-based portfolio that simulates an entire operating system experience. complete with BIOS boot sequence, login screen, draggable desktop icons, and a functional terminal.&lt;/p&gt;

&lt;p&gt;because why show your projects in a normal grid layout when you can make people boot into your portfolio like it's 1995?&lt;/p&gt;
&lt;h2&gt;
  
  
  what makes it different
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;it's not just themed, it actually boots&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;most "terminal-style" portfolios are just green text on a black background. tfish goes further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BIOS boot sequence with that authentic loading feel&lt;/li&gt;
&lt;li&gt;actual login screen (username: user, password: pass)&lt;/li&gt;
&lt;li&gt;draggable desktop icons that you can move around&lt;/li&gt;
&lt;li&gt;working start menu with themes and wallpaper options&lt;/li&gt;
&lt;li&gt;multiple terminal themes (ubuntu, windows cmd, powershell, hacker, retro)&lt;/li&gt;
&lt;li&gt;customizable wallpapers&lt;/li&gt;
&lt;li&gt;window management with minimize/maximize/close&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;built with modern tech&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;under the hood, it's React + TypeScript + Vite. shadcn/ui for components. tailwind for styling. everything you'd expect from a 2025 web app, packaged in a throwback OS interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  the terminal commands
&lt;/h2&gt;

&lt;p&gt;once you boot in, you can use actual commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;help&lt;/code&gt; - see all available commands&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;about&lt;/code&gt; - learn about me (shows a profile picture and bio)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;skills&lt;/code&gt; - view technical skills&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;projects&lt;/code&gt; - browse my projects&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resume&lt;/code&gt; - download my resume&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contact&lt;/code&gt; - get contact information&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;waifu&lt;/code&gt; - fetch random waifu in the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;joke&lt;/code&gt; - fetch jokes in terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clear&lt;/code&gt; - clear the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exit&lt;/code&gt; - close the terminal&lt;/li&gt;
&lt;li&gt;more commands will be added...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;type them in. it feels real. that's the point.&lt;/p&gt;
&lt;h2&gt;
  
  
  screenshots
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;boot sequence&lt;/th&gt;
&lt;th&gt;desktop view&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2Fg1gubtfsgwtbtoxolxlk.png" alt="i" width="800" height="450"&gt;&lt;/td&gt;
&lt;td&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%2Fferhfud2swhm2i885rje.png" alt="ii" width="800" height="450"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;terminal view&lt;/th&gt;
&lt;th&gt;themes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2Fvp7v3wsr4y4xxpgch8jz.png" alt="iii" width="800" height="450"&gt;&lt;/td&gt;
&lt;td&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%2Fro2vh0spo0ek98uwjgfo.png" alt="iv" width="800" height="450"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  how to use it yourself
&lt;/h2&gt;

&lt;p&gt;yes, it's a template. yes, you can use it for your own portfolio. here's how:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# clone it&lt;/span&gt;
git clone https://github.com/iamovi/tfish.git
&lt;span class="nb"&gt;cd &lt;/span&gt;tfish

&lt;span class="c"&gt;# install dependencies&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="c"&gt;# or&lt;/span&gt;
bun &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# run it&lt;/span&gt;
npm run dev
&lt;span class="c"&gt;# or&lt;/span&gt;
bun dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then customize it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. update your info in &lt;code&gt;src/components/Terminal.tsx&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;change the welcome message, about section, skills, projects, and contact info. it's all in one file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. change the username&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;replace 'ren' with your username throughout the terminal prompts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. update the login screen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;edit &lt;code&gt;src/components/LoginScreen.tsx&lt;/code&gt; with your name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. swap the wallpaper&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;replace &lt;code&gt;public/frieren.jpg&lt;/code&gt; with your own image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. customize desktop icons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;edit &lt;code&gt;src/components/DesktopIcons.tsx&lt;/code&gt; to add or remove icons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. add your own commands&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;create new terminal commands in the COMMANDS object.&lt;/p&gt;

&lt;p&gt;full customization guide is in the &lt;a href="https://github.com/iamovi/tfish" rel="noopener noreferrer"&gt;github readme&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  adding your own terminal theme
&lt;/h2&gt;

&lt;p&gt;want a custom theme? add it to the theme switcher:&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="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yourtheme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// background&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// text color&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@host:~$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// prompt&lt;/span&gt;
    &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Your Theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// window title&lt;/span&gt;
    &lt;span class="na"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WELCOME_MESSAGE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;caret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#ffffff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;         &lt;span class="c1"&gt;// cursor&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;i've included ubuntu, windows cmd, powershell, hacker, and retro themes by default. make your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  deployment
&lt;/h2&gt;

&lt;p&gt;build it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;span class="c"&gt;# or&lt;/span&gt;
bun run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;deploy the &lt;code&gt;dist&lt;/code&gt; folder to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vercel&lt;/li&gt;
&lt;li&gt;netlify&lt;/li&gt;
&lt;li&gt;github pages&lt;/li&gt;
&lt;li&gt;anywhere that hosts static sites&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  why did i make this
&lt;/h2&gt;

&lt;p&gt;honestly? because tech portfolios have gotten boring. everyone has the same hero section, the same project cards, the same "scroll down to learn more" animation.&lt;/p&gt;

&lt;p&gt;i wanted something that felt different. something that made you interact with it. something that reminded you of the first time you opened a command line and felt like a hacker.&lt;/p&gt;

&lt;p&gt;also, i just really like terminals.&lt;/p&gt;

&lt;h2&gt;
  
  
  coming soon
&lt;/h2&gt;

&lt;p&gt;i'm actively working on adding more features to make this even more immersive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;youtube player&lt;/strong&gt; - watch videos without leaving the OS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;music player&lt;/strong&gt; - play your favorite tracks in the background&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;file explorer&lt;/strong&gt; - browse through a simulated file system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;notepad&lt;/strong&gt; - take notes in a classic text editor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;calculator&lt;/strong&gt; - because every OS needs one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;games&lt;/strong&gt; - maybe some retro games to kill time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;custom apps&lt;/strong&gt; - build and add your own desktop applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;this project is actively maintained, so expect regular updates with new features!&lt;/p&gt;

&lt;h2&gt;
  
  
  the tech stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;react&lt;/strong&gt; - component framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;typescript&lt;/strong&gt; - type safety&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vite&lt;/strong&gt; - build tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tailwind css&lt;/strong&gt; - styling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;shadcn/ui&lt;/strong&gt; - ui components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;lucide-react&lt;/strong&gt; - icons&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  try it yourself
&lt;/h2&gt;

&lt;p&gt;live demo: &lt;a href="https://iamovi.github.io/tfish/" rel="noopener noreferrer"&gt;iamovi.github.io/tfish&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;source code: &lt;a href="https://github.com/iamovi/tfish" rel="noopener noreferrer"&gt;github.com/iamovi/tfish&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  contributions
&lt;/h2&gt;

&lt;p&gt;it's open source (MIT license). fork it. break it. make it better. send a PR. i'm open to new themes, new commands, new features.&lt;/p&gt;

&lt;p&gt;if you end up using this for your portfolio, i'd love to see it. tag me or send a link.&lt;/p&gt;

&lt;h2&gt;
  
  
  final thoughts
&lt;/h2&gt;

&lt;p&gt;tfish is what happens when you combine nostalgia for old operating systems with modern web development. it's a portfolio that doesn't take itself too seriously but still looks professional enough to send to actual employers.&lt;/p&gt;

&lt;p&gt;it's for developers who want their portfolio to be a conversation starter. who want people to remember them because they had "that terminal portfolio that actually boots."&lt;/p&gt;

&lt;p&gt;use it. customize it. make it yours.&lt;/p&gt;

&lt;p&gt;that's all. go boot your portfolio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;live demo:&lt;/strong&gt; &lt;a href="https://iamovi.github.io/tfish/" rel="noopener noreferrer"&gt;iamovi.github.io/tfish&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;source code:&lt;/strong&gt; &lt;a href="https://github.com/iamovi/tfish" rel="noopener noreferrer"&gt;github.com/iamovi/tfish&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;made with ❤️ by &lt;a href="https://github.com/iamovi" rel="noopener noreferrer"&gt;ovi ren&lt;/a&gt;, for developers who appreciate a good terminal&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>i made buttons that run away from you (prank projects)</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Tue, 27 Jan 2026 17:38:00 +0000</pubDate>
      <link>https://dev.to/iamovi/i-made-buttons-that-run-away-from-you-prank-projects-5ej0</link>
      <guid>https://dev.to/iamovi/i-made-buttons-that-run-away-from-you-prank-projects-5ej0</guid>
      <description>&lt;h2&gt;
  
  
  button-will-react
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;a collection of untouchable buttons that will make your users question their clicking abilities&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  so here's the thing
&lt;/h2&gt;

&lt;p&gt;two years ago i created a project called button-will-react. i've been adding new pranks to it regularly since then. but writing about it? that's the part i've been procrastinating on. now here we are.&lt;/p&gt;

&lt;p&gt;the concept is simple: what if buttons just... didn't let you click them? what if they had a mind of their own and decided that your cursor wasn't worthy? revolutionary stuff, i know.&lt;/p&gt;

&lt;h2&gt;
  
  
  what's in the box
&lt;/h2&gt;

&lt;p&gt;this collection includes 10 + different button pranks, each more annoying than the last:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. sign-in button&lt;/strong&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%2Fjwmkt1iautyztzszbc8r.gif" 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%2Fjwmkt1iautyztzszbc8r.gif" alt="sign-in button demo" width="600" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;an untouchable sign-in button. try clicking it. try using enter. it will throw an alert at you like it's personally offended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. propose&lt;/strong&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%2F3pwcujirsmm395ssg7bp.gif" 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%2F3pwcujirsmm395ssg7bp.gif" alt="propose button demo" width="600" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the classic "will you be my valentine" but the "no" button is impossible to click. because consent is important, but also, your partner should say yes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. valentine&lt;/strong&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%2Fizq5aclz2dy84vc2kw7z.gif" 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%2Fizq5aclz2dy84vc2kw7z.gif" alt="valentine button demo" width="600" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;a fun way to propose on valentine's day. assuming you want your relationship to start with mild frustration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. get_partner&lt;/strong&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%2Flvb6uuiej3a0tcxei179.gif" 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%2Flvb6uuiej3a0tcxei179.gif" alt="get_partner demo" width="600" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;enter your preferences and get a partner (spoiler: it's me).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. love_on_hover&lt;/strong&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%2F73w0gk8k73m9bovag2ij.gif" 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%2F73w0gk8k73m9bovag2ij.gif" alt="love_on_hover demo" width="600" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;contributed by &lt;a href="https://github.com/tahsinzidane" rel="noopener noreferrer"&gt;tahsin zidane&lt;/a&gt;. hover and get love. it's the most wholesome one here, which isn't saying much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. boom_btn&lt;/strong&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%2Fkl102cyzag03wcic2i6k.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%2Fkl102cyzag03wcic2i6k.png" alt="boom_btn demo" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;click the button and boom. i won't tell you what happens. that would ruin the surprise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. love_on_hover_v2&lt;/strong&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%2F2xgtw1osq798gh6xrpwu.gif" 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%2F2xgtw1osq798gh6xrpwu.gif" alt="love_on_hover_v2 demo" width="426" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/tahsinzidane" rel="noopener noreferrer"&gt;tahsin zidane&lt;/a&gt; strikes again with version 2. because why make one when you can make two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. starboy69&lt;/strong&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%2Fyhnbmi3p6e3fr7r5cdwf.gif" 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%2Fyhnbmi3p6e3fr7r5cdwf.gif" alt="starboy69 demo" width="600" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;an internet meme login project. if you know, you know.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. button_lol&lt;/strong&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%2Frfap4bkk8kx86dy9mqqh.gif" 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%2Frfap4bkk8kx86dy9mqqh.gif" alt="button_lol demo" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inspired from Project 1 but with a different approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. cursor_possession&lt;/strong&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%2Fsokz4ywn3q5v3zkoypxf.gif" 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%2Fsokz4ywn3q5v3zkoypxf.gif" alt="cursor_possession demo" width="760" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;your cursor afraid of button. lol.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;em&gt;THIS PROJECT IS ACTIVELY MAINTAINED, NEW PROJECTS WILL BE ADDED REGULAR, LOOK FOR NEW PROJECT IN PROJECT GITHUB REPOSITORY!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  use it yourself (because why not)
&lt;/h2&gt;

&lt;p&gt;here's the plot twist: you can actually add this to your own projects with a cdn. because apparently i thought "let me make this easy for other people to annoy their users too."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/gh/iamovi/button-will-react@cdn/dist/min/v1.0.0/move.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"button_will_react"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;click me!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that's it. add the class &lt;code&gt;button_will_react&lt;/code&gt; to any button and watch your conversion rates drop.&lt;/p&gt;

&lt;h2&gt;
  
  
  why though
&lt;/h2&gt;

&lt;p&gt;honestly? because it's funny. because sometimes web development should be about making people smile (or scream in frustration). because not everything needs to be a serious productivity tool or a groundbreaking framework.&lt;/p&gt;

&lt;p&gt;it's harmless. it's silly. it's been sitting in my github for two years collecting dust and a respectable 23 stars from people who also appreciate chaos.&lt;/p&gt;

&lt;h2&gt;
  
  
  try it
&lt;/h2&gt;

&lt;p&gt;the project is live at &lt;a href="https://iamovi.github.io/button-will-react/" rel="noopener noreferrer"&gt;iamovi.github.io/button-will-react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the code is on github at &lt;a href="https://github.com/iamovi/button-will-react" rel="noopener noreferrer"&gt;github.com/iamovi/button-will-react&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it's mit licensed, which means you can do whatever you want with it. use it for pranks. use it for april fools. use it to test your users' patience. i won't judge. and yes, i'm still adding more pranks to the collection, so check back occasionally if you're into that sort of thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  contributions and open source
&lt;/h2&gt;

&lt;p&gt;this project is fully open source under the mit license. that means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use it for personal projects&lt;/li&gt;
&lt;li&gt;use it commercially &lt;/li&gt;
&lt;li&gt;modify it however you want&lt;/li&gt;
&lt;li&gt;fork it and make it your own&lt;/li&gt;
&lt;li&gt;no attribution required (though always appreciated)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;basically, do whatever you want with it. turn it into a library. use it for your portfolio. prank your friends. integrate it into your company's internal tools. i don't care, it's yours now.&lt;/p&gt;

&lt;p&gt;shoutout to &lt;a href="https://github.com/tahsinzidane" rel="noopener noreferrer"&gt;tahsin zidane&lt;/a&gt; for contributing the love_on_hover projects. turns out other people also enjoy making buttons that mess with users.&lt;/p&gt;

&lt;p&gt;want to add your own button prank? pull requests are welcome. the only requirements: it has to be harmless and funny. malicious code stays out, chaos is welcome in.&lt;/p&gt;

&lt;h2&gt;
  
  
  author
&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%2Favatars.githubusercontent.com%2Fu%2F137372623%3Fv%3D4" 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%2Favatars.githubusercontent.com%2Fu%2F137372623%3Fv%3D4" alt="Ovi" width="460" height="460"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/iamovi" rel="noopener noreferrer"&gt;Ovi ren&lt;/a&gt;&lt;br&gt;
main creator and developer of the button-will-react project&lt;/p&gt;

&lt;h2&gt;
  
  
  final thoughts
&lt;/h2&gt;

&lt;p&gt;if you're looking for a serious, production-ready ui component library, this isn't it. but if you want to add a little chaos to your next project, or just need a good laugh, give it a try.&lt;/p&gt;

&lt;p&gt;i keep adding new button pranks when inspiration strikes (or when i should be doing something more productive). because apparently this is what i do with my free time.&lt;/p&gt;

&lt;p&gt;that's all. go forth and make some buttons that refuse to be clicked.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>html</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Glitch - A Modern Animated Portfolio Template</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Sun, 25 Jan 2026 07:20:17 +0000</pubDate>
      <link>https://dev.to/iamovi/glitch-a-modern-animated-portfolio-template-5108</link>
      <guid>https://dev.to/iamovi/glitch-a-modern-animated-portfolio-template-5108</guid>
      <description>&lt;p&gt;&lt;strong&gt;I recently built a portfolio template called Glitch, and I wanted to share it with the dev community. It's designed for developers and creatives who want something more engaging than the usual portfolio sites but don't want to sacrifice performance.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;You can check it out live here: &lt;a href="https://iamovi.github.io/glitch" rel="noopener noreferrer"&gt;iamovi.github.io/glitch&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;Most portfolio templates fall into two camps - either they're super minimal and boring, or they're packed with animations that tank performance. I wanted something in between. Something that feels modern and interactive but still loads fast and runs smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's inside
&lt;/h2&gt;

&lt;p&gt;Here's what I used to build it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React 18 + Vite + TypeScript&lt;/li&gt;
&lt;li&gt;GSAP for animations (it's just really good at this)&lt;/li&gt;
&lt;li&gt;Tailwind CSS for styling&lt;/li&gt;
&lt;li&gt;shadcn/ui components&lt;/li&gt;
&lt;li&gt;Framer Motion for some declarative animations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Glitch text effects (hence the name)&lt;/li&gt;
&lt;li&gt;Magnetic buttons that react to your cursor&lt;/li&gt;
&lt;li&gt;Smooth scroll animations&lt;/li&gt;
&lt;li&gt;Fully responsive&lt;/li&gt;
&lt;li&gt;Pretty decent performance thanks to GSAP's context API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;It's pretty standard React stuff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/iamovi/glitch.git
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use bun if that's your thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it yours
&lt;/h2&gt;

&lt;p&gt;All the content lives in &lt;code&gt;src/components/sections/&lt;/code&gt;. Just update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Hero.tsx&lt;/code&gt; - your name and what you do&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;About.tsx&lt;/code&gt; - bio and skills&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Work.tsx&lt;/code&gt; - add your projects to the array&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Contact.tsx&lt;/code&gt; - email and socials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For styling, the theme is in &lt;code&gt;tailwind.config.ts&lt;/code&gt; and global styles are in &lt;code&gt;src/index.css&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Standard Vite build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything ends up in &lt;code&gt;dist/&lt;/code&gt; ready to deploy wherever you host static sites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some notes
&lt;/h2&gt;

&lt;p&gt;The animations use GSAP ScrollTrigger which is really powerful once you get the hang of it. I tried to keep the code pretty clean so it's easier to understand if you want to modify things or learn from it.&lt;/p&gt;

&lt;p&gt;It's all MIT licensed so feel free to use it however you want. The repo is here: &lt;a href="https://github.com/iamovi/glitch" rel="noopener noreferrer"&gt;github.com/iamovi/glitch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you end up using it or have suggestions for improvements.&lt;/p&gt;




&lt;p&gt;Made by &lt;a href="https://iamovi.github.io" rel="noopener noreferrer"&gt;Ovi ren&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>gsap</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>repoana - github repository health analyzer</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Fri, 23 Jan 2026 13:57:51 +0000</pubDate>
      <link>https://dev.to/iamovi/repoana-github-repository-health-analyzer-1lbl</link>
      <guid>https://dev.to/iamovi/repoana-github-repository-health-analyzer-1lbl</guid>
      <description>&lt;h2&gt;
  
  
  what is repoana?
&lt;/h2&gt;

&lt;p&gt;repoana is a web application that analyzes any public github repository and gives it a health score from 0 to 100. it breaks down the analysis into five key categories and provides specific recommendations for improvement.&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%2Flcs9cmcm5vwuiwvo4xqf.gif" 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%2Flcs9cmcm5vwuiwvo4xqf.gif" alt="repoana preview gif" width="720" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  why i built this
&lt;/h2&gt;

&lt;p&gt;as a developer, i often wonder how healthy a repository is before deciding to use it or contribute to it. is it actively maintained? does it have good documentation? is the community engaged? repoana answers these questions instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  how it works
&lt;/h2&gt;

&lt;p&gt;just paste any github repository url and get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;overall health score&lt;/strong&gt;: a comprehensive 0-100 rating&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;category breakdown&lt;/strong&gt;: detailed scores across five areas:

&lt;ul&gt;
&lt;li&gt;documentation quality&lt;/li&gt;
&lt;li&gt;code quality&lt;/li&gt;
&lt;li&gt;maintenance status&lt;/li&gt;
&lt;li&gt;community engagement&lt;/li&gt;
&lt;li&gt;activity level&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;smart recommendations&lt;/strong&gt;: prioritized suggestions for improvement&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  technical details
&lt;/h2&gt;

&lt;p&gt;built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;react for the ui&lt;/li&gt;
&lt;li&gt;vite for fast development&lt;/li&gt;
&lt;li&gt;github rest api for data&lt;/li&gt;
&lt;li&gt;lucide react for icons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the scoring algorithm weighs different factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;documentation (25%): readme, license, contributing guidelines, templates&lt;/li&gt;
&lt;li&gt;code quality (20%): issue close rate, pr merge rate, response times&lt;/li&gt;
&lt;li&gt;maintenance (25%): commit frequency, contributor activity, last update&lt;/li&gt;
&lt;li&gt;community (15%): stars, forks, watchers, health metrics&lt;/li&gt;
&lt;li&gt;activity (15%): recent issues, prs, and commits&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  try it out
&lt;/h2&gt;

&lt;p&gt;live demo: &lt;a href="https://iamovi.github.io/repoana/" rel="noopener noreferrer"&gt;https://iamovi.github.io/repoana/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;no signup required. works with any public github repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  github api limits
&lt;/h2&gt;

&lt;p&gt;works without authentication (60 requests/hour). for power users, add a github personal access token to get 5,000 requests/hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  source code
&lt;/h2&gt;

&lt;p&gt;the project is open source under mit license.&lt;/p&gt;

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

&lt;p&gt;contributions welcome. if you find it useful, consider giving it a star.&lt;/p&gt;

&lt;h2&gt;
  
  
  future plans
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;historical tracking of health scores&lt;/li&gt;
&lt;li&gt;comparison between multiple repositories&lt;/li&gt;
&lt;li&gt;export reports as pdf&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;made by &lt;a href="https://github.com/iamovi" rel="noopener noreferrer"&gt;@iamovi&lt;/a&gt;&lt;br&gt;
under MIT license.&lt;/p&gt;

</description>
      <category>github</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Zappp ⚡ - A Lightning-Fast Alternative to VS Code Live Server</title>
      <dc:creator>Ovi ren</dc:creator>
      <pubDate>Tue, 20 Jan 2026 12:45:10 +0000</pubDate>
      <link>https://dev.to/iamovi/zappp-a-lightning-fast-alternative-to-vs-code-live-server-17hb</link>
      <guid>https://dev.to/iamovi/zappp-a-lightning-fast-alternative-to-vs-code-live-server-17hb</guid>
      <description>&lt;p&gt;Ever wished you had VS Code's Live Server extension as a standalone CLI tool? Meet &lt;strong&gt;Zappp&lt;/strong&gt; - a simple, fast static file server with live reload functionality that you can run from anywhere.&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%2Fn1q9e892fhcub43czydf.jpg" 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%2Fn1q9e892fhcub43czydf.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built Zappp
&lt;/h2&gt;

&lt;p&gt;As developers, we've all been there: you're working on a quick HTML/CSS/JS project, need to test it locally, and reach for Python's SimpleHTTPServer or VS Code's Live Server. But what if you're not in VS Code? What if you want something you can run from any terminal, on any project, instantly?&lt;/p&gt;

&lt;p&gt;That's why I created Zappp - a zero-configuration development server that just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features That Make Development Easier
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚀 Zero Configuration
&lt;/h3&gt;

&lt;p&gt;No config files, no setup. Just run &lt;code&gt;zappp&lt;/code&gt; and you're live.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappp
&lt;span class="c"&gt;# Server running at http://localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🔄 Automatic Live Reload
&lt;/h3&gt;

&lt;p&gt;Edit your files and watch the browser refresh automatically. No manual reloading, no browser extensions needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  📁 Beautiful Directory Listing
&lt;/h3&gt;

&lt;p&gt;No index.html? No problem. Zappp shows you a clean directory listing so you can navigate your project easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 Network Accessible
&lt;/h3&gt;

&lt;p&gt;Want to test on your phone or share with a colleague? Zappp binds to &lt;code&gt;0.0.0.0&lt;/code&gt; by default, making your dev server accessible on your local network.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎨 Developer-Friendly Error Pages
&lt;/h3&gt;

&lt;p&gt;Beautiful, informative error pages help you debug issues faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔒 Built-in Security
&lt;/h3&gt;

&lt;p&gt;Protection against directory traversal attacks keeps your file system safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;Install globally with npm:&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; &lt;span class="nt"&gt;-g&lt;/span&gt; zappp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You're ready to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usage Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Basic Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start server in current directory&lt;/span&gt;
zappp

&lt;span class="c"&gt;# Serve a specific directory&lt;/span&gt;
zappp ./dist

&lt;span class="c"&gt;# Custom port&lt;/span&gt;
zappp &lt;span class="nt"&gt;-p&lt;/span&gt; 8080

&lt;span class="c"&gt;# Open browser automatically&lt;/span&gt;
zappp &lt;span class="nt"&gt;-o&lt;/span&gt;

&lt;span class="c"&gt;# Combine options&lt;/span&gt;
zappp ./public &lt;span class="nt"&gt;-p&lt;/span&gt; 5000 &lt;span class="nt"&gt;-o&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Quick HTML Prototype&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-landing-page
zappp &lt;span class="nt"&gt;-o&lt;/span&gt;
&lt;span class="c"&gt;# Browser opens automatically, live reload active&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario 2: Testing on Mobile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappp &lt;span class="nt"&gt;-h&lt;/span&gt; 0.0.0.0
&lt;span class="c"&gt;# Visit http://192.168.1.x:3000 on your phone&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scenario 3: Production Build Preview&lt;/strong&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 run build
zappp ./dist &lt;span class="nt"&gt;-p&lt;/span&gt; 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Zappp is built on three core technologies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Node.js HTTP Server&lt;/strong&gt; - Fast, reliable static file serving&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File System Watcher&lt;/strong&gt; - Detects changes in your project&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebSocket&lt;/strong&gt; - Real-time communication for live reload&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you run Zappp:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It spins up an HTTP server to serve your files&lt;/li&gt;
&lt;li&gt;A file watcher monitors your directory for changes&lt;/li&gt;
&lt;li&gt;A WebSocket connection is injected into HTML files&lt;/li&gt;
&lt;li&gt;On file change, the server notifies the browser to reload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple, elegant, effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Command Options
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Alias&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--port &amp;lt;number&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Port to use&lt;/td&gt;
&lt;td&gt;3000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--host &amp;lt;host&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Host to bind to&lt;/td&gt;
&lt;td&gt;0.0.0.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--open&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open browser automatically&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--help&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Show help message&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-v&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show version&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Choose Zappp Over Alternatives?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;vs Python SimpleHTTPServer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Live reload built-in&lt;/li&gt;
&lt;li&gt;✅ Faster startup&lt;/li&gt;
&lt;li&gt;✅ Better error handling&lt;/li&gt;
&lt;li&gt;✅ Modern WebSocket-based updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vs VS Code Live Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Works outside VS Code&lt;/li&gt;
&lt;li&gt;✅ Can be used in any terminal&lt;/li&gt;
&lt;li&gt;✅ Programmable (use in npm scripts)&lt;/li&gt;
&lt;li&gt;✅ Lighter weight&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;vs http-server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Live reload included&lt;/li&gt;
&lt;li&gt;✅ Zero configuration&lt;/li&gt;
&lt;li&gt;✅ Simpler CLI interface&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Perfect For
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🎨 Frontend prototyping&lt;/li&gt;
&lt;li&gt;📱 Testing responsive designs&lt;/li&gt;
&lt;li&gt;🧪 Quick experiments&lt;/li&gt;
&lt;li&gt;📚 Local documentation viewing&lt;/li&gt;
&lt;li&gt;🎓 Teaching and demos&lt;/li&gt;
&lt;li&gt;🚀 Build output preview&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Zappp is actively maintained and I'm planning to add more features day by day...&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Today
&lt;/h2&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; &lt;span class="nt"&gt;-g&lt;/span&gt; zappp
&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
zappp &lt;span class="nt"&gt;-o&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give it a spin and let me know what you think! Contributions are welcome on &lt;a href="https://github.com/iamovi/zappp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Involved
&lt;/h2&gt;

&lt;p&gt;⭐ &lt;a href="https://github.com/iamovi/zappp" rel="noopener noreferrer"&gt;Star the repo&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🐛 &lt;a href="https://github.com/iamovi/zappp/issues" rel="noopener noreferrer"&gt;Report issues&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🤝 &lt;a href="https://github.com/iamovi/zappp/pulls" rel="noopener noreferrer"&gt;Contribute&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Happy coding! ⚡&lt;/p&gt;




&lt;h3&gt;
  
  
  Fun Fact
&lt;/h3&gt;

&lt;p&gt;The name of this project zappp is actually inspired from Electro Wizard Character in Clash Royale!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have you tried Zappp? What features would you like to see next? Drop a comment below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cli</category>
      <category>liveserver</category>
      <category>zappp</category>
      <category>vscode</category>
    </item>
  </channel>
</rss>
