✨ Become an AI-era PM — words → product → doAIPM.com
#MD SoloMD

v3.5.5 — Win font fix, self-hosted analytics, PR #48 polish

Three things rolled into one patch: a 6-week-old Windows UI font regression finally diagnosed and fixed, telemetry migrated off Aptabase to our own Cloudflare D1 endpoint (zero third-party SaaS in the data path), and a polish PR from @beihai23 covering PDF export timeout, outline button location, and mermaid overlay contrast.

🇨🇳 The Windows UI font fix (issue #43)

A Win11 user (@sparkdonn-netizen) reported that since v0.1.12 the UI Chinese characters had gone slightly thin and inconsistent — not blurry exactly, but visibly different from native Win ClearType rendering. The picture made it obvious. The cause took longer to find.

Back in v0.1.12, commit 12b82c7 ("feat(ios): iPad v0.1.11 feature integration + CJK font fix") bundled a 43 KB LXGW WenKai subset as "SoloMD CJK" — a deliberately-soft handwritten font we embed for the iOS Simulator (which has no PingFang). The intent was a fallback. But the implementation put it first in the font-family chain, like this:

--font-ui: "SoloMD CJK", system-ui, -apple-system, ..., "Microsoft YaHei", ...

Combined with the @font-face rule's unicode-range: U+3400-9FFF, this told every Chromium / WebView2 / WKWebView: "for any CJK character, prefer SoloMD CJK over everything that follows." So Windows YaHei was bypassed for Chinese. Mac PingFang was bypassed. Linux Noto Sans CJK was bypassed. Everywhere fell through to the bundled handwritten font, which has thinner strokes than YaHei and looks visibly different especially at small UI sizes (toolbar buttons, sidebar items, menu text).

The Settings → Font picker didn't help because that picker only controls the editor font (the CodeMirror pane), not the UI chrome. The UI uses --font-ui, which SoloMD CJK had hijacked.

The fix: move "SoloMD CJK" from position 1 to last in the chain, no other changes. The unicode-range still triggers a download only when the bundled font is needed. On every real platform, the cascade now finds a system CJK font first:

Lesson saved internally: a bundled @font-face with unicode-range always goes last in the chain. The unicode-range gates download, not preference; chain order determines which font wins.

📊 Self-hosted analytics — Aptabase → Cloudflare D1

We had been using Aptabase — a privacy-respecting analytics service — to count app launches and feature usage. The dashboard showed ~2 active users despite 3,400+ downloads, which made it hard to reason about anything. Rather than diagnose the third-party SaaS, we ripped it out entirely.

The replacement is a single Cloudflare Pages Function backed by Cloudflare D1:

The Tauri side dropped tauri-plugin-aptabase entirely — including the runtime workaround for that plugin's Windows launch crash. The frontend's track() wrapper is now a 100-line fire-and-forget fetch with a 2-second timeout. Opt-out toggle stays in Settings → 发送匿名使用数据 (default on).

Architecture writeup is at web/ANALYTICS.md in the repo. The whole change is a single commit you can read end-to-end.

🐛 PR #48 — @beihai23 polish, four small wins

Big thanks to @beihai23 (王志刚) — third PR from this contributor, all of them quality fixes:

  1. PDF export 30-second timeout. markdownToPdfBlob now wraps its work in a Promise.race against a 30s timer, so html2pdf.js or Mermaid getting stuck no longer freezes the UI indefinitely. The DOM cleanup path is also idempotent now, eliminating double-remove exceptions on early errors.
  2. Outline button moved into the tab bar. The old floating ≌ button at the top-left of the editor area is gone. Each markdown tab now has its own ≌ icon — click it to toggle the outline pane for that tab specifically. Active state is accent-colored, non-active fades on hover.
  3. Mermaid SVG overlay contrast. When you click a Mermaid diagram to open it in the lightbox, the SVG now gets a theme-matching background card (white on light theme, dark slate on dark theme). Solves the "Mermaid lines invisible in dark mode lightbox" bug.
  4. HTML cleanup. The <table> elements in MarkdownHelp and Slideshow now wrap rows in <tbody>, eliminating a Vite build warning.

📥 Download

Download v3.5.5 →   All releases

v3.0.x+ users will see an in-app update prompt within 24h. On macOS, brew upgrade --cask solomd works too.

What's next — v3.6

Issue #44 — image and table inline rendering inside live edit mode — is next up. It's not a CSS change; it needs a CodeMirror block-decoration extension that intercepts image-syntax lines and renders the actual image inline (collapsing the source ![]() when the cursor isn't on that line). Same treatment for tables: render the formatted table when not editing, expand to source when the caret enters.

Beyond #44: iPad / Mac App Store resubmission gates are queued, and the v4 thrust on agent-endpoint surfaces (CLI + MCP + BYOK as the public surface for "any LLM can drive this vault") continues.

Comments & feedback

Comments live on GitHub Discussions — sign in once with your GitHub account.

Comments load from GitHub Discussions. If you see this message instead, the maintainer has not finished the one-time giscus.app setup yet — see web/COMMUNITY-SETUP.md.

Open on GitHub Discussions →