<?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>Forem: Kanishk Kumar Mishra</title>
    <description>The latest articles on Forem by Kanishk Kumar Mishra (@kanishkmishra143).</description>
    <link>https://forem.com/kanishkmishra143</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%2F3859022%2Ffa7d8c2c-f24a-46bb-bec5-8ababe9299bc.png</url>
      <title>Forem: Kanishk Kumar Mishra</title>
      <link>https://forem.com/kanishkmishra143</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kanishkmishra143"/>
    <language>en</language>
    <item>
      <title>Stop Trusting Memory: Engineering Reliable Notion Backups That Just Work</title>
      <dc:creator>Kanishk Kumar Mishra</dc:creator>
      <pubDate>Fri, 03 Apr 2026 09:31:04 +0000</pubDate>
      <link>https://forem.com/kanishkmishra143/stop-trusting-memory-engineering-reliable-notion-backups-that-just-work-mbc</link>
      <guid>https://forem.com/kanishkmishra143/stop-trusting-memory-engineering-reliable-notion-backups-that-just-work-mbc</guid>
      <description>&lt;h2&gt;
  
  
  From manual exports to a cross-platform, OS-native backup system
&lt;/h2&gt;

&lt;p&gt;Backing up your Notion workspace shouldn’t depend on memory.&lt;/p&gt;

&lt;p&gt;But in practice, it does.&lt;/p&gt;

&lt;p&gt;If you rely on Notion for serious work—notes, projects, documentation—you’ve probably experienced this pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“I should probably export this…”
&lt;/li&gt;
&lt;li&gt;“I’ll do it later…”
&lt;/li&gt;
&lt;li&gt;And then… you don’t
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until something breaks.&lt;/p&gt;

&lt;p&gt;The problem isn’t that backups are hard.&lt;br&gt;&lt;br&gt;
The problem is that the workflow around them is unreliable.&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%2F3v0xmx2douz3p9ejy2bn.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%2F3v0xmx2douz3p9ejy2bn.png" alt="Notionsafe logo" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Explore the Project
&lt;/h2&gt;

&lt;p&gt;Check out the project here:&lt;br&gt;&lt;br&gt;
&lt;a href="https://kanishkmishra143.github.io/NotionSafe/" rel="noopener noreferrer"&gt;https://kanishkmishra143.github.io/NotionSafe/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ The Real Issue: Backups That Depend on Humans
&lt;/h2&gt;

&lt;p&gt;Notion provides export functionality.&lt;/p&gt;

&lt;p&gt;But the default workflow looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manually trigger export
&lt;/li&gt;
&lt;li&gt;Wait for processing
&lt;/li&gt;
&lt;li&gt;Download and organize files
&lt;/li&gt;
&lt;li&gt;Repeat regularly (if you remember)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a system that depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory
&lt;/li&gt;
&lt;li&gt;Discipline
&lt;/li&gt;
&lt;li&gt;Timing
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s exactly what backups should &lt;em&gt;not&lt;/em&gt; depend on.&lt;/p&gt;

&lt;p&gt;This isn’t a feature gap.&lt;br&gt;&lt;br&gt;
It’s a reliability problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 The Shift: From Manual Action → Background System
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I back up my Notion workspace?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I reframed it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I make backups happen reliably without thinking about them?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That shift led to building &lt;strong&gt;NotionSafe&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%2Fnkywb7ygnz0h76kteong.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%2Fnkywb7ygnz0h76kteong.png" alt="gui" width="635" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 What is NotionSafe?
&lt;/h2&gt;

&lt;p&gt;NotionSafe is a cross-platform desktop application that automatically backs up your Notion workspace into structured, timestamped local snapshots.&lt;/p&gt;

