<?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: Joe Greenwood</title>
    <description>The latest articles on DEV Community by Joe Greenwood (@grnwood).</description>
    <link>https://dev.to/grnwood</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%2F3796787%2Ff7dc4b60-0780-4043-ba7f-53e6782c1ed7.jpeg</url>
      <title>DEV Community: Joe Greenwood</title>
      <link>https://dev.to/grnwood</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/grnwood"/>
    <language>en</language>
    <item>
      <title>Local first Markdown Workspace - FastAPI + PySide + distributed sync</title>
      <dc:creator>Joe Greenwood</dc:creator>
      <pubDate>Fri, 27 Feb 2026 17:12:49 +0000</pubDate>
      <link>https://dev.to/grnwood/building-a-local-first-app-with-fastapi-pyside-distributed-sync-23l8</link>
      <guid>https://dev.to/grnwood/building-a-local-first-app-with-fastapi-pyside-distributed-sync-23l8</guid>
      <description>&lt;h2&gt;
  
  
  Building StillPoint: A Local-First Markdown Workspace with a Server Core
&lt;/h2&gt;

&lt;p&gt;Most note-taking tools fall into one of two camps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure desktop apps that never think about networking (or paid models to get there...)&lt;/li&gt;
&lt;li&gt;Cloud-first systems that treat your data as something hosted somewhere else&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something different.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;StillPoint&lt;/strong&gt; as a local-first Markdown workspace that treats the file system as the source of truth — but is architected around a server model from day one.&lt;/p&gt;

&lt;p&gt;This post walks through why I built it, how it’s structured, and what tradeoffs I’ve made.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Was Trying to Solve
&lt;/h2&gt;

&lt;p&gt;Over time I found myself juggling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notes in one tool&lt;/li&gt;
&lt;li&gt;Tasks in another&lt;/li&gt;
&lt;li&gt;Journal entries somewhere else&lt;/li&gt;
&lt;li&gt;Diagrams in yet another place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many of them were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cloud-dependent&lt;/li&gt;
&lt;li&gt;Locked behind accounts&lt;/li&gt;
&lt;li&gt;Or heavy with abstractions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notes + tasks + planning in one surface&lt;/li&gt;
&lt;li&gt;Markdown files on disk&lt;/li&gt;
&lt;li&gt;Something calm&lt;/li&gt;
&lt;li&gt;Something I could reason about&lt;/li&gt;
&lt;li&gt;Something I could run entirely locally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I also didn’t want to paint myself into a “single-device desktop app” corner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Philosophy
&lt;/h2&gt;

&lt;p&gt;StillPoint is built around a few principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local-first by default&lt;/li&gt;
&lt;li&gt;Markdown-first (human-readable, tool-agnostic)&lt;/li&gt;
&lt;li&gt;Folder-per-page structure (filesystem-native)&lt;/li&gt;
&lt;li&gt;No proprietary lock-in&lt;/li&gt;
&lt;li&gt;AI optional and opt-in&lt;/li&gt;
&lt;li&gt;Progressive complexity (simple solo use first, remote/sync later)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the app disappears tomorrow, your vault is still a folder of Markdown files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture: Desktop + Server, Even Locally
&lt;/h2&gt;

&lt;p&gt;Even in “local mode”, StillPoint runs a server.&lt;/p&gt;

&lt;p&gt;Here’s the simplified model:&lt;/p&gt;

&lt;p&gt;Desktop UI → HTTP → StillPoint Server → Filesystem Vault&lt;/p&gt;

&lt;p&gt;The server is built with FastAPI and:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads/writes Markdown files directly&lt;/li&gt;
&lt;li&gt;Manages search (SQLite FTS)&lt;/li&gt;
&lt;li&gt;Handles tasks parsing&lt;/li&gt;
&lt;li&gt;Exposes endpoints for links, journal, attachments, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why use a server internally?&lt;/p&gt;

&lt;p&gt;Because that unlocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A web UI&lt;/li&gt;
&lt;li&gt;A PWA for quick task updates&lt;/li&gt;
&lt;li&gt;Remote access&lt;/li&gt;
&lt;li&gt;A distributed sync engine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without changing the core vault model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Notes, Tasks, and Planning in One Surface
&lt;/h2&gt;

