A minimal, aesthetic markdown notes app with real-time sync across devices.
- Markdown Editor - CodeMirror 6 with syntax highlighting
- Preview Mode - Toggle to see rendered markdown
- Folders - Organize notes into folders
- Tags - Tag notes for easy filtering
- Today View - Quick access to today's notes
- Search - Find notes by title or content
- Dark/Light Theme - Toggle between themes
- Offline Support - Works without internet, syncs when back online
- Multi-device Sync - Real-time sync via InstantDB
- Secure Email Auth - Magic link authentication (passwordless)
- Server-side Security - Permission rules prevent unauthorized access
- Native Desktop App - Multiplatform via Tauri (macOS, Windows, Linux)
- Go to instantdb.com
- Create a new app
- Copy your App ID
In your InstantDB dashboard, go to Permissions and add these rules:
{
"$users": {
"allow": {
"view": "false",
"create": "false",
"update": "false",
"delete": "false"
}
},
"notes": {
"allow": {
"view": "auth.id != null && data.ownerId == auth.id",
"create": "auth.id != null && newData.ownerId == auth.id",
"update": "auth.id != null && data.ownerId == auth.id && newData.ownerId == auth.id",
"delete": "auth.id != null && data.ownerId == auth.id"
}
},
"folders": {
"allow": {
"view": "auth.id != null && data.ownerId == auth.id",
"create": "auth.id != null && newData.ownerId == auth.id",
"update": "auth.id != null && data.ownerId == auth.id && newData.ownerId == auth.id",
"delete": "auth.id != null && data.ownerId == auth.id"
}
},
"tags": {
"allow": {
"view": "auth.id != null && data.ownerId == auth.id",
"create": "auth.id != null && newData.ownerId == auth.id",
"update": "auth.id != null && data.ownerId == auth.id && newData.ownerId == auth.id",
"delete": "auth.id != null && data.ownerId == auth.id"
}
}
}These rules ensure:
- Users cannot access the
$userstable - Users can only read/write their own notes, folders, and tags
- The
ownerIdcannot be changed after creation
Create a .env file in the root:
VITE_INSTANT_APP_ID=your-app-id-herenpm install
npm run devThe app includes a native desktop version built with Tauri, supporting macOS, Windows, and Linux.
-
Rust - Install via rustup.rs:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Platform-specific dependencies:
macOS:
xcode-select --install
Windows:
- Visual Studio Build Tools with "C++ build tools" workload
- WebView2 (pre-installed on Windows 11)
Linux (Ubuntu/Debian):
sudo apt update sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev
Linux (Fedora):
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file libappindicator-gtk3-devel librsvg2-devel sudo dnf group install "C Development Tools and Libraries"
npm run tauri:devThis starts both the Vite dev server and the Tauri native window with hot reload.
npm run tauri:buildThis creates native installers in src-tauri/target/release/bundle/:
- macOS:
.appand.dmg - Windows:
.exeand.msi - Linux:
.deb,.AppImage, and.rpm
npm run tauri:build:debugCreates a debug build with developer tools enabled.
| Shortcut | Action |
|---|---|
⌘N |
New note |
⌘P |
Toggle preview |
⌘S |
Save note |
- React 19 + Vite 7
- InstantDB - Real-time database with offline support
- CodeMirror 6 - Markdown editor
- react-markdown - Markdown preview
- TailwindCSS - Styling
- Tauri 2 - Native desktop app
src/
├── components/
│ ├── AuthModal.tsx # Email magic link auth
│ ├── Editor.tsx # CodeMirror editor
│ ├── FolderTree.tsx # Folder navigation
│ ├── NoteEditor.tsx # Editor + preview wrapper
│ ├── NoteList.tsx # Note list with search
│ ├── Preview.tsx # Markdown preview
│ └── Sidebar.tsx # Main sidebar
├── db/
│ └── instant.ts # InstantDB config
├── hooks/
│ ├── useAuth.ts # InstantDB auth
│ ├── useFolders.ts # Folder operations
│ ├── useNotes.ts # Note CRUD
│ ├── useTags.ts # Tag operations
│ ├── useTauri.ts # Tauri environment detection
│ └── useTheme.ts # Theme toggle
├── App.tsx
├── main.tsx
└── index.css # Tailwind + theme vars
src-tauri/
├── src/
│ ├── lib.rs # Tauri backend
│ └── main.rs # Entry point
├── icons/ # App icons for all platforms
├── Cargo.toml # Rust dependencies
└── tauri.conf.json # Tauri configuration
instant.perms.ts # Permission rules (for reference)
- Sign in with your email on any device
- Check your email for the magic code
- Enter the code to authenticate
- Your notes will automatically sync across all devices where you're signed in
Security: Your notes are protected by server-side permission rules. Only you can access your notes - no one else can read them, even with direct database access.
- Push your code to GitHub
- Go to vercel.com and import your repo
- Add environment variable:
VITE_INSTANT_APP_ID=your-app-id - Deploy
- Push your code to GitHub
- Go to netlify.com and import your repo
- Build command:
npm run build - Publish directory:
dist - Add environment variable:
VITE_INSTANT_APP_ID=your-app-id - Deploy
- Push your code to GitHub
- Go to Cloudflare Dashboard → Pages
- Connect your repo
- Build command:
npm run build - Build output directory:
dist - Add environment variable:
VITE_INSTANT_APP_ID=your-app-id - Deploy
npm run build
# Upload the `dist` folder to your hostAfter running npm run tauri:build, distribute the appropriate installer:
- macOS: Share the
.dmgfile - Windows: Share the
.msior.exeinstaller - Linux: Share the
.AppImage,.deb, or.rpmpackage
For automated cross-platform builds, add a GitHub Actions workflow:
# .github/workflows/release.yml
name: Release
on:
push:
tags: ['v*']
jobs:
release:
permissions:
contents: write
strategy:
fail-fast: false
matrix:
platform: [macos-latest, ubuntu-22.04, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Rust
uses: dtolnay/rust-action@stable
- name: Install dependencies (Ubuntu)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Install npm dependencies
run: npm ci
- name: Build
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VITE_INSTANT_APP_ID: ${{ secrets.VITE_INSTANT_APP_ID }}
with:
tagName: v__VERSION__
releaseName: 'Notes v__VERSION__'
releaseBody: 'See the assets to download this version and install.'
releaseDraft: true
prerelease: false- Desktop app (Tauri) ✅
- Mobile app (React Native / Tauri Mobile)
- Export to
.mdfiles - Note templates
- Vim keybindings