<?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: sangeet verma</title>
    <description>The latest articles on DEV Community by sangeet verma (@phoenix911).</description>
    <link>https://dev.to/phoenix911</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F12207%2F2749200.jpeg</url>
      <title>DEV Community: sangeet verma</title>
      <link>https://dev.to/phoenix911</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/phoenix911"/>
    <language>en</language>
    <item>
      <title>Selfhosted scratchpad</title>
      <dc:creator>sangeet verma</dc:creator>
      <pubDate>Sat, 27 Jun 2026 19:56:09 +0000</pubDate>
      <link>https://dev.to/phoenix911/selfhosted-scratchpad-4kcc</link>
      <guid>https://dev.to/phoenix911/selfhosted-scratchpad-4kcc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149" class="crayons-story__hidden-navigation-link"&gt;Everything I scratched down kept disappearing — so I built a workspace that actually keeps it&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/phoenix911" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F12207%2F2749200.jpeg" alt="phoenix911 profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/phoenix911" class="crayons-story__secondary fw-medium m:hidden"&gt;
              sangeet verma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                sangeet verma
                
              
              &lt;div id="story-author-preview-content-4007756" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/phoenix911" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F12207%2F2749200.jpeg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;sangeet verma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 27&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149" id="article-link-4007756"&gt;
          Everything I scratched down kept disappearing — so I built a workspace that actually keeps it
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/selfhosted"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;selfhosted&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/go"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;go&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>productivity</category>
      <category>showdev</category>
      <category>sideprojects</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Everything I scratched down kept disappearing — so I built a workspace that actually keeps it</title>
      <dc:creator>sangeet verma</dc:creator>
      <pubDate>Sat, 27 Jun 2026 19:55:04 +0000</pubDate>
      <link>https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149</link>
      <guid>https://dev.to/phoenix911/everything-i-scratched-down-kept-disappearing-so-i-built-a-workspace-that-actually-keeps-it-149</guid>
      <description>&lt;p&gt;I have lost more notes than I'd like to admit. Not to dramatic disk failures —&lt;br&gt;
to the quiet, ordinary stuff. A snippet in a pastebin tab that I closed before&lt;br&gt;
it saved. A diagram in some web tool I never made an account for, gone the&lt;br&gt;
moment the tab reloaded. A folder of "temp" markdown files that stayed on the&lt;br&gt;
old laptop when I switched machines. None of it felt important in the moment.&lt;br&gt;
All of it I went looking for later, and couldn't find.&lt;/p&gt;

&lt;p&gt;The pattern was always the same:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scattered across too many tools.&lt;/strong&gt; A pastebin for code, a drawing app, a
notes app, a doc editor, a kanban board — five tabs, five accounts, five
silos. The thing I wanted was always in the one I wasn't looking at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never really saved.&lt;/strong&gt; Half these tools keep your work in browser state or a
draft that only persists if you remember to hit save / sign in / export.
Close the tab at the wrong moment and it's just… gone. No file, nothing to
recover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bleeds away over time.&lt;/strong&gt; Every device change, every "I'll migrate that
later," every dead startup that took my data down with it — a little more of
my own thinking quietly lost. Five years of scratch work and I can show you
almost none of it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built the tool I wanted: one place for all of it, where &lt;strong&gt;everything is a&lt;br&gt;
real file the instant I type it&lt;/strong&gt;, and where the data outlives the app, the&lt;br&gt;
tab, and the laptop.&lt;/p&gt;