&lt;p&gt;It’s designed around one core idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Backups should happen without interrupting your workflow.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At a high level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure what to back up
&lt;/li&gt;
&lt;li&gt;Set up scheduling once
&lt;/li&gt;
&lt;li&gt;Let the system handle everything
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No reminders. No manual exports. No friction.&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%2Fjuz4ta6zm2ehr47kw702.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%2Fjuz4ta6zm2ehr47kw702.png" alt="linux gui" width="800" height="629"&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%2Fgolm6782o05xgbimrmpt.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%2Fgolm6782o05xgbimrmpt.png" alt="windows gui" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Workflow Model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Traditional approach
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remember → Export → Download → Organize → Repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  NotionSafe
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Configure once → Scheduled backups → Local history maintained automatically
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From &lt;strong&gt;effort-based&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;To &lt;strong&gt;system-driven&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🐧 Linux vs 🪟 Windows: Designing for Native Reliability
&lt;/h2&gt;

&lt;p&gt;Making this work across platforms wasn’t just a UI problem.&lt;br&gt;&lt;br&gt;
It was a &lt;strong&gt;systems design problem&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🐧 Linux: Composable and Predictable
&lt;/h3&gt;

&lt;p&gt;On Linux, the system provides powerful primitives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;systemd&lt;/code&gt; timers for scheduling
&lt;/li&gt;
&lt;li&gt;Secure credential storage via keyring
&lt;/li&gt;
&lt;li&gt;Native GTK for lightweight interfaces
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allowed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Background execution independent of the app
&lt;/li&gt;
&lt;li&gt;Secure token handling
&lt;/li&gt;
&lt;li&gt;Clean integration with the OS
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result: a solution that feels native and reliable by default.&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%2Fpnjh14cmt42daqswr8je.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%2Fpnjh14cmt42daqswr8je.png" alt="linux gui" width="775" height="509"&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%2Fkj6pkmknck2413ro72im.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%2Fkj6pkmknck2413ro72im.png" alt="linux gui" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🪟 Windows: Different Constraints, Different Approach
&lt;/h3&gt;

&lt;p&gt;Windows required a different strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Task Scheduler replaces &lt;code&gt;systemd&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Different credential storage mechanisms
&lt;/li&gt;
&lt;li&gt;UI expectations differ significantly
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of forcing the Linux approach onto Windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used Task Scheduler for background execution
&lt;/li&gt;
&lt;li&gt;Built a Qt-based interface for native experience
&lt;/li&gt;
&lt;li&gt;Designed workflows to feel consistent, not identical
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was a key decision:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cross-platform doesn’t mean same implementation.&lt;br&gt;&lt;br&gt;
It means same &lt;em&gt;experience&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&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%2Foanvuie6vml96klx12um.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%2Foanvuie6vml96klx12um.png" alt="windows gui" width="627" height="451"&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%2Famol7kx5hmj1oun3r03u.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%2Famol7kx5hmj1oun3r03u.png" alt="windows gui" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Key Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Native UI Over One-Size-Fits-All
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GTK on Linux
&lt;/li&gt;
&lt;li&gt;Qt on Windows
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better performance
&lt;/li&gt;
&lt;li&gt;Familiar interaction patterns
&lt;/li&gt;
&lt;li&gt;OS-level consistency
&lt;/li&gt;
&lt;/ul&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%2Fgtf0hebq38h06vt86i1m.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%2Fgtf0hebq38h06vt86i1m.png" alt="landing page" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. OS-Level Scheduling Over In-App Timers
&lt;/h3&gt;

&lt;p&gt;Instead of running timers inside the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux → &lt;code&gt;systemd&lt;/code&gt; timers
&lt;/li&gt;
&lt;li&gt;Windows → Task Scheduler
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backups run even if the app is closed
&lt;/li&gt;
&lt;li&gt;No dependency on app uptime
&lt;/li&gt;
&lt;li&gt;True background reliability
&lt;/li&gt;
&lt;/ul&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%2Fsgmw12ehgg7m4vxeiaxt.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%2Fsgmw12ehgg7m4vxeiaxt.png" alt="scheduler" width="800" height="613"&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%2Fy0lptz6rjbza6fycs58g.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%2Fy0lptz6rjbza6fycs58g.png" alt="scheduler" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Local Snapshots + Optional Git Sync
&lt;/h3&gt;

