Skip to content

Repository files navigation

M34-Write

A modern, ultra-minimalist Markdown writing app built with TanStack Start, Milkdown, and Tailwind CSS.

Walkthrough

A quick walkthrough of creating a page, writing Markdown, and using slash commands in M34-Write.

Screenshots

Empty workspace Writing with Markdown Slash commands
Empty workspace Writing with Markdown Slash commands
New page Sidebar pages
New page Sidebar pages

Features

  • Clean, centered workspace — A distraction-free canvas with generous whitespace and monochrome styling.
  • Collapsible sidebar — Navigate pages, search, create new pages, and delete pages quickly.
  • Inline Markdown rendering — Write # headers, - lists, **bold**, code, blockquotes, and more; they render as you type.
  • Slash commands — Type / to insert headings, lists, todos, quotes, code blocks, dividers, and images.
  • Image uploads — Drag, drop, paste, or pick images; they are inlined as Base64 data URLs so everything stays local.
  • Autosave with status — Debounced persistence to localStorage with a live "Saving… / Saved" indicator.
  • Version history — Each page keeps up to 20 autosaved snapshots; view, diff, and revert to previous states.
  • Export — Download the current page as a clean PDF or raw Markdown (.md).
  • Local-first — No backend required; all data is stored in the browser's localStorage.

Desktop app

M34-Write can be run as a standalone desktop app on Linux, macOS, and Windows. The desktop build wraps the app in Electron and runs a local server internally — your notes still live in the app's own localStorage. Every desktop build includes the custom M34-Write "M" icon.

Prebuilt releases

Download the latest v0.1 desktop archives from /0.1v/bin/:

Platform Archive SHA256
Linux (x64) M34-Write-linux-x64.tar.gz 2b29238290b91336fc6e84565d4603f5e24feff38ec77931f069b2fe52e353dc
macOS (Apple Silicon) M34-Write-darwin-arm64.zip 9173d9897a502589c597ba45ee563509fe20a164a57050dec8bccfc00b05f0c8
Windows (x64) M34-Write-win32-x64.zip 82788ab235d00af3acef4d3cec42200bd8988fc836a078c8002a785831c0496e

Extract the archive for your platform and launch the M34-Write executable (M34-Write.app on macOS, M34-Write.exe on Windows).

Verify your download

All three checksums are also listed in /0.1v/bin/SHA256SUMS.

# macOS / Linux
shasum -a 256 M34-Write-linux-x64.tar.gz
# or, from inside /0.1v/bin/
sha256sum -c SHA256SUMS
# Windows (PowerShell)
Get-FileHash M34-Write-win32-x64.zip -Algorithm SHA256

GitHub Releases

Once the repo is connected to GitHub (Lovable → Plus menu → GitHub → Connect project), pushing a v* tag (e.g. git tag v0.1.0 && git push --tags) triggers .github/workflows/release.yml, which builds all three archives in CI and attaches them — plus a regenerated SHA256SUMS — to a GitHub Release at https://github.com/<owner>/<repo>/releases/latest.

Build it yourself

bun install
bun run electron:package   # produces electron-release/M34-Write-<platform>-<arch>/

Cross-compile from Linux by passing --platform=darwin or --platform=win32 and --arch=x64|arm64:

bun run build
npx @electron/packager . M34-Write --platform=darwin --arch=arm64 --overwrite --out=electron-release \
  --ignore='^/src' --ignore='^/public' --ignore='^/docs' --ignore='^/electron-release' \
  --ignore='^/node_modules' --ignore='^/dist'

Run in development

bun run electron:dev

Notes

  • Archives are not code-signed — macOS and Windows will show an unsigned-app warning on first launch (right-click → Open on macOS; "More info → Run anyway" on Windows).
  • The app spawns a local HTTP server on 127.0.0.1 at a random-ish port; no data leaves your machine.

Android app