&lt;p&gt;It's called &lt;strong&gt;Scratchpad&lt;/strong&gt; — a single Go binary that embeds a React app. No&lt;br&gt;
database server, no Docker, no cloud account. Everything you create is a plain&lt;br&gt;
file on disk, &lt;strong&gt;continuously synced to a private git repo you own&lt;/strong&gt;, and&lt;br&gt;
shareable as view-only links.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/phoenix911/scratchpad" rel="noopener noreferrer"&gt;https://github.com/phoenix911/scratchpad&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Landing + docs:&lt;/strong&gt; &lt;a href="https://phoenix911.github.io/scratchpad/" rel="noopener noreferrer"&gt;https://phoenix911.github.io/scratchpad/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F00cdu5rtodytyvcsfqk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F00cdu5rtodytyvcsfqk6.png" alt="Scratchpad code editor" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;Six editors, one app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt; snippets — CodeMirror 6, with real language detection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drawings&lt;/strong&gt; — Excalidraw, saved as scene JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mindmaps&lt;/strong&gt; — Mind Elixir.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich-text docs&lt;/strong&gt; — Tiptap, with Markdown input rules and paste-an-image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kanban boards&lt;/strong&gt; — drag-and-drop with dnd-kit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cornell notes&lt;/strong&gt; — the cue / notes / summary study layout, with Markdown
auto-formatting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Folders&lt;/strong&gt; (nestable) to organize items — mirrored as real subdirectories in
your data repo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;View-only share links&lt;/strong&gt; with optional expiry (1–30 days, or never), each
with an auto-generated link-preview image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version history&lt;/strong&gt; — every item is git-tracked, so you can browse and restore
any past version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backlinks&lt;/strong&gt; — &lt;code&gt;[[wiki-links]]&lt;/code&gt; between items, with a "links to / linked
from" panel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;⌘K command palette&lt;/strong&gt;, light/dark following your system, ~20–30 MB idle RAM.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy1l6jgbnvaosiz9fkh2t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy1l6jgbnvaosiz9fkh2t.png" alt="Mindmaps and boards" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The design: files on disk, git as the backbone
&lt;/h2&gt;

&lt;p&gt;Every frustration above comes back to one thing — &lt;em&gt;where does the work actually&lt;br&gt;
live?&lt;/em&gt; In most tools the honest answer is "somewhere you don't control, until&lt;br&gt;
you remember to save it somewhere you do." So I inverted it. In Scratchpad the&lt;br&gt;
source of truth is &lt;strong&gt;the filesystem&lt;/strong&gt;, not a database, and the safety net is&lt;br&gt;
&lt;strong&gt;git&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you create a code snippet, it's written to disk with the language's real&lt;br&gt;
extension (&lt;code&gt;.go&lt;/code&gt;, &lt;code&gt;.py&lt;/code&gt;, …) as you type. A drawing is an &lt;code&gt;.excalidraw&lt;/code&gt; JSON&lt;br&gt;
file. A doc is HTML. Those files live in a directory that &lt;em&gt;is&lt;/em&gt; a git working&lt;br&gt;
tree, and Scratchpad shells out to the system &lt;code&gt;git&lt;/code&gt; to commit and push them to a&lt;br&gt;
private repo you own (SSH or HTTPS).&lt;/p&gt;

&lt;p&gt;That single choice answers each of the three frustrations directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Never really saved" → it's a file before you look away.&lt;/strong&gt; There's no draft
state to lose. Autosave writes to disk; the only place your work can be is a
real file. Close the tab, kill the process, pull the plug — it's already on
disk and already committed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Bleeds away over time" → the data outlives the app and the device.&lt;/strong&gt; Your
repo &lt;em&gt;is&lt;/em&gt; the backup. New laptop? &lt;code&gt;git clone&lt;/code&gt; and you're whole again. Bored of
Scratchpad in two years? You're left with a folder of normal files in normal
formats — code, JSON, HTML, Markdown — readable with or without this tool.
Zero lock-in, by construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Scattered across tools" → one repo holds all of it.&lt;/strong&gt; Code, diagrams,
mindmaps, docs and boards land in the &lt;em&gt;same&lt;/em&gt; versioned tree, in folders you
organize.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because it's git, you get &lt;strong&gt;full version history for free&lt;/strong&gt; — no custom&lt;br&gt;
versioning code, it's &lt;code&gt;git log&lt;/code&gt; and &lt;code&gt;git show&lt;/code&gt; under the hood, so you can browse&lt;br&gt;
and restore any past version of anything.&lt;/p&gt;