&lt;p&gt;Each backup creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Timestamped local snapshot
&lt;/li&gt;
&lt;li&gt;Structured file output
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git-based version history
&lt;/li&gt;
&lt;li&gt;External drive copies
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast recovery (local)
&lt;/li&gt;
&lt;li&gt;Long-term history (Git)
&lt;/li&gt;
&lt;/ul&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%2Fnp7s0w3r4gi6dz8lqawu.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%2Fnp7s0w3r4gi6dz8lqawu.png" alt="storage options" width="775" height="509"&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%2Fxs0eemfjimv2d7am2xhd.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%2Fxs0eemfjimv2d7am2xhd.png" alt="storage options" width="627" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Config-Driven Setup (With a Wizard)
&lt;/h3&gt;

&lt;p&gt;Instead of exposing everything upfront:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guided setup
&lt;/li&gt;
&lt;li&gt;Config stored cleanly
&lt;/li&gt;
&lt;li&gt;Minimal cognitive load
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This balances:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Power
&lt;/li&gt;
&lt;li&gt;Simplicity
&lt;/li&gt;
&lt;/ul&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%2Fiuytw8heej5dxzsa9sf4.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%2Fiuytw8heej5dxzsa9sf4.png" alt="config wizard" width="800" height="553"&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%2Fi57rf4wozsxtyo95w05s.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%2Fi57rf4wozsxtyo95w05s.png" alt="config wizard" width="627" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 What Actually Gets Backed Up?
&lt;/h2&gt;

&lt;p&gt;Each run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exports selected pages/databases
&lt;/li&gt;
&lt;li&gt;Stores them as timestamped snapshots
&lt;/li&gt;
&lt;li&gt;Organizes them for easy retrieval
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a &lt;strong&gt;recoverable, versioned history of your workspace&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Design Philosophy
&lt;/h2&gt;

&lt;p&gt;This project wasn’t about backups.&lt;br&gt;&lt;br&gt;
It was about removing anxiety from a critical workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core principles:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reliability over visibility&lt;/strong&gt; → it should just work
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation over discipline&lt;/strong&gt; → remove human dependency
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native integration over abstraction&lt;/strong&gt; → use the OS properly
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local-first over cloud dependency&lt;/strong&gt; → you own your data
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Who Is This For?
&lt;/h2&gt;

&lt;p&gt;NotionSafe is built for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;People who rely on Notion for real work
&lt;/li&gt;
&lt;li&gt;Users who want local ownership of their data
&lt;/li&gt;
&lt;li&gt;Cross-platform workflows
&lt;/li&gt;
&lt;li&gt;Anyone who values reliable systems over manual routines
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📌 What This Project Really Represents
&lt;/h2&gt;

&lt;p&gt;This wasn’t about backing up Notion.&lt;/p&gt;

&lt;p&gt;It was about solving a deeper problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Systems that depend on humans will eventually fail.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The solution:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Design systems that remove human dependency wherever possible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🚀 Final Thought
&lt;/h2&gt;

&lt;p&gt;You don’t notice backups when they work.&lt;br&gt;&lt;br&gt;
You only notice them when they fail.&lt;/p&gt;

&lt;p&gt;The goal isn’t to think about backups more.&lt;/p&gt;

&lt;p&gt;It’s to stop thinking about them entirely.&lt;/p&gt;

</description>
      <category>notion</category>
      <category>automation</category>
      <category>python</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Stop Breaking Flow: Engineering Instant Audio Switching Across Linux and Windows</title>
      <dc:creator>Kanishk Kumar Mishra</dc:creator>
      <pubDate>Fri, 03 Apr 2026 08:52:58 +0000</pubDate>
      <link>https://forem.com/kanishkmishra143/stop-breaking-flow-engineering-instant-audio-switching-across-linux-and-windows-427f</link>
      <guid>https://forem.com/kanishkmishra143/stop-breaking-flow-engineering-instant-audio-switching-across-linux-and-windows-427f</guid>
      <description>&lt;h2&gt;
  
  
  🎧 From a simple pactl script to a cross-platform, low-latency system tool
&lt;/h2&gt;

&lt;p&gt;Switching audio devices should be instant.&lt;/p&gt;

&lt;p&gt;In practice, it isn’t.&lt;/p&gt;

&lt;p&gt;If you regularly use multiple audio outputs—headphones, speakers, Bluetooth devices—you’ve likely run into the same friction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening system settings just to switch output
&lt;/li&gt;
&lt;li&gt;Clicking through nested menus
&lt;/li&gt;
&lt;li&gt;Losing focus from your current task
&lt;/li&gt;
&lt;li&gt;Repeating this multiple times a day
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn’t a hard problem.&lt;/p&gt;

&lt;p&gt;But it’s a &lt;strong&gt;bad workflow problem&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%2Fb6hpxe6176gmmoza8ngt.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%2Fb6hpxe6176gmmoza8ngt.png" alt="sink switch linux gui" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Explore the Project
&lt;/h2&gt;

&lt;p&gt;Check out the project here:&lt;br&gt;
&lt;a href="https://kanishkmishra143.github.io/Sink-Switch/" rel="noopener noreferrer"&gt;https://kanishkmishra143.github.io/Sink-Switch/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ The Real Issue: Friction, Not Functionality
&lt;/h2&gt;

&lt;p&gt;Modern operating systems already support multiple audio devices.&lt;/p&gt;

&lt;p&gt;The issue isn’t capability—it’s interaction.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switching is UI-heavy instead of keyboard-first
&lt;/li&gt;
&lt;li&gt;No fast, predictable way to move between preferred devices
&lt;/li&gt;
&lt;li&gt;Context switching breaks flow
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re not lacking features.&lt;/p&gt;

&lt;p&gt;You’re lacking &lt;strong&gt;speed and intent in the workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 The Shift: From Selection → Cycling
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I switch audio devices faster?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I reframed it as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I eliminate the need to &lt;em&gt;choose&lt;/em&gt; every time?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That led to a simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Cycle through a predefined set of devices using a single action.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No menus. No decisions. Just movement.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Introducing Sink Switch
&lt;/h2&gt;

&lt;p&gt;Sink Switch is a cross-platform utility for instantly switching audio outputs using a hotkey, CLI command, or lightweight GUI.&lt;/p&gt;

&lt;p&gt;👉 :contentReference[oaicite:0]{index=0}&lt;/p&gt;

&lt;p&gt;At its core, the workflow is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select the devices you care about
&lt;/li&gt;
&lt;li&gt;Define a cycle order
&lt;/li&gt;
&lt;li&gt;Trigger a hotkey or command
&lt;/li&gt;
&lt;li&gt;Switch instantly
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No UI friction. No repeated decisions.&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%2Fz3z3nofmm56pkfa52j4p.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%2Fz3z3nofmm56pkfa52j4p.png" alt="linux gui" width="800" height="716"&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%2F5u0gq5y2in1enualrsal.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%2F5u0gq5y2in1enualrsal.png" alt="windows gui" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ Core Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Cycling &amp;gt; Selection
&lt;/h3&gt;

&lt;p&gt;Traditional approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open settings
&lt;/li&gt;
&lt;li&gt;Select device
&lt;/li&gt;
&lt;li&gt;Confirm
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sink Switch approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Press hotkey → next device
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes switching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster
&lt;/li&gt;
&lt;li&gt;Predictable
&lt;/li&gt;
&lt;li&gt;Muscle-memory driven
&lt;/li&gt;
&lt;/ul&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%2Fw8s9kwjezoawg7ikqpm5.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%2Fw8s9kwjezoawg7ikqpm5.png" alt="device switched" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Config-Driven State
&lt;/h3&gt;

