Modern web-based writing app with cloud sync. Kanban-style workflow: Ideas → Drafts → Finalized.
- Three-stage workflow — Ideas → Drafts → Finalized
- Cloud sync — Real-time sync across devices via InstantDB
- Magic code auth — Passwordless email authentication
- Distraction-free editor — Clean interface with native fullscreen mode
- Auto-save — Changes saved automatically on navigation
- Real-time word count — Live tracking with animated feedback
- Polished interactions — Smooth animations and hover states
- Node.js 18+ or Bun
- InstantDB account (free at instantdb.com)
# Clone the repo
git clone https://github.com/modernmedici/hemmingway.git
cd hemmingway
# Install dependencies
bun install
# or: npm install
# Set up environment variables
cp .env.example .env
# Add your InstantDB app ID and admin token to .env
# Push schema to InstantDB
bun x instant-cli push schema
bun x instant-cli push perms
# Start dev server
bun run dev
# or: npm run devOpen http://localhost:5173 and sign in with magic code authentication.
- Frontend: React 18 + Vite
- Database: InstantDB (real-time sync)
- Authentication: Magic code (passwordless email)
- Animations: Framer Motion
- Styling: CSS custom properties + Tailwind v4
- Typography: EB Garamond (serif) + Inter (sans-serif)
src/
├── instant.schema.ts # InstantDB schema definition
├── instant.perms.ts # User-scoped permissions
├── lib/
│ ├── db.js # InstantDB client initialization
│ └── constants.js # Fonts and column definitions
├── components/
│ ├── AuthScreen.jsx # Two-step magic code auth
│ ├── Board.jsx # Three-column Kanban layout
│ ├── Column.jsx # Individual column with animations
│ ├── PostCard.jsx # Card with move/delete actions
│ ├── WritingView.jsx # Distraction-free editor + fullscreen
│ └── AppShell.jsx # Main app container
└── hooks/
└── useKanban.js # All CRUD operations via InstantDB
| Action | How |
|---|---|
| Sign in | Enter email → receive code → enter code |
| Create post | Click + New Idea button |
| Edit post | Click any card |
| Save | Click Save or press ⌘↵ |
| Fullscreen | Click maximize icon or press ⌘⇧F |
| Exit fullscreen | Press Esc or hover top-right corner |
| Move post | Three-dot menu → Move to [column] |
| Delete post | Three-dot menu → Delete |
| Navigate back | Press Esc or click Back to Board |
Uses InstantDB's magic code authentication:
- User enters email
- InstantDB sends 6-digit code
- User enters code to sign in
- Session persists across devices
Test user (development):
- Email:
modernmedici88@gmail.com - Code:
424242
title(string) — Post titlebody(string, optional) — Post contentcolumn(string) — "ideas" | "drafts" | "finalized"createdAt(date) — Creation timestampupdatedAt(date) — Last modified timestamp
creator(user → post) — Post owner
- Users can only view/edit their own posts
- Posts are scoped by
creator.id
# Start dev server
bun run dev
# Build for production
bun run build
# Preview production build
bun run preview
# Run linter
bun run lint
# Run tests
bun run test
# Run tests in watch mode
bun run test:watch# Pull schema from production
bun x instant-cli pull schema
# Push local schema to production
bun x instant-cli push schema
# Query database
bun x instant-cli query '{ posts: {} }'
# Open InstantDB Explorer
bun x instant-cli explorer# Install Vercel CLI
npm i -g vercel
# Deploy
vercel# Install Netlify CLI
npm i -g netlify-cli
# Deploy
netlify deploy --prodRequired for production:
VITE_INSTANT_APP_ID=your-app-id-here.env or expose your admin token in client-side code.
User action → useKanban hook → InstantDB transact → Real-time sync → UI update
- InstantDB transactions — Atomic operations with
.transact() - Optimistic UI — InstantDB handles optimistic updates automatically
- User-scoped data — Posts linked to creator via
creatorrelationship - Auto-save — Changes saved on navigation, not explicit save button spam
- Fullscreen API — Native browser fullscreen (like YouTube)
- Framer Motion — Staggered animations for column cards
- CSS custom properties — Design tokens for consistent theming
| Shortcut | Action |
|---|---|
⌘↵ |
Save post |
⌘⇧F |
Toggle fullscreen mode |
Esc |
Exit editor / fullscreen / cancel |
- Check browser console for errors
- Verify InstantDB app ID in
.env - Check network tab for API failures
- Ensure user is authenticated
# Pull latest schema
bun x instant-cli pull schema
# Or push local schema
bun x instant-cli push schemaCheck instant.perms.ts and ensure:
isOwnerrule referencescreator.id- Posts are linked with
{ creator: user.id }
The previous Swift/Electron version used local file storage. To migrate:
- Export markdown files from
~/Desktop/Hemingway/ - Run migration script (see
docs/for details) - Posts preserve original timestamps and columns
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT
- InstantDB — Real-time database
- Framer Motion — Animation library
- Lucide Icons — Icon set
- EB Garamond — Serif typography