&lt;p&gt;So where does SQLite come in? Only as a &lt;strong&gt;rebuildable index&lt;/strong&gt;. It's a pure-Go&lt;br&gt;
SQLite (&lt;code&gt;modernc.org/sqlite&lt;/code&gt;, so no cgo) that caches item metadata and the&lt;br&gt;
backlink graph for fast queries. On boot, Scratchpad reconciles the DB against&lt;br&gt;
what's actually on disk — so if the DB is ever lost or out of sync, it's&lt;br&gt;
regenerated from the files. The files win, always.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why a single Go binary
&lt;/h2&gt;

&lt;p&gt;The whole app ships as one static binary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The built React SPA is embedded with &lt;code&gt;embed.FS&lt;/code&gt;, so there's nothing to serve
separately — the binary &lt;em&gt;is&lt;/em&gt; the web server (net/http + chi).&lt;/li&gt;
&lt;li&gt;Pure-Go SQLite means no cgo, so it cross-compiles cleanly to linux/amd64,
arm, etc. with a plain &lt;code&gt;GOOS&lt;/code&gt;/&lt;code&gt;GOARCH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sync is just &lt;code&gt;os/exec&lt;/code&gt; calling the &lt;code&gt;git&lt;/code&gt; you already have installed — no
embedded git library, no SSH-in-Go complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result boots instantly and sits around 20–30 MB of RAM. You can &lt;code&gt;scp&lt;/code&gt; it to&lt;br&gt;
a $5 VPS or a Raspberry Pi and run it under systemd.&lt;/p&gt;
&lt;h2&gt;
  
  
  Self-hosting it
&lt;/h2&gt;

&lt;p&gt;Grab a release binary (or &lt;code&gt;make all&lt;/code&gt; from source) and 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;git clone https://github.com/phoenix911/scratchpad
&lt;span class="nb"&gt;cd &lt;/span&gt;scratchpad
make all          &lt;span class="c"&gt;# builds the SPA, embeds it, produces ./scratchpad&lt;/span&gt;
./scratchpad      &lt;span class="c"&gt;# http://localhost:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configuration is all environment variables (or a &lt;code&gt;.env&lt;/code&gt; file). The ones that&lt;br&gt;
matter:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SCRATCHPAD_PASSWORD&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single-password gate (blank = open, local only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GIT_URL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The private repo to sync your data to&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SHARE_BASE_URL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your public URL, used to build share links&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATA_DIR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Where the item files (the git working tree) live&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It's a personal, single-user tool behind one password. Put it behind any&lt;br&gt;
reverse proxy or tunnel — Caddy, nginx, Cloudflare Tunnel, Tailscale — so the&lt;br&gt;
share links work from anywhere. I run mine behind a Cloudflare Tunnel; there's&lt;br&gt;
a sample systemd unit in the deployment docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's under the hood
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Go, net/http + chi, &lt;code&gt;embed.FS&lt;/code&gt;, pure-Go SQLite, HMAC-signed
session cookies, OG share-image rendering with the Go &lt;code&gt;image&lt;/code&gt; libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; React 19 + Vite + TypeScript + Tailwind v4 + Zustand, with the
heavy editors code-split via &lt;code&gt;React.lazy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Editors:&lt;/strong&gt; CodeMirror, Excalidraw, Mind Elixir, Tiptap, dnd-kit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it / tear it apart
&lt;/h2&gt;

&lt;p&gt;I've been running it for a while now, and the nice part is the thing I built it&lt;br&gt;
for: I haven't lost a scratch note since. It's all just sitting in a repo,&lt;br&gt;
across every machine I've moved to.&lt;/p&gt;

&lt;p&gt;It's open source under MIT and I'd genuinely like feedback — especially from&lt;br&gt;
people who've lost work the same dumb ways I have. What would it take before&lt;br&gt;
you'd trust a tool with the stuff you scribble down?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/phoenix911/scratchpad" rel="noopener noreferrer"&gt;https://github.com/phoenix911/scratchpad&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs &amp;amp; screenshots:&lt;/strong&gt; &lt;a href="https://phoenix911.github.io/scratchpad/" rel="noopener noreferrer"&gt;https://phoenix911.github.io/scratchpad/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(I'm the dev — happy to answer anything about the architecture in the comments.)&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>go</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