&lt;p&gt;Instead of dynamically choosing devices every time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You define a cycle list once
&lt;/li&gt;
&lt;li&gt;The system remembers it
&lt;/li&gt;
&lt;li&gt;Switching becomes deterministic
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This removes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cognitive overhead
&lt;/li&gt;
&lt;li&gt;Repeated configuration
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Keyboard-First Workflow
&lt;/h3&gt;

&lt;p&gt;Everything is designed around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hotkeys
&lt;/li&gt;
&lt;li&gt;CLI commands
&lt;/li&gt;
&lt;li&gt;Minimal UI interaction
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because speed comes from &lt;strong&gt;not leaving your current context&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐧 Linux vs 🪟 Windows: A Systems Perspective
&lt;/h2&gt;

&lt;p&gt;One of the most interesting parts of building Sink Switch was how different the platforms are.&lt;/p&gt;

&lt;h3&gt;
  
  
  On Linux
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clean interfaces via PulseAudio / PipeWire
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pactl&lt;/code&gt; provides direct control
&lt;/li&gt;
&lt;li&gt;Bash was enough for a fast, native-feeling solution
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Result:&lt;br&gt;&lt;br&gt;
A lightweight, scriptable system that integrates naturally into the environment.&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%2F4xvlea1ouxceppelk49x.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%2F4xvlea1ouxceppelk49x.png" alt="linux gui" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  On Windows
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Outdated and restrictive audio APIs
&lt;/li&gt;
&lt;li&gt;PowerShell + AutoHotkey approach broke down quickly
&lt;/li&gt;
&lt;li&gt;No reliable abstraction for consistent device control
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This forced a shift:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rebuild the Windows version in Go using Core Audio APIs directly.&lt;/p&gt;
&lt;/blockquote&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%2F4q9nig1yu49gci6ge2h6.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%2F4q9nig1yu49gci6ge2h6.png" alt="windows gui" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠️ Why Go for Windows?
&lt;/h2&gt;

&lt;p&gt;The Go implementation enabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Direct interaction with Windows Core Audio APIs
&lt;/li&gt;
&lt;li&gt;Reliable, low-latency switching
&lt;/li&gt;
&lt;li&gt;Better control over device enumeration and state
&lt;/li&gt;
&lt;li&gt;A native dashboard + CLI interface
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This wasn’t just a rewrite.&lt;/p&gt;

&lt;p&gt;It was a &lt;strong&gt;necessary architectural upgrade&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 A Subtle Edge Case
&lt;/h2&gt;

&lt;p&gt;One interesting challenge:&lt;/p&gt;

&lt;p&gt;Tools like FxSound always appear as the active output device—even when they’re just acting as a processing layer.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The system reports a “virtual” device
&lt;/li&gt;
&lt;li&gt;But the actual output is happening elsewhere
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fixing this required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracking real device state beyond surface-level API data
&lt;/li&gt;
&lt;li&gt;Designing around &lt;strong&gt;how audio is routed&lt;/strong&gt;, not just reported
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where a simple tool becomes a &lt;strong&gt;systems problem&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Design Philosophy
&lt;/h2&gt;

&lt;p&gt;This project wasn’t about building another utility.&lt;/p&gt;

&lt;p&gt;It was about removing friction from a high-frequency workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Principles
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Speed Over Flexibility
&lt;/h4&gt;

&lt;p&gt;Fewer decisions → faster execution.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Predictability Over Complexity
&lt;/h4&gt;

&lt;p&gt;Cycling ensures consistent behavior every time.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. State Over Stateless Actions
&lt;/h4&gt;

&lt;p&gt;The system remembers your preferences.&lt;/p&gt;

