English | 한국어
A web-based note application with integrated Git version control
- Multiple Document Formats: Markdown, AsciiDoc, TXT
- CodeMirror Editor: Syntax highlighting, line numbers, auto-completion
- Editing Toolbar: Markdown/AsciiDoc formatting buttons, table grid selector
- AsciiDoc Table Editor: Drag to select cells, merge/split, auto-generate span syntax
- Real-time Preview: Live rendering for Markdown/AsciiDoc
-
KaTeX Math Rendering: LaTeX syntax support (
$...$ ,$$...$$ ) - Editor/Preview Docking: Horizontal/vertical layout, tab mode, popout preview
- Git Version Control: Auto-commit all changes, 3-way diff comparison
- User Authentication: SQLite-based multi-user support
- Password Protection: Individual note encryption
- File Encryption: AES-256-GCM encryption for stored files (optional)
- File Attachments: Image and file upload (original filename restoration)
- 4 Themes: Light, Dark, Dark High Contrast, Dark Cyan
- Sidebar Font Size: Adjustable note list tree font size (Settings > General)
- Multi-language Support: English/Korean (changeable in Settings)
- Offline Support: All libraries included locally
- Short URLs: Generate short links for note sharing (public/private, expiration date)
- Calendar View: Sidebar mini calendar, date-based note management, auto YYYY/MM folder creation
- Folder Management: Drag & drop, expand/collapse, icon change, note move modal
- New Note Location: Folder selection modal when creating notes
- Tablet Support: Touch device optimization (44px minimum touch area)
- Tag Feature: YAML frontmatter storage, autocomplete, filter notes by tag
- Data Management: Note export/import, statistics view
- Cross-platform: Linux/macOS/Windows build without CGO
- Nginx Proxy: Operable on sub-paths
- Single Binary: Templates/static files embedded (go:embed)
- Daemon Mode: Background execution (start/stop/restart/status)
-
Log Rolling: Daily log file creation (
gitnotepad.log.YYYY-MM-DD) - Telegram Bot: Auto-save Telegram messages as notes (Long Polling)
- Media Preview: Video/audio playback in note preview (HTML5 video/audio)
- Telegram Media: Auto-download photos, videos, audio, voice messages, documents from Telegram
List View (Default):
┌─────────────────────────────────────────────────────────────┐
│ Git Notepad [+] [?] [⚙] [☀] │
├─────────────┬───────────────────────────────────────────────┤
│ [☰][📅] │ # Title │ # Title │
│ 📄 Note 1 │ │ │
│ 📄 Note 2 │ Content... │ Content... │
│ 📁 Folder │ │ │
│ 📄 Sub │ [Editor] │ [Preview] │
└─────────────┴───────────────────────────────────────────────┘
Calendar View:
┌─────────────────────────────────────────────────────────────┐
│ Git Notepad [+] [?] [⚙] [☀] │
├─────────────┬───────────────────────────────────────────────┤
│ [☰][📅] │ ◀ January 2025 ▶ [Today] │ Jan 15, 2025 │
│ │ Su Mo Tu We Th Fr Sa │ [+ New Note] │
│ │ 1 2 3 4 5 6 │ │
│ │ 7 8 9 10 11 12 13 │ 📄 Meeting │
│ │ 14 [15] 16 17 18 19 20 │ 📄 Diary │
│ │ 21 22 23 24 25 26 27 │ │
│ │ 28 29 30 31 │ │
└─────────────┴───────────────────────────────────────────────┘
- Go 1.21 or higher (CGO not required)
- Git (for version control feature)
# Clone repository
git clone https://github.com/playok/gitNotepad.git
cd gitNotepad
# Install dependencies
make deps
# Build
make build
# Run
./gitnotepadmake runAccess http://localhost:8080 in browser
gitnotepad # Auto mode (foreground if initial setup needed, else daemon)
gitnotepad --help # Show help
gitnotepad --nginx # Show nginx proxy setup guide
gitnotepad -config my.yaml # Specify config file
gitnotepad --reset-password <username> # Reset user passwordgitnotepad start # Start background daemon
gitnotepad stop # Stop daemon
gitnotepad restart # Restart daemon
gitnotepad status # Check daemon status
gitnotepad run # Foreground execution (for debugging)
gitnotepad start -config my.yaml # Start with specific config fileDefault Behavior: When run without arguments, it runs in foreground for initial setup (admin password), then starts as daemon once configured.
On first run, enter admin password in terminal:
╔════════════════════════════════════════════════════════════╗
║ Initial Admin Password Setup ║
╚════════════════════════════════════════════════════════════╝
Enter admin password:
Confirm admin password:
Admin password set successfully!
- Username:
admin(changeable in config.yaml) - Password: Enter directly in terminal (stored as SHA-512 hash in config.yaml)
Password is never stored in plaintext; SHA-512 hash is saved in config.yaml.
After logging in as admin:
- Click user icon in top right
- Select "Manage Users"
- Add new users or delete existing ones
- Click
+button at top of sidebar - Enter note title
- Select document format (MD/ADOC/TXT)
- Write content
| Format | Extension | Description |
|---|---|---|
| Markdown | .md |
GitHub Flavored Markdown support |
| AsciiDoc | .adoc |
Suitable for technical documentation |
| Text | .txt |
Plain text (no preview) |
Use / in note titles to create folder structure:
Project/Design Document
Project/Meeting Notes/2024-01
Personal/Diary
Moving Notes:
- Right-click note in list → "Move..."
- Select target folder in modal
- Move to root or existing folder
Creating New Notes:
- Click
+button to show location selection modal - Choose from root, existing folder, or new folder
- Click 🔒 icon at top of editor
- Set password
- Password required for next access
Pasting Images:
- Paste images from clipboard with
Ctrl+V
File Upload:
- Click 📎 button at top of editor
- Select file
- Markdown link automatically inserted
Viewing History:
- Click 🕐 button at top of editor
- 3-panel view: Version list + Previous version + Current version
- Color legend shows changes (red: deleted, green: added)
- Select version to view diff comparison
- Click "Restore" button to restore
Creating Share Links:
- Click share button at top of editor
- Set public/private
- Set expiration date (Never or select date)
- Copy generated link to share
Share Options:
- Public: Anyone can access without login
- Private: Login required
Expiration Options:
Never: Valid indefinitely- Select date: Valid until that date
Expired links are automatically cleaned up daily at midnight (notes are preserved)
Use layout control buttons at top of editor area for various layouts:
Layout Buttons:
- ⇔ Layout Direction: Toggle horizontal/vertical
- ⇉ Preview Position: Swap editor/preview order
- ☷ Tab Mode: Switch between editor and preview as tabs
- ⧉ Popout: Separate preview into new window
Popout Preview:
- Display preview in separate browser window
- Real-time sync when typing in editor
- Useful for dual monitor setups
Layout settings are saved in localStorage and persist across browser restarts.
- Select JSON text (or all)
- Press
Ctrl+Shift+For click{ }button - Indentation automatically applied
- Click ⚙ (Settings) button in top right
- Select Language in General tab
- Choose English or 한국어
Language setting applies immediately and is saved in localStorage.
Mini Calendar:
- Mini calendar displayed at top of sidebar
- Dates with notes shown with dots
Using Calendar:
- Navigate months: ◀ / ▶ buttons or "Today" button
- Select date: Click desired date
- View notes: Date notes panel shown in editor area
- Open note: Click note item to go to editor
Date Move (Drag & Drop):
- Drag note item from date panel
- Drop on desired date cell
- Note's creation date changes to that date
Creating New Notes:
- Select date then click "+ New Note" button
- Auto-saved in
YYYY/MM/folder (e.g.,2026/02/) - Date automatically entered as title (YYYY-MM-DD format)
server:
port: 8080 # Server port
host: "0.0.0.0" # Binding address
base_path: "" # Sub-path (for nginx proxy, e.g., "/note")
storage:
path: "./data" # Note storage path
auto_init_git: true # Auto Git initialization
logging:
encoding: "" # "utf-8" (default) or "euc-kr"
file: false # Enable file logging
dir: "./logs" # Log directory (daily rolling: gitnotepad.log.YYYY-MM-DD)
max_age: 30 # Log retention days
editor:
default_type: "markdown" # Default document format
auto_save: true # Auto save (after 2 seconds)
auth:
enabled: true # Enable authentication
session_timeout: 168 # Session expiration (hours)
admin_username: "admin" # Initial admin ID
admin_password_hash: "" # SHA-512 hash (auto-set on first run)
database:
path: "./data/gitnotepad.db" # SQLite DB path
encryption:
enabled: false # Enable file encryption
salt: "" # Encryption salt (auto-generated on first run)
daemon:
pid_file: "./gitnotepad.pid" # PID file path
telegram:
enabled: false # Enable Telegram bot
token: "" # Bot token from @BotFather
allowed_users: [] # Allowed Telegram user IDs
default_folder: "Telegram" # Default folder for notes
default_username: "admin" # GitNotepad username to save notes asDevelopment:
server:
port: 3000
auth:
enabled: false # Disable authenticationProduction:
server:
host: "127.0.0.1" # Allow localhost only
auth:
enabled: true
encryption:
enabled: true # Enable file encryptionTo operate on sub-path (/note):
config.yaml:
server:
port: 8080
host: "127.0.0.1"
base_path: "/note" # Set sub-pathnginx.conf:
location /note {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100M; # File upload size limit
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}Note:
client_max_body_sizesets the maximum file upload size. Default nginx limit is 1MB.
| Shortcut | Function |
|---|---|
Ctrl+N |
Create new note |
Ctrl+S |
Save |
Ctrl+F |
Focus search box |
Ctrl+B |
Toggle sidebar |
F1 or Ctrl+/ |
Help |
Esc |
Close modal |
| Shortcut | Function |
|---|---|
Ctrl+E |
Editor fullscreen |
Ctrl+P |
Preview fullscreen |
Ctrl+Shift+F |
JSON formatting |
Enter |
Auto-continue markdown list |
| Command | Description |
|---|---|
make |
Build for current OS |
make build |
Build for current OS |
make run |
Quick run |
make dev |
Run with config.yaml |
make clean |
Delete build artifacts |
make test |
Run tests |
make deps |
Install dependencies |
make tidy |
Clean go.mod |
make linux |
Linux build (amd64, arm64) |
make windows |
Windows build |
make darwin |
macOS build (amd64, arm64) |
make release |
Build all platforms |
On Windows, you can use build.cmd:
build :: Build for current OS
build run :: Quick run
build dev :: Run with config.yaml
build clean :: Delete build artifacts
build test :: Run tests
build deps :: Install dependencies
build tidy :: Clean go.mod
build linux :: Linux build
build windows :: Windows build
build darwin :: macOS build
build release :: Build all platforms
build help :: HelpgitNotepad/
├── main.go # Entry point
├── config.yaml # Config file
├── internal/
│ ├── config/ # Config loading
│ ├── daemon/ # Daemon management, log rolling
│ ├── database/ # SQLite initialization
│ ├── encryption/ # AES-256 encryption
│ ├── git/ # Git integration
│ ├── handler/ # HTTP handlers
│ ├── middleware/ # Auth middleware
│ ├── model/ # Data models
│ ├── repository/ # DB repositories
│ ├── server/ # Server setup
│ └── telegram/ # Telegram bot integration
├── web/
│ ├── static/
│ │ ├── css/ # Stylesheets
│ │ ├── js/ # JavaScript
│ │ └── lib/ # External libraries (for offline)
│ └── templates/ # HTML templates
└── data/ # Note storage (gitignore)
├── gitnotepad.db # SQLite DB
└── {username}/ # Per-user notes
├── .git/
├── note1.md
└── images/
| Method | Path | Description |
|---|---|---|
| POST | /api/auth/login |
Login |
| POST | /api/auth/logout |
Logout |
| GET | /api/auth/me |
Current user info |
| Method | Path | Description |
|---|---|---|
| GET | /api/notes |
List notes |
| GET | /api/notes/:id |
Get note |
| POST | /api/notes |
Create note |
| PUT | /api/notes/:id |
Update note |
| DELETE | /api/notes/:id |
Delete note |
| Method | Path | Description |
|---|---|---|
| POST | /api/images |
Upload image |
| POST | /api/files |
Upload file |
| GET | /api/git/history/:id |
Version history |
| GET | /api/git/version/:id/:hash |
Get specific version |
| Method | Path | Description |
|---|---|---|
| POST | /api/notes/:id/shortlink |
Create short URL |
| GET | /api/notes/:id/shortlink |
Get short URL |
| DELETE | /api/notes/:id/shortlink |
Delete short URL |
| Method | Path | Description |
|---|---|---|
| GET | /api/tags |
List all tags |
| Method | Path | Description |
|---|---|---|
| GET | /api/stats |
Get statistics |
| GET | /api/notes/export |
Export notes |
| POST | /api/notes/import |
Import notes |
| DELETE | /api/notes |
Delete all notes |
| Method | Path | Description |
|---|---|---|
| GET | /api/admin/users |
List users |
| POST | /api/admin/users |
Create user |
| DELETE | /api/admin/users/:id |
Delete user |
| PUT | /api/admin/users/:id/password |
Change password |
Encrypts note files with AES-256-GCM. Derives PBKDF2 key from user password.
Enable encryption in config.yaml:
encryption:
enabled: true
salt: "" # Auto-generated on first run- Key Derivation: Generate PBKDF2 key from password and salt on login (100,000 iterations, SHA-256)
- Encryption: Encrypt with AES-256-GCM when saving notes
- Storage Format: Saved as
ENC:base64_encoded_ciphertextin file - Decryption: Decrypt with session key when loading notes
- Session-based Key: Encryption key kept in memory only during login session
- Backward Compatibility: Existing unencrypted files still readable
- Auto Salt Generation: Security random salt auto-generated on first run
- Data unrecoverable if password lost after enabling encryption
- Existing encrypted files unreadable if salt changes
- Same password required for multiple users to access same encrypted notes
Save Telegram messages as Git Notepad notes automatically.
The bot uses Long Polling - it connects outbound to Telegram servers, so no port forwarding or public IP is required. Works behind NAT/firewall.
┌─────────────────┐ ┌─────────────────┐
│ Local Server │ ───(outbound)────▶ │ Telegram API │
│ (gitnotepad) │ ◀───(response)──── │ (telegram.org)│
└─────────────────┘ └─────────────────┘
-
Create Bot: Message @BotFather on Telegram
- Send
/newbot - Follow prompts to get your bot token
- Send
-
Get Your Telegram ID: Message @userinfobot
- It will reply with your numeric user ID
-
Configure
config.yaml:
telegram:
enabled: true
token: "123456789:ABCdefGHIjklMNOpqrsTUVwxyz"
allowed_users:
- 123456789 # Your Telegram user ID
default_folder: "Telegram"
default_username: "admin"- Restart gitnotepad
| Command | Description |
|---|---|
/start |
Show help message |
/info |
Show bot settings (folder, user, your ID) |
- Send text, photos, videos, audio, or documents to your bot
- Bot saves them as a Markdown note with attachments
- Note title = first line (max 50 chars)
- Auto-tagged with
telegram - Saved in configured folder (default:
Telegram)
| Type | Format | Description |
|---|---|---|
| Photos | JPG, PNG, GIF, WebP | Highest resolution downloaded |
| Videos | MP4 | Saved with original filename |
| Audio | MP3, OGG, WAV, FLAC, M4A | Title/performer metadata preserved |
| Voice | OGG | Voice messages from Telegram |
| Animation | GIF | Animated GIFs |
| Documents | PDF, ZIP, etc. | Original filename preserved |
- Media Groups (Albums): Multiple media sent together are saved as a single note
- Media Preview: Videos and audio files are playable directly in note preview
- Security: Only allowed users can create notes
- Auto Git Commit: Note + attachments committed in single commit
- Folder Organization: All Telegram notes in one folder
- Title Generation: First line of message becomes title
- Real-time Sync: Browser note list auto-refreshes via WebSocket
- Media Download: Files stored with UUID names, original filenames preserved in metadata
# Run on different port
./gitnotepad -port 3000Or change port in config.yaml
# Check if Git is installed
git --version
# Initialize data directory
rm -rf data/
./gitnotepad# Delete SQLite DB and restart
rm data/gitnotepad.db
./gitnotepadSee CHANGELOG.md for version history.
MIT License
Bug reports and feature suggestions welcome at GitHub Issues.