A clean, privacy-focused, self-hosted note-taking application with markdown support, rich text editing, and complete data sovereignty. Your notes are stored as simple markdown files that you own and control.
Whiteboard is built on the principle that your notes should belong to you. No subscriptions, no cloud lock-in, no tracking. Just a simple, powerful tool that respects your data and your privacy.
- Rich Text Editor: WYSIWYG editing powered by Toast UI Editor with markdown support
- Auto-save: Changes save automatically 1 second after editing
- Multiple Views: Grid, list, and grouped organization modes
- Privacy Mode: Hide note previews for sensitive work
- Word Count: Real-time word count tracking
- Document Titles: Editable titles displayed in the footer
- Tags: Categorize notes with searchable tags
- Groups: Organize notes into multiple groups (notes can belong to several groups)
- Tag Cloud: Visual overview of all tags with usage frequency
- Full-Text Search: Search across note titles, content, tags, and groups
- Collage View: Visual grid of note cards with previews
- Grouped View: Notes organized by their assigned groups
List view showing notes with tags and metadata
Tag cloud for quick filtering by tags
- Shareable Links: Generate public links for individual notes
- Password Protection: Optional password protection for notes
- Share Management: View and revoke active share links
- Session Security: Automatic session validation and timeout handling
- Privacy Controls: Toggle preview visibility for sensitive environments
- Image Support: Upload and embed images (JPEG, PNG, GIF, WebP, SVG)
- 10MB Limit: Per-image size limit for reasonable storage
- Markdown Import: Import existing markdown files
- Bulk Export: Export all notes as a ZIP archive of markdown files
- Pure Markdown: Notes stored as standard .md files for maximum portability
- User Accounts: Multiple users with individual note collections
- Admin Panel: User management and system settings
- Role-Based Access: Admin and regular user roles
- Password Management: Users can change their own passwords
- Isolated Storage: Each user's notes stored separately
Admin panel for managing users, settings, and backups
- Mobile-First Design: Fully responsive interface for all screen sizes
- Touch Optimized: Context menus and controls designed for touch
- Collapsible Navigation: Sidebar collapses on mobile devices
- Landscape Support: Optimized for both portrait and landscape
- Print-Friendly: Clean print layouts for note archival
- Docker and Docker Compose (recommended for production)
- Node.js 18.x or higher (for local development only)
- npm or yarn package manager (for local development only)
The primary and recommended way to run Whiteboard is through Docker using the included Dockerfile and docker-compose.yml.
Quick start with Docker:
git clone <repository-url>
cd Whiteboard
docker compose up -dAccess the application at http://localhost:2452
Default credentials:
- Username:
admin - Password:
admin123
For development purposes only:
- Clone the repository:
git clone <repository-url>
cd Whiteboard- Install dependencies:
npm install- Start the development server:
npm run dev- Access the application at http://localhost:2452
Create a .env file in the project root:
# Session secret for cookie encryption (REQUIRED in production)
SESSION_SECRET=your-secure-random-string-here
# Port to run the server on (default: 2452)
PORT=2452
# Timezone (default: America/New_York)
TZ=America/New_YorkThe SESSION_SECRET is used to encrypt user session cookies. It must be a long, random string that is impossible to guess.
Option 1: Using OpenSSL (Linux/Mac)
openssl rand -base64 32Option 2: Using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"Option 3: Using Python
python3 -c "import secrets; print(secrets.token_urlsafe(32))"Option 4: Online Generator Visit https://www.random.org/strings/ and generate a random string with:
- Length: 32 characters
- Character set: Alphanumeric + symbols
Example .env file:
SESSION_SECRET=K7x9mP2nQ5wR8tY3uI6oA1sD4fG7hJ0k
PORT=2452
TZ=America/New_YorkImportant:
- Never share your SESSION_SECRET with anyone
- Never commit it to version control (the .env file is already in .gitignore)
- Use a different secret for each deployment (development, staging, production)
- If compromised, generate a new secret immediately (all users will need to log in again)
After logging in as admin:
- Navigate to Admin Panel
- Go to Settings
- Configure Public URL Base for share links (e.g., https://yourdomain.com)
- Click the "+ New Note" button
- Enter a name for the note
- Start writing in the editor
- The title can be edited in the footer while viewing the note
- Changes auto-save after 1 second
Creating a new note with a custom name
Tags:
- Right-click on a note
- Select "Manage Tags"
- Add or remove tags
- Press Enter to add each tag
Groups:
- Right-click on a note
- Select "Add to Group"
- Choose an existing group or create a new one
- Notes can belong to multiple groups
- Toggle "All Notes/Groups" to switch between views
Tag Cloud:
- Click your username in the top-right
- Select "Tag Cloud"
- Click any tag to filter notes by that tag
- Use the search bar to find notes by title, content, tags, or groups
- Switch between Grid and List view using the toggle controls
- Toggle between All Notes and Groups view
- Enable Privacy Mode to hide note previews
- Right-click on a note
- Select "Share Link"
- Copy the generated link
- Optionally, password protect the note first via "Password Protect"
Managing Shared Links:
- Click your username
- Select "Manage Shared Notes"
- View all active share links
- Copy links or revoke sharing
Import:
- Click your username
- Select "Import Notes (.md)"
- Choose one or more markdown files
- Notes will be imported into your collection
Export:
- Click your username
- Select "Export All Notes"
- Downloads a ZIP file containing all your notes as markdown files
User Management:
- Click "Admin Panel"
- Create, update, or delete user accounts
- Toggle admin privileges
- Reset user passwords
Settings:
- Click "Admin Panel"
- Navigate to Settings tab
- Update Public URL Base for share links
Whiteboard/
├── server.js # Express server and API routes
├── package.json # Node.js dependencies
├── Dockerfile # Docker image configuration
├── docker-compose.yml # Docker Compose configuration
├── migrate-to-database.js # Migration script for database architecture
├── MIGRATION.md # Migration documentation
├── DOCKER.md # Docker deployment guide
├── linux-app.md # Native Linux app documentation
├── android-app.md # Native Android app documentation
├── vscode-setup.md # VSCode development setup guide
├── public/ # Frontend static files
│ ├── index.html # Main application page
│ ├── app.js # Frontend JavaScript (Toast UI Editor)
│ ├── styles.css # Application styles
│ ├── login.html # Login page
│ ├── login.js # Login functionality
│ ├── login.css # Login styles
│ ├── admin.html # Admin panel page
│ ├── admin.js # Admin functionality
│ ├── admin.css # Admin styles
│ └── favicon.svg # Application icon
├── data/ # User notes and media (runtime)
│ ├── _system/ # System-level metadata
│ │ └── users-index.json # Tracks all users with data
│ └── username/ # Per-user directory
│ ├── database.json # Per-user note index (fast lookups)
│ └── notes/ # User's notes
│ ├── note-id.md # Markdown content files
│ └── media/ # Media files
│ └── note-id/ # Per-note media directory
├── shared/ # Shared note metadata (runtime)
├── users.json # User accounts (created on first run)
└── settings.json # Application settings (created on first run)
Whiteboard uses a per-user database architecture for optimal performance:
data/
├── _system/
│ └── users-index.json # System-level: tracks all users
└── username/
├── database.json # Per-user: indexes all notes with metadata
└── notes/
├── note-id.md # Raw markdown files
└── media/
└── note-id/ # Per-note media files
- Fast Traversal: Single database.json read gives all note metadata
- Pure Markdown: Content stored as standard .md files
- Scalable: Each user has their own isolated database
- Simple Backups: Just backup the data directory
- Portable: Markdown files work with any editor
User Database (data/username/database.json):
{
"notes": {
"abc123def456": {
"title": "My Note",
"tags": ["work", "important"],
"groups": ["Projects", "Active"],
"isPasswordProtected": false,
"shareId": "xyz789...",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-02T00:00:00.000Z"
}
}
}Markdown File (data/username/notes/abc123def456.md):
# My Note Content
Pure markdown content here...POST /api/auth/login- User loginPOST /api/auth/logout- User logoutGET /api/auth/me- Get current userPOST /api/auth/change-password- Change password
GET /api/files- List all notes for current userGET /api/file/:noteId- Get specific notePOST /api/file/:noteId- Save/update notePOST /api/files/new- Create new noteDELETE /api/file/:noteId- Delete notePOST /api/file/metadata/:noteId- Update note metadata (tags, groups, password)POST /api/file/verify-password/:noteId- Verify note passwordPOST /api/file/move- Move note to different folder
POST /api/file/share/:noteId- Generate share linkDELETE /api/file/share/:noteId- Remove share linkGET /api/shared/:shareId- Access shared note (public)GET /api/shares- List all shared notes for current user
POST /api/notes/:noteId/upload- Upload imageGET /api/media/:userId/:noteId/:filename- Access media file
POST /api/notes/import- Import note from markdownGET /api/notes/export- Export all notes as ZIP
GET /api/search?q=query- Search notes (title, content, tags, groups)
GET /api/admin/users- List all usersPOST /api/admin/users- Create new userPUT /api/admin/users/:username- Update userDELETE /api/admin/users/:username- Delete userGET /api/admin/settings- Get application settingsPUT /api/admin/settings- Update application settings
-
Change Default Credentials
- Immediately change the admin password after first login
-
Set Strong Session Secret
- Generate a strong random string for SESSION_SECRET
- Never commit this to version control
-
Use HTTPS
- Deploy behind a reverse proxy (nginx, Caddy, Traefik)
- Obtain SSL certificate (Let's Encrypt recommended)
-
Regular Backups
- Backup the
data/directory regularly - Backup
shared/directory for share links - Backup
users.jsonfor user accounts - Backup
settings.jsonfor application settings
- Backup the
-
Keep Dependencies Updated
- Regularly run
npm auditto check for vulnerabilities - Update dependencies with
npm update
- Regularly run
- User passwords are hashed with bcrypt
- Note passwords are hashed separately per note
- Session cookies are HTTP-only and signed
Ctrl+S(orCmd+Son Mac) - Manual save current noteEnter- Submit in modals and tag inputEscape- Close modals
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile browsers (iOS Safari, Chrome Mobile)
A native Android application is in development using Kotlin and Jetpack Compose. Features:
- Native Material Design 3 interface
- Offline-first with local SQLite storage
- Background sync with server
- Native sharing integration
- Biometric authentication support
A native Linux application is in development using Rust and GTK 4.
Features:
- Native GTK 4 interface with libadwaita
- Desktop integration (notifications, system tray)
- Flatpak packaging for easy distribution
- Offline-first with local storage
- Background sync support
- Auto-save debounced to 1 second
- Search debounced to 300ms
- Images lazy-loaded in editor
- Efficient CSS with minimal reflows
- Session validation every 5 minutes
- Single database read for all note metadata
If port 2452 is already in use:
- Change PORT in
.envfile - Update
docker-compose.ymlport mapping - Restart the application
- Check that
users.jsonexists in project root - Delete
users.jsonto reset to default admin account - Restart the server
- Login as admin
- Go to Admin Panel > Settings
- Set Public URL Base to your domain
- New share links will use this base URL
- Check that
data/directory exists and is writable - Verify file permissions
- Check browser console for 403/404 errors
- Toggle to "Groups" view using the switch
- Notes must be added to groups via right-click menu
- Refresh the page if groups don't appear
- ES6+ JavaScript features
- Async/await for asynchronous operations
- Functional programming patterns where appropriate
- Clear variable and function names
- Comments for complex logic
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
GPLv3 License
Whiteboard is free and open-source software licensed under the GNU General Public License v3.0. This ensures that the software remains free forever, anyone can study and modify the code, and all modifications must also be open source under GPLv3.
Contributions are welcome. Please:
- Open an issue to discuss major changes
- Follow the existing code style
- Add appropriate documentation
- Test your changes thoroughly
For issues, questions, or feature requests, please open an issue on the project repository.
These are planned features for future releases. Community contributions welcome!
- Share notes with other users on the same server for real-time collaboration
- Shared notes appear in a "Shared Notes" group for all collaborators
- Both users can edit the note simultaneously with conflict resolution
- Changes sync automatically between collaborators
- Permission levels: view-only, edit, or owner
- Full dark theme for the entire interface
- Toggle between light and dark mode in settings
- Respects system theme preferences
- Separate dark mode styling for editor, collage view, and admin panel
- Reduced eye strain for night-time note-taking
- Browser extension for clipping web pages directly into notes
- Save entire articles or selected text with formatting preserved
- Automatic metadata extraction (title, URL, date)
- Convert web pages to clean markdown
- Batch clip multiple pages into a single note or separate notes
- Real-time collaborative editing with cursor presence
- Note version history and rollback
- Nested folders for better organization
- Note templates for common formats
- Quick capture widget for desktop
- Mobile apps (Android and iOS) with offline sync
- Two-factor authentication for enhanced security
- API webhooks for integrations
- Markdown table editor with GUI
- Diagram support (Mermaid, PlantUML)
Want to help? These features are open for community implementation. Check the issues page or submit a proposal!
- Added Toast UI Editor replacing Quill
- Added Groups feature for organizing notes
- Added All Notes/Groups toggle view
- Added Privacy Mode to hide note previews
- Added Tag Cloud visualization
- Added sticky toolbar that stays visible when scrolling
- Added document title editing in footer
- Added context menu with submenus for groups
- Improved mobile responsiveness
- Fixed scrolling issues with toolbar
- Enhanced collage view with better card layouts
- Added list view mode for notes
- Improved search to include groups
- Per-user database architecture
- Each user gets their own database.json for fast note indexing
- System-level users index for tracking all users
- Pure markdown files (no metadata mixed in)
- Media files organized per-note under notes/media/
- Added visible Save button with state indicators
- Migration script for upgrading from previous versions
- Split note storage format (metadata.json + content.md)
- Added migration script for legacy notes
- Maintained backward compatibility
- Improved performance for note list operations
- Initial release
- Rich text editing with Quill
- Multi-user support
- Note sharing functionality
- Password protection
- Import/export features
- Admin panel
- Mobile-responsive design
- Docker support