&lt;p&gt;You don’t have to reconfigure each time.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Flow Over Features
&lt;/h4&gt;

&lt;p&gt;The goal isn’t more functionality.&lt;/p&gt;

&lt;p&gt;The goal is &lt;strong&gt;not breaking your focus&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📂 What It Enables
&lt;/h2&gt;

&lt;p&gt;Sink Switch becomes especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-device setups (headphones + speakers + Bluetooth)
&lt;/li&gt;
&lt;li&gt;Developers working in full-screen environments
&lt;/li&gt;
&lt;li&gt;Linux users on tiling WMs like Hyprland
&lt;/li&gt;
&lt;li&gt;Anyone optimizing for keyboard-first workflows
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📌 What This Project Really Represents
&lt;/h2&gt;

&lt;p&gt;This wasn’t about switching audio devices.&lt;/p&gt;

&lt;p&gt;It was about identifying a small but frequent annoyance—and solving it properly.&lt;/p&gt;

&lt;p&gt;The pattern is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Identify friction → remove decisions → optimize for flow&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That pattern applies everywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dev tools
&lt;/li&gt;
&lt;li&gt;System utilities
&lt;/li&gt;
&lt;li&gt;Even product design
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🚀 Final Thought
&lt;/h2&gt;

&lt;p&gt;Good tools add features.&lt;/p&gt;

&lt;p&gt;Great tools remove steps.&lt;/p&gt;

&lt;p&gt;And the best ones become invisible—because they just fit into your workflow.&lt;/p&gt;

&lt;p&gt;Sink Switch is one of those tools.&lt;/p&gt;

</description>
      <category>audiotool</category>
      <category>utilitytool</category>
      <category>crossplatform</category>
      <category>pactl</category>
    </item>
    <item>
      <title>Stop Babysitting Symlinks: Designing a Safer, Faster TUI Workflow</title>
      <dc:creator>Kanishk Kumar Mishra</dc:creator>
      <pubDate>Fri, 03 Apr 2026 08:29:39 +0000</pubDate>
      <link>https://forem.com/kanishkmishra143/stop-babysitting-symlinks-designing-a-safer-faster-tui-workflow-aob</link>
      <guid>https://forem.com/kanishkmishra143/stop-babysitting-symlinks-designing-a-safer-faster-tui-workflow-aob</guid>
      <description>&lt;h2&gt;
  
  
  📝 From &lt;code&gt;ln -s&lt;/code&gt; to Intentional Workflows: Building an Interactive Symlink Creator in Go
&lt;/h2&gt;

&lt;p&gt;Managing symlinks should be trivial. In practice, it's anything but.&lt;/p&gt;

&lt;p&gt;If you've worked with symlinks long enough—especially while managing dotfiles, configs, or multi-environment setups—you've likely fallen into the same repetitive loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Double-check source and destination paths
&lt;/li&gt;
&lt;li&gt;Worry about overwriting something important
&lt;/li&gt;
&lt;li&gt;Manually resolve conflicts
&lt;/li&gt;
&lt;li&gt;Repeat the process, carefully, every single time
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem isn't that symlinks are complex.&lt;br&gt;&lt;br&gt;
The problem is that the workflow around them is fragile.&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%2Fy0eonjtoazgz1ddmppc4.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%2Fy0eonjtoazgz1ddmppc4.png" alt="isc welcome page" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🔗 Explore the Project
&lt;/h2&gt;