M34-Write also ships as a native Android app (Capacitor shell around the same offline bundle — notes stay in the app's local storage, nothing is uploaded).

bun run mobile:sync    # build the static web bundle + copy it into android/
bun run android:apk    # android/app/build/outputs/apk/release/*.apk
bun run android:aab    # android/app/build/outputs/bundle/release/*.aab  (Play Store upload)

Requires JDK 21 and the Android SDK (ANDROID_HOME). Open the project in Android Studio with bunx cap open android for emulator runs.

Release signing is read from the environment, so nothing secret lives in the repo:

Variable Purpose
MONO_VERSION_NAME Version name, e.g. 0.1.0
MONO_VERSION_CODE Integer build number, must increase per Play upload
MONO_KEYSTORE_PATH Path to the upload keystore (unsigned build if unset)
MONO_KEYSTORE_PASSWORD / MONO_KEY_ALIAS / MONO_KEY_PASSWORD Keystore credentials

Signing setup (one time): run bash scripts/make-keystore.sh, then add MONO_KEYSTORE_BASE64, MONO_KEYSTORE_PASSWORD, MONO_KEY_ALIAS and MONO_KEY_PASSWORD as GitHub repository secrets (Settings -> Secrets and variables -> Actions). Back the keystore up outside the repo — store updates must use the same key forever.

Pushing a v* tag then builds signed M34-Write-android.apk / M34-Write-android.aab in CI (downloadable from the GitHub Releases page, and from the run's Artifacts -> M34-Write-android). If the secrets are missing the tagged run fails instead of publishing an unsigned build; manual runs still produce M34-Write-android-UNSIGNED.apk for local testing only. The Android versionCode is derived from the tag (MAJOR*10000 + MINOR*100 + PATCH, so v0.1.0 -> 100), so reruns are reproducible and newer tags always sort higher.

Before submitting to a store: PRIVACY.md must be pushed to main — store reviewers open https://github.com/RU22-S-LABS/Mono-Write/blob/main/PRIVACY.md, and that URL 404s until the file is on the remote branch.

App stores

M34-Write can be published to Google Play and the Indus Appstore (India) from the same signed Android build:

Store Upload file Guide
Google Play M34-Write-android.aab (release notes call it M34-Write-google-play.aab) docs/play-store.md
Indus Appstore M34-Write-android.apk (release notes call it M34-Write-indus-appstore.apk) docs/indus-appstore.md

Tech Stack

  • Framework: TanStack Start (React 19, Vite 8)
  • Editor: Milkdown (Crepe preset)
  • State: Zustand with custom debounced persistence
  • Styling: Tailwind CSS 4 + shadcn/ui components
  • Typography: Geist Sans
  • Icons: Lucide React

Getting Started

# Install dependencies
bun install

# Start the dev server
bun dev

Open http://localhost:8080 to start writing.

Scripts

Script Description
bun dev Start the Vite dev server
bun build Build for production
bun build:dev Build in development mode
bun preview Preview the production build
bun lint Run ESLint
bun format Format code with Prettier

Project Structure

src/
├── components/
│   ├── app-sidebar.tsx      # Collapsible sidebar navigation
│   ├── diff-view.tsx        # Diff dialog for history snapshots
│   ├── markdown-editor.tsx  # Milkdown editor wrapper
│   └── workspace.tsx        # Main writing canvas + export actions
├── hooks/
│   ├── use-mobile.tsx
│   └── use-notes-store.ts   # Zustand store + localStorage persistence
├── routes/
│   ├── __root.tsx           # Root layout + head metadata
│   ├── index.tsx            # Home page with sidebar + workspace
│   └── README.md            # TanStack Start routing conventions
├── styles.css               # Monochrome tokens + editor overrides
└── lib/                     # Utilities and error handling

Data Storage

All notes and their version history are saved to localStorage under the key md-notes:v1. The app is designed to work fully offline in the browser with no backend. If you later want cloud sync or file storage, the editor and components can remain unchanged while swapping the storage layer.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages