<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Project on Vindrin</title><link>https://vindrin.top/project/</link><description>Recent content in Project on Vindrin</description><generator>Hugo</generator><language>en</language><managingEditor>vindrin@outlook.com (Vindrin)</managingEditor><webMaster>vindrin@outlook.com (Vindrin)</webMaster><lastBuildDate>Fri, 10 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://vindrin.top/project/rss.xml" rel="self" type="application/rss+xml"/><item><title>RSS Reader Bot</title><link>https://vindrin.top/project/rss-reader-bot/</link><pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/rss-reader-bot/</guid><description>&lt;h1 id="rss-reader-bot"&gt;RSS Reader Bot&lt;/h1&gt;
&lt;p&gt;A Telegram bot that pulls from your RSS subscriptions and sends you a daily digest.&lt;/p&gt;
&lt;h2 id="problem"&gt;Problem&lt;/h2&gt;
&lt;p&gt;I follow 15+ blogs and news sources. I got tired of checking each site manually. One bot, one message per day.&lt;/p&gt;
&lt;h2 id="architecture"&gt;Architecture&lt;/h2&gt;
&lt;div class="code-block code-line-numbers open" style="counter-reset: code-block 0"&gt;
 &lt;div class="code-header language-"&gt;
 &lt;span class="code-title"&gt;&lt;i class="arrow fas fa-angle-right" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="ellipses"&gt;&lt;i class="fas fa-ellipsis-h" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="copy" title="Copy to clipboard"&gt;&lt;i class="far fa-copy" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RSS feeds → Parser → Deduplication → Digest formatter → Telegram Bot API&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="key-features"&gt;Key features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Add/remove feeds via bot commands (&lt;code&gt;/add&lt;/code&gt;, &lt;code&gt;/remove&lt;/code&gt;, &lt;code&gt;/list&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Daily digest at a configured time&lt;/li&gt;
&lt;li&gt;Mark articles as read&lt;/li&gt;
&lt;li&gt;Filter by keyword&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="setup"&gt;Setup&lt;/h2&gt;
&lt;div class="code-block code-line-numbers open" style="counter-reset: code-block 0"&gt;
 &lt;div class="code-header language-bash"&gt;
 &lt;span class="code-title"&gt;&lt;i class="arrow fas fa-angle-right" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="ellipses"&gt;&lt;i class="fas fa-ellipsis-h" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="copy" title="Copy to clipboard"&gt;&lt;i class="far fa-copy" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install feedparser python-telegram-bot apscheduler
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;TELEGRAM_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_token_here
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;python bot.py&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="status"&gt;Status&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v1.0.0&lt;/code&gt; — Running in production for 2 months. No issues.&lt;/p&gt;</description></item><item><title>Terminal Dashboard</title><link>https://vindrin.top/project/terminal-dashboard/</link><pubDate>Sat, 28 Mar 2026 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/terminal-dashboard/</guid><description>&lt;h1 id="terminal-dashboard"&gt;Terminal Dashboard&lt;/h1&gt;
&lt;p&gt;A real-time system monitor that runs entirely in the terminal.&lt;/p&gt;
&lt;h2 id="why-terminal"&gt;Why terminal?&lt;/h2&gt;
&lt;p&gt;Sometimes you&amp;rsquo;re SSHed into a machine with no GUI. A terminal dashboard gives you CPU, memory, disk, and network stats without installing any heavy monitoring tools.&lt;/p&gt;
&lt;h2 id="built-with"&gt;Built with&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Textual&lt;/strong&gt; — TUI framework&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;psutil&lt;/strong&gt; — system metrics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rich&lt;/strong&gt; — pretty tables and charts&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="screenshot-ascii"&gt;Screenshot (ASCII)&lt;/h2&gt;
&lt;div class="code-block code-line-numbers open" style="counter-reset: code-block 0"&gt;
 &lt;div class="code-header language-"&gt;
 &lt;span class="code-title"&gt;&lt;i class="arrow fas fa-angle-right" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="ellipses"&gt;&lt;i class="fas fa-ellipsis-h" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="copy" title="Copy to clipboard"&gt;&lt;i class="far fa-copy" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌── CPU ──────────────────┐ ┌── Memory ────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Core 0 ████░░░░ 42% │ │ Used 6.2GB / 16GB 38% │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Core 1 ██░░░░░░ 21% │ │ Swap 0.1GB / 4GB 2% │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────────────┘ └──────────────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌── Disk ─────────────────────────────────────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ / 80GB / 250GB 32% ██████░░░░░░░░░░░░░░░░░░░░ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ D:\ 167GB / 250GB 67% ██████████████░░░░░░░░░░░░ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────────────────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="status"&gt;Status&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v0.1.0&lt;/code&gt; — functional but unstyled. Polishing in progress.&lt;/p&gt;</description></item><item><title>Markdown Note Sync CLI</title><link>https://vindrin.top/project/markdown-note-sync/</link><pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/markdown-note-sync/</guid><description>&lt;h1 id="markdown-note-sync-cli"&gt;Markdown Note Sync CLI&lt;/h1&gt;
&lt;p&gt;Keep your notes in Markdown. Sync them anywhere. No proprietary formats.&lt;/p&gt;
&lt;h2 id="problem"&gt;Problem&lt;/h2&gt;
&lt;p&gt;I take notes in Markdown across multiple machines. I wanted something simpler than Obsidian Sync — just a CLI that diffs and pushes changes.&lt;/p&gt;
&lt;h2 id="commands"&gt;Commands&lt;/h2&gt;
&lt;div class="code-block code-line-numbers open" style="counter-reset: code-block 0"&gt;
 &lt;div class="code-header language-bash"&gt;
 &lt;span class="code-title"&gt;&lt;i class="arrow fas fa-angle-right" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="ellipses"&gt;&lt;i class="fas fa-ellipsis-h" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="copy" title="Copy to clipboard"&gt;&lt;i class="far fa-copy" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Initialize sync config&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mnotes init --remote user@server:/notes
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Sync (two-way)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mnotes sync
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Show diff before syncing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mnotes diff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Hash every local &lt;code&gt;.md&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Compare with remote hash index&lt;/li&gt;
&lt;li&gt;Push new/changed files, pull remote-only files&lt;/li&gt;
&lt;li&gt;Conflict = keep both with timestamp suffix&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="dependencies"&gt;Dependencies&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;paramiko&lt;/code&gt; — SSH&lt;/li&gt;
&lt;li&gt;&lt;code&gt;watchdog&lt;/code&gt; — optional auto-sync on file change&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="status"&gt;Status&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v0.2.1&lt;/code&gt; — stable for two machines. Three-way sync is future work.&lt;/p&gt;</description></item><item><title>Local AI Image Classifier</title><link>https://vindrin.top/project/ai-image-classifier/</link><pubDate>Wed, 18 Feb 2026 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/ai-image-classifier/</guid><description>&lt;h1 id="local-ai-image-classifier"&gt;Local AI Image Classifier&lt;/h1&gt;
&lt;p&gt;Classify images by description — no cloud API needed, everything runs locally.&lt;/p&gt;
&lt;h2 id="how-it-works"&gt;How it works&lt;/h2&gt;
&lt;p&gt;Uses &lt;strong&gt;OpenAI CLIP&lt;/strong&gt; to compute similarity between an image and a list of text labels. The highest-scoring label wins.&lt;/p&gt;
&lt;div class="code-block code-line-numbers open" style="counter-reset: code-block 0"&gt;
 &lt;div class="code-header language-python"&gt;
 &lt;span class="code-title"&gt;&lt;i class="arrow fas fa-angle-right" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="ellipses"&gt;&lt;i class="fas fa-ellipsis-h" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;span class="copy" title="Copy to clipboard"&gt;&lt;i class="far fa-copy" aria-hidden="true"&gt;&lt;/i&gt;&lt;/span&gt;
 &lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;clip&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preprocess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;ViT-B/32&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;preprocess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;photo.jpg&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unsqueeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;a cat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;a dog&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;a car&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;a tree&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;probs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;probs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Predicted: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;best&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id="interface"&gt;Interface&lt;/h2&gt;
&lt;p&gt;Flask-based web UI. Drop an image, enter labels, get a classification.&lt;/p&gt;</description></item><item><title>vindrin.top — Personal Website</title><link>https://vindrin.top/project/personal-website/</link><pubDate>Sun, 01 Feb 2026 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/personal-website/</guid><description>&lt;h1 id="vindrintop--personal-website"&gt;vindrin.top — Personal Website&lt;/h1&gt;
&lt;p&gt;The site you&amp;rsquo;re looking at right now.&lt;/p&gt;
&lt;h2 id="goals"&gt;Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A clean place to publish writing and projects&lt;/li&gt;
&lt;li&gt;Bilingual (Chinese + English)&lt;/li&gt;
&lt;li&gt;Fast, static, no backend needed&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="stack"&gt;Stack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Generator&lt;/strong&gt;: Hugo Extended&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theme&lt;/strong&gt;: LoveIt (customized)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hosting&lt;/strong&gt;: Cloudflare Pages&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Domain&lt;/strong&gt;: vindrin.top&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="custom-features-added"&gt;Custom features added&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Dynamic video background on homepage&lt;/li&gt;
&lt;li&gt;Bilingual language switcher in nav&lt;/li&gt;
&lt;li&gt;About page with activity heatmap and paginated journal&lt;/li&gt;
&lt;li&gt;Dark/light mode with glass-effect navbar&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="deployment"&gt;Deployment&lt;/h2&gt;
&lt;p&gt;Every push to &lt;code&gt;main&lt;/code&gt; triggers a Cloudflare Pages build. Zero-downtime deploys.&lt;/p&gt;</description></item><item><title>GitPush Manager</title><link>https://vindrin.top/project/gitpush-manager/</link><pubDate>Wed, 10 Sep 2025 00:00:00 +0000</pubDate><author>vindrin@outlook.com (Vindrin)</author><guid>https://vindrin.top/project/gitpush-manager/</guid><description>&lt;h1 id="gitpush-manager"&gt;GitPush Manager&lt;/h1&gt;
&lt;p&gt;A lightweight desktop application built with &lt;strong&gt;pywebview + Flask&lt;/strong&gt; that wraps common Git operations into a clean visual interface.&lt;/p&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;I found myself running the same three Git commands dozens of times a day. This tool turns those into a single click.&lt;/p&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stage, commit, and push in one view&lt;/li&gt;
&lt;li&gt;Multi-repo management&lt;/li&gt;
&lt;li&gt;Commit message templates&lt;/li&gt;
&lt;li&gt;Push history log&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tech-stack"&gt;Tech Stack&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Python + Flask&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: HTML/CSS/JS via pywebview&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Packaging&lt;/strong&gt;: PyInstaller&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="status"&gt;Status&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;v0.3.0&lt;/code&gt; — stable for personal use. Multi-repo support in progress.&lt;/p&gt;</description></item></channel></rss>