&lt;p&gt;You can check out the full project here:&lt;br&gt;
&lt;a href="https://github.com/KanishkMishra143/Interactive-Symlink-Creator" rel="noopener noreferrer"&gt;https://github.com/KanishkMishra143/Interactive-Symlink-Creator&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ⚠️ The Real Issue: Workflow, Not Command
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;ln -s&lt;/code&gt; command itself is simple. But the moment you scale beyond a single link, things start breaking down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No structured navigation → long, error-prone paths
&lt;/li&gt;
&lt;li&gt;No safety layer → easy to overwrite unintentionally
&lt;/li&gt;
&lt;li&gt;No batch operations → repetitive, manual work
&lt;/li&gt;
&lt;li&gt;No feedback loop → you don't know what went wrong until it's too late
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a tooling problem.&lt;br&gt;&lt;br&gt;
It's a workflow design problem.&lt;/p&gt;
&lt;h2&gt;
  
  
  💡 The Shift: From Commands → Experience
&lt;/h2&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I create symlinks faster?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I reframed the problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"How do I make symlink creation intentional, safe, and repeatable?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That shift led to building &lt;strong&gt;Interactive Symlink Creator (ISC)&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%2Ficgggn26h5o1q4uh4nwm.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%2Ficgggn26h5o1q4uh4nwm.png" alt="isc destination selection" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🚀 What is ISC?
&lt;/h2&gt;

&lt;p&gt;ISC is a full-screen terminal application that guides you through the entire symlink creation process—from selecting directories to resolving conflicts—without dropping back into raw shell commands.&lt;/p&gt;

&lt;p&gt;It's built using Go and a TUI framework to create a structured, keyboard-first experience.&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%2Fp85zbfvx8z0fje18vfh8.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%2Fp85zbfvx8z0fje18vfh8.png" alt="isc welcome screen" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Workflow Overview
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Choose a source directory
&lt;/li&gt;
&lt;li&gt;Choose a destination directory
&lt;/li&gt;
&lt;li&gt;Select files/folders to link (bulk supported)
&lt;/li&gt;
&lt;li&gt;Handle conflicts interactively
&lt;/li&gt;
&lt;li&gt;Review results and restart if needed
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything happens inside a single, continuous interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  ⚙️ Key Capabilities
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Interactive Directory Navigation
&lt;/h3&gt;

&lt;p&gt;Instead of typing long paths manually, ISC provides a two-column navigator for selecting source and destination directories.&lt;/p&gt;

&lt;p&gt;This reduces both cognitive load and error probability.&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%2Fap2ba9r2a3dli6s86f7a.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%2Fap2ba9r2a3dli6s86f7a.png" alt="isc source selection" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Bulk Selection Before Execution
&lt;/h3&gt;

&lt;p&gt;You don't execute commands one by one.&lt;/p&gt;

&lt;p&gt;You:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select multiple files/folders
&lt;/li&gt;
&lt;li&gt;Review your selection
&lt;/li&gt;
&lt;li&gt;Execute in a single pass
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This shifts the workflow from &lt;strong&gt;reactive → planned&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%2Fwwb11ce6reqjj4ag74aj.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%2Fwwb11ce6reqjj4ag74aj.png" alt="isc bulk selection" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Conflict Resolution That Doesn't Break Flow
&lt;/h3&gt;

&lt;p&gt;When conflicts occur, you're not thrown back into the shell.&lt;/p&gt;

&lt;p&gt;You get structured options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overwrite
&lt;/li&gt;
&lt;li&gt;Skip
&lt;/li&gt;
&lt;li&gt;Rename
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All handled inline, without losing context.&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%2Fghjog4wyrou7zyz583he.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%2Fghjog4wyrou7zyz583he.png" alt="isc conflict resolution" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Dry-Run Mode (Critical for Safety)
&lt;/h3&gt;

&lt;p&gt;Before making any changes, you can simulate the entire operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--dry-run&lt;/span&gt; create
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you validate decisions without touching the filesystem.&lt;/p&gt;

&lt;p&gt;A small feature—but high leverage in preventing mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cleanup for Broken Symlinks
&lt;/h3&gt;

&lt;p&gt;Symlink-heavy environments tend to accumulate broken links over time.&lt;/p&gt;