&lt;p&gt;Instead of splitting “notes” and “tasks” into different systems:&lt;/p&gt;

&lt;p&gt;Tasks are written directly inside notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Review proposal&lt;/li&gt;
&lt;li&gt;[ ] Ship release &lt;a class="mentioned-user" href="https://dev.to/high"&gt;@high&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system parses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checkboxes&lt;/li&gt;
&lt;li&gt;Dates&lt;/li&gt;
&lt;li&gt;Priorities&lt;/li&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s a task panel, calendar view, and journal layout:&lt;/p&gt;

&lt;p&gt;Journal/YYYY/MM/DD/DD.md&lt;/p&gt;

&lt;p&gt;Graph navigation lets you explore relationships, and “project mode” lets you filter from a specific root page — effectively zooming into a contextual slice of the vault.&lt;/p&gt;

&lt;p&gt;This has been especially useful for client or project-based work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Focus and Audience Modes
&lt;/h2&gt;

&lt;p&gt;One thing I wanted was control over noise.&lt;/p&gt;

&lt;p&gt;StillPoint includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Focus Mode (distraction-free writing)&lt;/li&gt;
&lt;li&gt;Audience Mode (simplified UI for screen sharing)&lt;/li&gt;
&lt;li&gt;Optional vi-style navigation for keyboard-heavy workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s designed to feel quiet, not busy.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI (Optional, Not Required)
&lt;/h2&gt;

&lt;p&gt;AI is supported but not mandatory.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Run against local model servers&lt;/li&gt;
&lt;li&gt;Use OpenAI-compatible APIs&lt;/li&gt;
&lt;li&gt;Configure your own endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page-scoped chat&lt;/li&gt;
&lt;li&gt;Global chat&lt;/li&gt;
&lt;li&gt;Draft/refine/transform actions&lt;/li&gt;
&lt;li&gt;Agent/tool loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if you never enable AI, the app still works completely fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Remote Models and Sync
&lt;/h2&gt;

&lt;p&gt;There are two remote approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remote Vault (Server-Trusted)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Server stores plaintext Markdown&lt;/li&gt;
&lt;li&gt;JWT-based authentication&lt;/li&gt;
&lt;li&gt;Role-based permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suitable for trusted/self-hosted setups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Homebase (Distributed / Zero-Trust Model)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Encrypted object replication&lt;/li&gt;
&lt;li&gt;Server stores opaque blobs&lt;/li&gt;
&lt;li&gt;Client-side key derivation&lt;/li&gt;
&lt;li&gt;Push/pull checkpoint sync&lt;/li&gt;
&lt;li&gt;Offline-first with conflict handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is to separate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Confidentiality&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m still refining this model and welcome feedback.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tradeoffs
&lt;/h2&gt;

&lt;p&gt;StillPoint is not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A SaaS product&lt;/li&gt;
&lt;li&gt;A real-time collaborative editor&lt;/li&gt;
&lt;li&gt;A CRDT-based multi-user system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It favors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplicity&lt;/li&gt;
&lt;li&gt;File transparency&lt;/li&gt;
&lt;li&gt;Explicit structure&lt;/li&gt;
&lt;li&gt;User-controlled sync&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;PySide6 (desktop UI)&lt;/li&gt;
&lt;li&gt;FastAPI (server)&lt;/li&gt;
&lt;li&gt;SQLite FTS&lt;/li&gt;
&lt;li&gt;JSON config&lt;/li&gt;
&lt;li&gt;Markdown vault on disk&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Build This?
&lt;/h2&gt;

&lt;p&gt;Because I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A calm place to think&lt;/li&gt;
&lt;li&gt;A journal that lives beside project work&lt;/li&gt;
&lt;li&gt;A task system inside notes&lt;/li&gt;
&lt;li&gt;A graph that can be filtered by context&lt;/li&gt;
&lt;li&gt;A server model without losing local-first principles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;StillPoint is open source and runnable locally. No signup required.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/grnwood/stillpoint" rel="noopener noreferrer"&gt;https://github.com/grnwood/stillpoint&lt;/a&gt;&lt;br&gt;
Site: &lt;a href="https://stillpoint.info/" rel="noopener noreferrer"&gt;https://stillpoint.info/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re interested in local-first software, distributed sync models, or file-based workflows, I’d love feedback.&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>productivity</category>
      <category>python</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
