Skip to content

Distraction-free, minimalist writing environment built with Svelte.

Notifications You must be signed in to change notification settings

danielbodnar/zenwriter

Repository files navigation

Zen Writer

A distraction-free writing application with AI-powered assistance, built with Tauri, SvelteKit, and TypeScript.

Features

  • Zen Mode - Minimalist interface that hides controls until needed
  • Focus Mode - Dims non-active paragraphs while writing
  • AI Ghost Text - Intelligent text suggestions that appear as you type
  • Slash Commands - Quick formatting with / menu
  • Bubble Menu - Context-aware toolbar on text selection
  • AI Sidebar - Chat-based writing assistant
  • Auto-Save - Documents persist automatically with 2-second debounce
  • Cross-Platform - Runs on Windows, macOS, and Linux

Tech Stack

Layer Technology
Desktop Framework Tauri 2.0 (Rust)
Frontend Framework SvelteKit 2.9 + Svelte 5
Editor Tiptap 3.18 (ProseMirror-based)
Styling Tailwind CSS 4
UI Components bits-ui
Language TypeScript 5.6 (strict mode)
Package Manager Bun

Prerequisites

  • Bun v1.2.23+
  • Rust (latest stable)
  • Platform-specific dependencies for Tauri:
    • Linux: webkit2gtk, libappindicator
    • macOS: Xcode Command Line Tools
    • Windows: WebView2, Visual Studio Build Tools

Getting Started

Install Dependencies

bun install

Development

Run the desktop application in development mode:

bun run tauri:dev

Or run just the web frontend (without Tauri):

bun run dev

Build

Build the production application:

bun run tauri:build

Output binaries are located in src-tauri/target/release/bundle/.

Project Structure

zen-writer/
├── src/                          # Frontend (SvelteKit)
│   ├── lib/
│   │   ├── components/
│   │   │   ├── editor/           # Editor components
│   │   │   │   ├── ZenEditor.svelte    # Main Tiptap editor
│   │   │   │   ├── BubbleMenu.svelte   # Selection toolbar
│   │   │   │   └── SlashMenu.svelte    # Command palette
│   │   │   └── ui/               # Reusable UI components
│   │   ├── extensions/           # Custom Tiptap extensions
│   │   │   └── ghost-text.ts     # AI suggestion extension
│   │   ├── stores/               # State management
│   │   │   └── document.svelte.ts
│   │   └── tauri/                # Tauri IPC wrappers
│   │       └── commands.ts
│   └── routes/
│       └── +page.svelte          # Main application
├── src-tauri/                    # Backend (Rust)
│   ├── src/
│   │   ├── main.rs               # Entry point
│   │   └── lib.rs                # Commands & document storage
│   └── tauri.conf.json           # Tauri configuration
└── package.json

Keyboard Shortcuts

Editor

Shortcut Action
/ Open command menu
Cmd+K AI chat with selection
Tab Accept ghost suggestion
Esc Dismiss menu/suggestion

Formatting

Shortcut Action
Cmd+B Bold
Cmd+I Italic
Cmd+U Underline
Cmd+Shift+X Strikethrough
Cmd+E Inline code

Application

Shortcut Action
Cmd+S Save document
Cmd+N New document
Cmd+\ Toggle AI sidebar
Cmd+. Toggle zen mode
? Show shortcuts

Scripts

bun run dev          # Start SvelteKit dev server
bun run build        # Build static frontend
bun run preview      # Preview production build
bun run check        # TypeScript type checking
bun run tauri:dev    # Run Tauri in development
bun run tauri:build  # Build production app
bun run lint         # Run linters (oxlint + biome)
bun run lint:fix     # Auto-fix lint issues
bun run format       # Format code with biome

Architecture

Document Flow

User Input → Document Store → Tauri Command → Rust Backend → File System
                   ↓
            Auto-save (2s debounce)
                   ↓
            ~/.config/zen-writer/documents/

AI Integration Points

The Rust backend exposes these commands (currently mock implementations):

  • complete_text - Ghost text suggestions
  • transform_text - Rewrite/edit selected text
  • analyze_document - Document analysis and feedback

State Management

Uses Svelte 5 runes for reactive state:

// Reactive state
let currentDocument = $state<Document | null>(null);
let documents = $state<Document[]>([]);

// Derived values
const isDirty = $derived(/* ... */);
const saveStatus = $derived(/* ... */);

Configuration

Tauri (src-tauri/tauri.conf.json)

  • Window: 800x600 default
  • Bundle targets: all platforms
  • App identifier: com.zenwriter.app

TypeScript (tsconfig.json)

  • Strict mode enabled
  • Path alias: $lib./src/lib

Biome (biome.json)

  • 2-space indentation
  • 100-character line width
  • Import organization enabled

IDE Setup

Recommended extensions:

License

MIT

About

Distraction-free, minimalist writing environment built with Svelte.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published