MarkEdit#
A modern, git-based markdown editor for managing blog posts stored in GitHub repositories. Edit your markdown files with a beautiful WYSIWYG editor, track changes with automatic version control, and publish updates via pull requests.
Features#
- 🎨 Beautiful WYSIWYG Editor - Rich text editing powered by TipTap with markdown support
- 📝 Frontmatter Support - Edit YAML frontmatter metadata alongside your content
- 💾 Auto-save - Changes are automatically saved as drafts every 2 seconds
- 🔄 Git Integration - Automatic branching, commits, and pull request creation
- 🔐 GitHub OAuth - Secure authentication with your GitHub account
- 📂 Multi-repo Support - Work with multiple repositories and folder structures
- ⚡ Fast & Lightweight - Built with modern technologies for optimal performance
- 🐳 Docker Ready - Easy deployment with Docker and docker-compose
Tech Stack#
Backend#
- Go 1.24+ - High-performance backend server
- chi - Lightweight router
- go-git - Native Git operations
- SQLite (modernc.org/sqlite) - Pure Go database, no CGO required
- goth - GitHub OAuth authentication
Frontend#
- Astro - Fast, client-only static site generation
- React 18 - UI components
- TipTap - WYSIWYG markdown editor
- shadcn/ui - Beautiful, accessible components
- Tailwind CSS - Utility-first styling
- React Query - Data fetching and state management
Quick Start#
Prerequisites#
- Docker and Docker Compose installed
- GitHub OAuth application credentials (Setup Guide)
Run with Docker#
- Clone the repository:
git clone https://github.com/yourusername/markedit.git
cd markedit
- Copy the environment file and configure:
cp .env.example .env
# Edit .env with your GitHub OAuth credentials
- Start the application:
make up
- Open your browser to
http://localhost:3000
That's it! The application will be running with all dependencies containerized.
Development#
Local Development Setup#
Backend#
Requirements:
- Go 1.24 or higher
cd backend
cp .env.example .env
# Edit .env with your credentials
# Run migrations and start server
go run cmd/server/main.go
The backend will start on http://localhost:8080
Frontend#
Requirements:
- Bun 1.x or higher
cd frontend
bun install
bun run dev
The frontend will start on http://localhost:4321
How It Works#
Workflow#
- Authenticate - Sign in with your GitHub account
- Select Repository - Choose the GitHub repo containing your blog posts
- Select Folder - Optionally specify a folder within the repo
- Edit Files - Browse and edit markdown files with the WYSIWYG editor
- Auto-save - Changes are automatically saved as drafts
- Publish - Create a pull request with your changes
Git Integration#
MarkEdit uses a smart branching strategy:
- Creates timestamped branches:
markedit-{unix_timestamp} - Reuses branches if they're less than 4 hours old
- Automatically commits your changes with descriptive messages
- Creates pull requests with your custom title and description
- Cleans up drafts after successful publication
Draft System#
- All edits are saved as drafts in the SQLite database
- Drafts are user-specific and file-specific
- Published changes replace the draft content
- Drafts are automatically deleted after successful PR creation
Architecture#
markedit/
├── backend/ # Go server
│ ├── cmd/server/ # Main entry point
│ ├── internal/
│ │ ├── api/ # HTTP handlers
│ │ ├── auth/ # OAuth & sessions
│ │ ├── database/ # SQLite & queries
│ │ ├── git/ # Git operations
│ │ └── markdown/ # Frontmatter parsing
│ └── Dockerfile
├── frontend/ # Astro + React
│ ├── src/
│ │ ├── components/
│ │ ├── lib/ # API client & hooks
│ │ └── pages/
│ ├── nginx.conf
│ └── Dockerfile
└── docker-compose.yml
API Endpoints#
Authentication#
GET /auth/github- Initiate GitHub OAuth flowGET /auth/github/callback- OAuth callback handlerGET /auth/user- Get current user infoPOST /auth/logout- Logout current user
Repositories#
GET /api/repos- List user's repositoriesGET /api/repos/:owner/:repo/files- List files in repositoryGET /api/repos/:owner/:repo/files/*path- Get file contentPUT /api/repos/:owner/:repo/files/*path- Save draft content
Git Operations#
GET /api/repos/:owner/:repo/branch/status- Get current branch infoPOST /api/repos/:owner/:repo/publish- Commit, push, and create PR
Configuration#
Environment Variables#
See SETUP.md for detailed configuration instructions.
Backend (.env):
GITHUB_CLIENT_ID=your_github_oauth_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_client_secret
SESSION_SECRET=random-32-character-string
DATABASE_PATH=./data/markedit.db
GIT_CACHE_DIR=./data/repos
CORS_ALLOWED_ORIGINS=http://localhost:4321,http://localhost:3000
Frontend (frontend/.env):
PUBLIC_API_URL=http://localhost:8080
Deployment#
Docker Production Deployment#
- Configure environment variables in
.env - Build and start containers:
make build
make up
- Check logs:
make logs
- Stop containers:
make down
Manual Deployment#
See SETUP.md for detailed deployment instructions for various platforms.
Makefile Commands#
make build # Build Docker images
make up # Start containers
make down # Stop containers
make restart # Restart containers
make logs # View logs
make logs-f # Follow logs
make clean # Remove containers and volumes
make shell-be # Access backend shell
make shell-fe # Access frontend shell
Design Philosophy#
MarkEdit features a distinctive brutalist/editorial aesthetic:
- Typography: Archivo Black for headings, Crimson Pro for body text
- Colors: Amber/orange accents (#d97706) with strong black borders
- Style: Bold 2px borders, grain texture backgrounds, no gradients
- UX: Clear, direct interactions with immediate feedback
Security#
- OAuth tokens are securely stored and never exposed to the frontend
- Session cookies are encrypted and HTTP-only
- File operations are scoped to authenticated user's accessible repos
- Git operations use the user's GitHub token with appropriate permissions
Contributing#
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
License#
MIT License - see LICENSE for details
Support#
For detailed setup instructions, see SETUP.md
For issues and feature requests, please use GitHub Issues