&lt;p&gt;ISC includes a cleanup command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run &lt;span class="nb"&gt;.&lt;/span&gt; cleanup /path/to/search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This scans and removes broken symlinks recursively.&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%2Fgzpagcu12eqd1swn6w3y.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%2Fgzpagcu12eqd1swn6w3y.png" alt="isc successful screen" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Design Philosophy
&lt;/h2&gt;

&lt;p&gt;This project wasn't about building another CLI tool.&lt;br&gt;
It was about eliminating friction from a recurring workflow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Key Principles
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Full-Screen TUI Over Prompt-Based CLI
&lt;/h4&gt;

&lt;p&gt;Prompts interrupt flow. A TUI maintains continuity.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Restartable Workflows
&lt;/h4&gt;

&lt;p&gt;No abrupt exits. You can restart the entire process seamlessly after completion.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Keyboard-First Interaction
&lt;/h4&gt;

&lt;p&gt;Every action is optimized for speed without leaving the keyboard.&lt;/p&gt;
&lt;h4&gt;
  
  
  4. Structured State Over Stateless Commands
&lt;/h4&gt;

&lt;p&gt;Traditional CLI usage is stateless—you issue commands and hope for correctness.&lt;/p&gt;

&lt;p&gt;ISC maintains state across steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What you selected&lt;/li&gt;
&lt;li&gt;What conflicts exist&lt;/li&gt;
&lt;li&gt;What actions you chose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This drastically reduces mental overhead.&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠️ Why Go + TUI?
&lt;/h2&gt;

&lt;p&gt;The initial version was a Bash script.&lt;/p&gt;

&lt;p&gt;It worked—but hit limits quickly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to scale cleanly&lt;/li&gt;
&lt;li&gt;Poor UX for multi-step workflows&lt;/li&gt;
&lt;li&gt;Difficult to maintain or extend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rewriting in Go enabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better structure (modular architecture)&lt;/li&gt;
&lt;li&gt;Clear separation of concerns&lt;/li&gt;
&lt;li&gt;Predictable behavior across environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The TUI layer allowed transforming a command into an experience.&lt;/p&gt;
&lt;h2&gt;
  
  
  📂 Under the Hood
&lt;/h2&gt;

&lt;p&gt;The project follows a layered structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;internal/
├── domain/
├── fs/
├── services/
└── ui/
    ├── components/
    ├── manager/
    └── styles/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filesystem logic is isolated&lt;/li&gt;
&lt;li&gt;UI remains independent&lt;/li&gt;
&lt;li&gt;Business logic is reusable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not just a tool—it's designed to be extendable.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Who Is This For?
&lt;/h2&gt;

&lt;p&gt;ISC is built for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers managing dotfiles&lt;/li&gt;
&lt;li&gt;Linux users working heavily in terminals&lt;/li&gt;
&lt;li&gt;Anyone tired of manually handling symlinks&lt;/li&gt;
&lt;li&gt;People who care about safe, repeatable workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📌 What This Project Really Represents
&lt;/h2&gt;

&lt;p&gt;This wasn't about symlinks.&lt;/p&gt;

&lt;p&gt;It was about taking a small, annoying, everyday task—and treating it like a real engineering problem.&lt;/p&gt;

&lt;p&gt;The outcome isn't just a tool.&lt;br&gt;
It's a pattern:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Identify friction → redesign the workflow → build around safety and intent&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That pattern scales far beyond this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Final Thought
&lt;/h2&gt;

&lt;p&gt;The best projects aren't always flashy.&lt;/p&gt;

&lt;p&gt;Sometimes, they're the ones that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove friction&lt;/li&gt;
&lt;li&gt;Reduce mistakes&lt;/li&gt;
&lt;li&gt;And quietly make your daily workflow 10x smoother&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And those are often the ones worth building.&lt;/p&gt;

</description>
      <category>terminalapp</category>
      <category>linux</category>
      <category>go</category>
      <category>utilitytool</category>
    </item>
  </channel>
</rss>
