A privacy-first, client-side-only Markdown editor where your content lives in the URL.
- Client-side only - No backend, no server, no database
- Markdown editor - Full-featured textarea with live preview
- Live preview - Real-time Markdown rendering with marked.js
- Copy URL button - One-click URL copying with fallback
- Clear button - Reset document with confirmation
- Light/dark mode - CSS-only theme switching with system preference detection
- URL length warning - Alerts when URL exceeds 2000 characters
- Responsive design - Mobile-friendly layout
- Zero Server: Everything runs in your browser—no backend, no database, no API calls
- Privacy by Design: Your content never leaves your device
- URL-based Storage: All document state is encoded in the URL fragment
- Live Preview: See your Markdown rendered in real-time
- Share Anywhere: Just copy and share the URL
- Works Offline: No internet required after initial load
- Theme Support: Built-in light and dark modes
- No Tracking: Zero analytics, zero cookies, zero data collection
- Modern & Minimal: Clean, responsive interface that works on all devices
Open the deployed app and start writing - everything works in your browser!
First time setup:
-
Install Node.js (if not already installed):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.zshrc nvm install --lts
-
Clone and setup:
git clone https://github.com/ngroegli/linknote.git cd linknote npm install -
Start development:
npm run dev
-
Build for production:
npm run build
📘 See docs/QUICKSTART.md for detailed setup instructions
After running npm run build, deploy the dist/ folder to:
- GitHub Pages: Free and easy
- Netlify: Drag and drop deployment
- Vercel: Git integration
- Any web server: Just serve the static files
The production build includes all dependencies - no external CDN requests needed!
- Type or paste your Markdown in the left editor pane
- Watch the live preview appear on the right
- Your content is automatically encoded into the URL
There is no "Save" button—your document IS the URL!
To save your work:
- Click the "📋 Copy URL" button
- Bookmark the URL, or
- Share it with others, or
- Paste it in your notes
When you or anyone else opens that URL, the document will be restored exactly as you left it.
- Write your content
- Copy the URL (it contains your encoded document)
- Share the URL via email, chat, social media, etc.
- Anyone with the URL can view and edit (creating their own URL)
Click the 🌓 button in the header to switch between light and dark modes. Your preference is saved locally.
Click the 🗑️ Clear button to start fresh. You'll be asked to confirm first.
- Browser Limit: Most browsers support URLs up to ~2,000 characters (some up to ~65,000)
- Warning: LinkNote will warn you when your URL exceeds 2,000 characters
- Practical Limit: Works best for short to medium-length documents
- Workaround: For longer documents, consider splitting into multiple notes
✅ Perfect for:
- Quick notes and snippets
- README files
- Documentation snippets
- Meeting notes
- Code examples
- Blog post drafts
❌ Not ideal for:
- Very long documents (10,000+ words)
- Documents with many large images (images must be linked, not embedded)
- Binary file storage
- ❌ No servers
- ❌ No databases
- ❌ No cookies
- ❌ No localStorage (except theme preference)
- ❌ No analytics
- ❌ No tracking
- ❌ No external API calls (except for CDN libraries)
- Complete Privacy: Your content never leaves your browser
- No Account Needed: No sign-up, no login, no password
- Your Data, Your Control: You control the URL, you control the content
- Cannot Be Censored: No one can delete or modify your documents except you
- No Data Breaches: There's no database to breach
✅ LinkNote protects against XSS attacks
- DOMPurify sanitizes all HTML before rendering
- Malicious scripts are automatically removed
- Event handlers and dangerous attributes are blocked
- Only safe Markdown/HTML elements are allowed
- See docs/SECURITY.md for detailed security information
- Anyone with your URL can read your document
- Don't put sensitive information (passwords, API keys, etc.) in LinkNote
- URLs might appear in browser history, server logs, or referrer headers
- Use only for content you're comfortable sharing via URL
- HTML5: Semantic markup
- CSS3: Modern styling with CSS variables for theming
- Vanilla JavaScript: No framework dependencies (ES modules)
- Vite: Fast dev server and production bundler
- Node.js & npm: Dependency management
✅ Clean Repository
- Dependencies installed via npm (not committed to git)
- Production build includes all dependencies (no external CDN)
- Modern ES module imports
To keep LinkNote:
- Fast and lightweight
- Easy to understand and modify
- Minimal dependencies
- Running forever without maintenance
linknote/
├── LICENSE # GNU GPL-3.0 license
├── README.md # This file (main documentation)
├── package.json # npm dependencies and scripts
├── package-lock.json # Locked dependency versions
├── vite.config.js # Vite build configuration
├── .gitignore # Git ignore
├── robots.txt # Web crawler blocking (67 lines)
├── ai.txt # AI crawler blocking (40 lines)
├── llms.txt # LLM crawler blocking (15 lines)
├── .well-known/ # Well-known URIs
│ └── security.txt # Security contact information
├── .github/ # GitHub Actions workflows
│ └── workflows/
│ ├── ci.yml # Continuous integration
│ ├── security.yml # Security scanning
│ └── release.yml # Release automation
├── src/ # Application source
│ ├── index.html # Main HTML file (uses ES modules)
│ ├── styles.css # All styling and themes
│ ├── app.js # Application logic (imports npm packages)
│ └── assets/ # Brand assets (logos, icons)
│ ├── favicon.svg # App icon
│ ├── logo.svg # Brand logo
│ └── logo-dark.svg # Dark theme logo
├── dist/ # Production build output (created by npm run build)
├── node_modules/ # npm dependencies (NOT committed to git)
└── docs/ # Documentation
├── ARCHITECTURE.md # Technical architecture
├── BRAND_ALIGNMENT.md # Brand guideline implementation
├── BRANDING_GUIDELINE.md # Personal brand guidelines
├── DEPENDENCIES.md # Dependency management comparison
├── QUICKSTART.md # Quick start & developer setup
├── SECURITY.md # Security documentation
└── drawings/ # Architecture diagrams (D2 + PNG)
├── data-flow.d2
├── data-flow.png
├── security-architecture.d2
├── security-architecture.png
└── ... # Additional diagrams
The application is organized into 5 main modules:
-
URLCodec - URL encoding/decoding
encode()- Text to URL-safe Base64decode()- Base64 to textgetFromURL()- Read from URL fragmentsetToURL()- Write to URL fragment
-
MarkdownEngine - Markdown parsing
initialize()- Configure marked.jsparse()- Convert Markdown to HTML
-
EditorManager - Editor state management
initialize()- Set up editorhandleInput()- Process user input (debounced)updatePreview()- Update preview paneupdateURL()- Encode content to URLloadFromURL()- Restore from URL
-
ThemeManager - Theme management
initialize()- Load saved themetoggle()- Switch themesapplyTheme()- Apply to document
-
UIController - UI interactions
initialize()- Set up event listenerscopyURL()- Copy URL to clipboardconfirmClear()- Clear with confirmationshowToast()- Show notifications
User types → handleInput() → updatePreview() (immediate)
→ updateURL() (debounced 500ms)
→ URLCodec.encode()
→ history.replaceState()
For detailed technical documentation, see docs/ARCHITECTURE.md.
Contributions are welcome! We value privacy-first design, simplicity, and accessibility.
-
Fork & Clone
git clone https://github.com/YOUR_USERNAME/linknote.git cd linknote npm install -
Create a Branch
git checkout -b feature/your-feature-name
-
Make Changes
- Edit files in
src/ - Run
npm run devfor live preview - Follow existing code style
- Test thoroughly
- Edit files in
-
Commit & Push
git add . git commit -m "Add: your feature description" git push origin feature/your-feature-name
-
Open Pull Request
- Go to GitHub and create a PR
- Describe your changes clearly
- Link any related issues
- JavaScript: ES6+, 4-space indent, double quotes, semicolons
- CSS: CSS variables for theming, hyphenated class names
- Comments: JSDoc for functions, section comments for CSS
- Keep it simple: Maintain the minimalist philosophy
✅ Privacy First - No servers, no tracking ✅ Simplicity - Keep codebase small and understandable ✅ Minimal Dependencies - Only essential external libs ✅ Accessibility - Work for everyone, all devices ✅ Offline First - Work without internet after load
- Compression for longer documents
- Export/import Markdown files
- More theme options
- Keyboard shortcuts
- Syntax highlighting in editor
- Word count / read time
- Multiple notes management
- Search within note
-
docs/QUICKSTART.md - Quick start guide
- 2-minute getting started
- Tips and tricks
- Troubleshooting
- Platform-specific notes
- Use cases
-
docs/EXAMPLES.md - Example documents
- Meeting notes template
- Technical documentation template
- Project README template
- Study notes template
- Blog post template
-
docs/ARCHITECTURE.md - Technical documentation
- System architecture
- Module descriptions
- Data flow diagrams
- URL encoding scheme
- Browser compatibility
- Security considerations
- Future enhancements
Core Technologies:
- HTML5 - Semantic markup
- CSS3 - Modern styling with CSS variables
- JavaScript ES6+ - Vanilla JS, no frameworks
External Dependencies:
- marked.js (v11.1.1) - Markdown parser (loaded from CDN)
Browser APIs Used:
- URL Fragment (
window.location.hash) - History API (
history.replaceState) - Clipboard API (
navigator.clipboard) - TextEncoder/TextDecoder (UTF-8)
- localStorage (theme only)
- Media Queries (responsive & theme)
GNU General Public License v3.0 - see LICENSE file for details.
This is free software: you are free to change and redistribute it under the terms of the GPL-3.0 license.
localStorage is device-specific. Using the URL makes your documents instantly portable and shareable.
Consider:
- Using a URL shortener (though this adds a server dependency)
- Splitting your document into multiple notes
- Linking to external images instead of embedding them
Absolutely! Just serve the src folder from any web server. No special configuration needed.
Yes, after the initial page load. The only external dependency is the marked.js library loaded from CDN.
Yes! Download marked.js (or another library) and update the script tag in index.html.
- marked.js for Markdown parsing
- DOMPurify for HTML sanitization
- Built with the assistance of GitHub Copilot
- Inspired by the desire for truly private, serverless note-taking
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with ❤️ for privacy-conscious users
No servers. No tracking. Just you and your Markdown.