Skip to content

DumbWareio/DumbPad

Repository files navigation

DumbPad

A stupid simple, no auth (unless you want it!), modern notepad application with auto-save functionality and dark mode support.

GitHub package.json version Docker Image Version Docker Pulls License GitHub Actions Workflow Status

dumbpad

Table of Contents

Features

  • Simple, clean interface
  • Auto-saving
  • Dark mode support
  • Responsive design
  • Docker support
  • Optional PIN protection (4-10 digits)
  • File-based storage
  • Data persistence across updates
  • Markdown Formatting with enhanced support
    • GitHub-style alert blocks (Note, Tip, Important, Warning, Caution)
    • Extended table formatting
    • Auto-expand collapsible details in print (configurable)
    • Code syntax highlighting in fenced codeblocks
  • Direct notepad linking with URL parameters
  • Copy shareable notepad links
  • Browser navigation support (back/forward buttons)
  • Fuzzy Search (by filename and file contents)
  • PWA Support with automatic cache updates

Quick Start

Prerequisites

  • Docker (recommended)
  • Node.js >=20.0.0 (for local development)

Option 1: Docker (For Dummies)

# Pull and run with one command
docker run -p 3000:3000 \
  -v ./data:/app/data \
  dumbwareio/dumbpad:latest
  1. Go to http://localhost:3000
  2. Start typing - Your notes auto-save
  3. Marvel at how dumb easy this was

⚠️ Note: If the container crashes with permission errors, see Docker Permissions section below.

Option 2: Docker Compose (For Dummies who like customizing)

Create a docker-compose.yml file:

services:
  dumbpad:
    image: dumbwareio/dumbpad:latest
    container_name: dumbpad
    restart: unless-stopped
    ports:
      - ${DUMBPAD_PORT:-3000}:3000
    volumes:
      - ${DUMBPAD_DATA_PATH:-./data}:/app/data
    environment:
      # The title shown in the web interface
      SITE_TITLE: ${DUMBPAD_SITE_TITLE:-DumbPad}
      # Optional PIN protection (leave empty to disable)
      DUMBPAD_PIN: ${DUMBPAD_PIN:-}
      # The base URL for the application
      BASE_URL: ${DUMBPAD_BASE_URL:-http://localhost:3000} # Use ALLOWED_ORIGINS below to restrict cors to specific origins
      # (OPTIONAL)
      # Usage: Comma-separated list of urls: http://localhost:port,http://internalip:port,https://base.proxy.tld,https://authprovider.domain.tld
      # ALLOWED_ORIGINS: ${DUMBPAD_ALLOWED_ORIGINS:-http://localhost:3000} # Comment out to allow all origins (*)
      # LOCKOUT_TIME: ${DUMBPAD_LOCK_TIME:-15} # Customize pin lockout time (if empty, defaults to 15 in minutes)
      # MAX_ATTEMPTS: ${DUMBPAD_MAX_ATTEMPTS:-5} # Customize pin max attempts (if empty, defaults to 5)
      # COOKIE_MAX_AGE: ${DUMBPAD_COOKIE_MAX_AGE:-24} # Customize maximum age of cookies primarily used for pin verification (default 24) in hours
      # PAGE_HISTORY_COOKIE_AGE: ${DUMBPAD_PAGE_HISTORY_COOKIE_AGE:-365} # Customize age of cookie to show the last notepad opened (default 365 | max 400) in days - shows default notepad on load if expired
      
      # MARKDOWN CODE SYNTAX HIGHLIGHTING (only use below if you want to restrict to specific languages):
      # By default, DumbPad includes support for all ~180 languages supported by highlight.js.
      # view entire list and usage in /docs/MARKDOWN_SYNTAX_HIGHLIGHTING_USAGE.md
      # HIGHLIGHT_LANGUAGES=c,csharp,css,dockerfile,go,html,java,javascript,json,kotlin,markdown,perl,php,python,ruby,sql,swift,typescript,xml,yaml

Then run:

docker compose up -d
  1. Go to http://localhost:3000
  2. Start typing - Your notes auto-save
  3. Rejoice in the glory of your dumb notes

⚠️ Note: If the container crashes with permission errors, see Docker Permissions section below.

Option 3: Running Locally (For Developers)

  1. Install dependencies:
npm install
  1. Set environment variables in .env or cp .env.example .env:
PORT=3000                  # Port to run the server on
DUMBPAD_PIN=1234          # Optional PIN protection
SITE_TITLE=DumbPad        # Custom site title
BASE_URL=http://localhost:3000  # Base URL for the application
  1. Start the server:
npm start

Windows Users

If you're using Windows PowerShell with Docker, use this format for paths:

docker run -p 3000:3000 -v "${PWD}\data:/app/data" dumbwareio/dumbpad:latest

Upgrading from Previous Versions

⚠️ Important: Docker Permission Issues (New Installations & Upgrades)

As of PR #76, DumbPad now runs as a non-root user (UID 1000) inside the Docker container for improved security. This can cause permission issues in two scenarios:

  1. Upgrading from a previous version - Existing data directory may have incorrect permissions, causing notepads to appear blank (Issue #74)
  2. Fresh installation - Docker may create the data directory with host user permissions that don't match UID 1000, causing container restart loops with EACCES: permission denied errors (Issue #79)

Symptoms

  • Fresh installations: Container crashes on startup with Error: EACCES: permission denied, open '/app/data/notepads.json'
  • Upgrades: Previously saved notepads appear blank or empty

Solution

Option 1: Fix Existing Installation

Set the ownership of your data directory to match the container's non-root user (UID 1000):

Linux/macOS:

# Stop the container first
docker stop dumbpad

# Fix permissions (replace /path/to/your/data with your actual path)
sudo chown -R 1000:1000 /path/to/your/data

Example for common setups:

# If using the default ./data directory
sudo chown -R 1000:1000 ./data

# If using a custom path like /opt/docker/dumbpad
sudo chown -R 1000:1000 /opt/docker/dumbpad

# For Unraid users
sudo chown -R 1000:1000 /mnt/user/appdata/dumbpad

Windows (Docker Desktop):

# Windows users typically don't need to change permissions
# Docker Desktop handles volume permissions automatically
Option 2: Preventive Setup (Fresh Installations)

For new installations, create the data directory with correct permissions before starting the container:

Linux/macOS:

# Create data directory
mkdir -p ./data

# Set correct ownership
sudo chown -R 1000:1000 ./data

# Now start the container
docker compose up -d

Windows (Docker Desktop):

# No special setup needed - Docker Desktop handles permissions automatically
docker compose up -d

Verifying the Fix

After updating permissions, verify everything is working:

  1. Start/Restart the container:

    docker restart dumbpad
    # or if starting fresh
    docker compose up -d
  2. Check container logs (should start without errors):

    docker logs dumbpad
  3. Verify file ownership inside container:

    docker exec dumbpad ls -la /app/data

    You should see files owned by node or UID 1000

  4. Test the application by accessing http://localhost:3000 and creating a test notepad

Why This Change?

Running containers as non-root users is a security best practice that:

  • Limits potential damage from container escapes
  • Reduces attack surface
  • Aligns with security compliance standards

Features

  • πŸ“ Auto-saving notes
  • πŸŒ“ Dark/Light mode support
  • πŸ”’ Optional PIN protection
  • πŸ“± Mobile-friendly interface / PWA Support
  • πŸ—‚οΈ Multiple notepads
  • πŸ“„ Enhanced Markdown Formatting with GitHub-style alerts and extended tables
  • πŸ”— Direct notepad linking with shareable URLs
  • 🧭 Browser navigation support (back/forward buttons)
  • ⬇️ Download notes as text or markdown files
  • πŸ–¨οΈ Print functionality with auto-expanded collapsible sections
  • πŸ” Fuzzy Search by name or contents
  • πŸ”„ Real-time saving
  • πŸ’½ Add .txt files into data folder to import (requires page refresh)
  • ⚑ Zero dependencies on client-side
  • πŸ›‘οΈ Built-in security features
  • 🎨 Clean, modern interface
  • πŸ“¦ Docker support with easy configuration
  • 🌐 Optional CORS support
  • βš™οΈ Customizable settings
  • πŸ”„ Automatic cache updates and version management

Configuration

Environment Variables

Variable Description Default Required
PORT Server port 3000 No
BASE_URL Base URL for the application http://localhost:PORT Yes
DUMBPAD_PIN PIN protection (4-10 digits) None No
SITE_TITLE Site title displayed in header DumbPad No
NODE_ENV Node environment mode (development or production) production No
ALLOWED_ORIGINS Allowed CORS origins (* for all or comma-separated list) * No
LOCKOUT_TIME Lockout time after max PIN attempts (in minutes) 15 No
MAX_ATTEMPTS Maximum PIN entry attempts before lockout 5 No
COOKIE_MAX_AGE Maximum age of authentication cookies (in hours) 24 No
PAGE_HISTORY_COOKIE_AGE Age of cookie storing last opened notepad (in days, max 400) 365 No
TRUST_PROXY Enable proxy trust for X-Forwarded-For headers false No
TRUSTED_PROXY_IPS Comma-separated list of trusted proxy IPs None No
HIGHLIGHT_LANGUAGES Comma-separated list of code syntax languages to restrict to all if not supplied No

Proxy Trust Configuration

When deploying DumbPad behind a reverse proxy (nginx, Apache, Cloudflare, etc.), you may need to configure proxy trust to correctly identify client IP addresses for rate-limiting and authentication.

⚠️ Security Warning

By default, TRUST_PROXY is false (most secure). Only enable proxy trust if you're deploying behind a trusted reverse proxy. Incorrect configuration can allow attackers to bypass rate-limiting and authentication by spoofing the X-Forwarded-For header.

When to Enable Proxy Trust

Enable TRUST_PROXY=true only if:

  1. You're deploying behind a reverse proxy (nginx, Cloudflare, etc.)
  2. The proxy adds X-Forwarded-For headers
  3. You can explicitly list all trusted proxy IPs in TRUSTED_PROXY_IPS

Configuration Examples

Example 1: Behind nginx on the same host

TRUST_PROXY=true
TRUSTED_PROXY_IPS=127.0.0.1

Example 2: Docker with nginx reverse proxy

TRUST_PROXY=true
TRUSTED_PROXY_IPS=172.17.0.1  # Docker default gateway IP

Example 3: Multiple proxies (load balancer + nginx)

TRUST_PROXY=true
TRUSTED_PROXY_IPS=10.0.0.1,10.0.0.2  # IPs of both proxies

Example 4: Cloudflare (using Cloudflare IPs)

TRUST_PROXY=true
# List all Cloudflare IP ranges that connect to your origin
# See: https://www.cloudflare.com/ips/
TRUSTED_PROXY_IPS=173.245.48.0,103.21.244.0,103.22.200.0,...

Finding Your Proxy IP

To find your proxy's IP address:

Docker:

docker network inspect bridge | grep Gateway

Check incoming connections:

# While DumbPad is running, check who's connecting
netstat -tn | grep :3000

How It Works

  • When TRUST_PROXY=false (default): Always uses the direct socket IP address, ignoring X-Forwarded-For headers
  • When TRUST_PROXY=true with TRUSTED_PROXY_IPS: Validates the immediate connecting IP against the trusted list before trusting X-Forwarded-For
  • When TRUST_PROXY=true without TRUSTED_PROXY_IPS: Trusts X-Forwarded-For from any source (⚠️ not recommended for production)

Security

Features

  • Variable-length PIN support (4-10 digits)
  • Constant-time PIN comparison
  • Brute force protection:
    • 5 attempts maximum
    • 15-minute lockout after failed attempts
    • IP-based tracking with spoofing protection
    • Validated client IP extraction (ignores untrusted X-Forwarded-For by default)
  • Secure cookie handling
  • No client-side PIN storage
  • Rate limiting
  • Collaborative editing
  • CORS support for origin restrictions (optional)
  • Configurable proxy trust with IP validation

User Settings

Access settings via the gear icon (βš™οΈ) in the header or use keyboard shortcut:

  • Windows/Linux: Ctrl+Alt+,
  • macOS: Cmd+Ctrl+,

Available Settings

Setting Description Default Options
Auto-save Status Interval Time interval for auto-save notifications (0 = disabled) 1000ms Any number (milliseconds)
Remote Connection Messages Show notifications when users connect/disconnect Enabled Enabled/Disabled
Disable Print Expansion Prevent auto-expanding collapsed sections when printing Disabled Enabled/Disabled
Default Markdown Preview Default view when loading DumbPad (Client-based) Editor Editor, Split, Full

Notepad Management

  • Unique Names: Notepad names are automatically made unique by the server. If you try to create or rename a notepad with an existing name, the server will append a suffix (e.g., "Note-1", "Note-2")
  • Name Validation: The server handles all name validation and uniqueness checks. The frontend will display a notification if your requested name was modified
  • Auto-save: Changes are automatically saved every 300ms after you stop typing, with periodic saves every 2 seconds
  • Persistence: All settings are stored in your browser's local storage and persist across sessions

Technical Details

Stack

  • Backend: Node.js (>=20.0.0) with Express
  • Frontend: Vanilla JavaScript (ES6+) with enhanced markdown support
  • Container: Docker with multi-stage builds
  • Security: Express security middleware
  • Storage: File-based with auto-save
  • Theme: Dynamic dark/light mode with system preference support
  • PWA: Service Worker with automatic cache updates and version management
  • Markdown: Enhanced with alert blocks, extended tables, and collapsible content
  • Real-time: WebSocket-based collaboration and live updates
  • Navigation: SPA-style routing with shareable URLs and browser history support
  • Print: Advanced print preview with auto-expanding collapsible content and theme preservation

Dependencies

  • express: Web framework
  • cors: Cross-origin resource sharing
  • dotenv: Environment configuration
  • cookie-parser: Cookie handling
  • express-rate-limit: Rate limiting
  • marked: Markdown formatting
  • marked-alert: GitHub-style alert blocks for markdown
  • marked-extended-tables: Enhanced table support for markdown
  • marked-highlight: Syntax highlighting for code blocks in markdown
  • @highlightjs/cdn-assets: Highlight.js assets for code syntax highlighting
  • fuse.js: Fuzzy searching
  • ws: WebSocket support for real-time collaboration

The data directory contains:

  • notepads.json: List of all notepads
  • Individual .txt files for each notepad's content
  • Drop in .txt files to import notes (requires page refresh)

⚠️ Important: Never delete the data directory when updating! This is where all your notes are stored.

Usage

Basic Operations

  • Start typing: Notes auto-save as you type (every 300ms after stopping, with periodic saves every 2 seconds)
  • Theme toggle: Switch between light/dark mode with the toggle button
  • Force save: Ctrl+S (or Cmd+S on Mac)
  • Search: Ctrl+K (or Cmd+K) to open fuzzy search across all notepads
  • Copy link: Click the link button (πŸ”—) to copy the current notepad's shareable URL
  • Settings: Click the gear icon (βš™οΈ) or use Ctrl+Alt+, (or Cmd+Ctrl+,)

Notepad Management

  • Create: Click the + button or Ctrl+Alt+N (or Cmd+Ctrl+N)
  • Rename: Click rename button or Ctrl+Alt+R (or Cmd+Ctrl+R)
  • Delete: Click delete button or Ctrl+Alt+X (or Cmd+Ctrl+X)
  • Navigate: Use dropdown, arrow keys (Ctrl+Alt+↑/↓), or browser back/forward buttons
  • Download: Click download button or Ctrl+Alt+A (or Cmd+Ctrl+A) for .txt/.md export
  • Print: Ctrl+P (or Cmd+P) with enhanced formatting and auto-expanded collapsible sections

Preview Modes

Swap between different modes using the 3-way markdown toggle button: (Editor, Split, Full)

Editor Split Preview Full Preview
editor-preview split-preview full-preview

You can also set your default preview mode in settings.

image

Markdown Formatting

DumbPad now supports enhanced markdown features:

GitHub-Style Alert Blocks

> [!NOTE]
> This is a note alert block

> [!TIP]
> This is a tip alert block

> [!IMPORTANT]
> This is an important alert block

> [!WARNING]
> This is a warning alert block

> [!CAUTION]
> This is a caution alert block

Extended Table Support

  • Advanced table formatting with alignment
  • Enhanced styling for better readability

Collapsible Details

<details>
<summary>Click to expand</summary>
Content that will be automatically expanded when printing
</details>

Code Syntax Highlighting

  • Uses highlight.js for syntax highlighting using fenced code blocks
  • Defaults to all supported languages (configured via HIGHLIGHT_LANGUAGES environment variable if you would like to restrict to specific languages)
  • Read more and view examples in /docs/MARKDOWN_SYNTAX_HIGHLIGHTING_USAGE.md
```javascript
console.log("Hello, world!");
```

URL Parameters

  • Direct notepad linking: ?id=notepadname - Opens a specific notepad by name (case-insensitive)
  • Browser navigation: Use back/forward buttons to navigate between notepads
  • Shareable URLs: Copy links to share specific notepads with others

Technical Details

  • Backend: Node.js with Express
  • Frontend: Vanilla JavaScript
  • Storage: File-based storage in data directory
  • Styling: Modern CSS with CSS variables for theming
  • Security: Constant-time PIN comparison, brute force protection

Links

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes using conventional commits
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

See Development Guide for local setup and guidelines.


Made with ❀️ by DumbWare.io

🌐 Check Us Out

Support the Project

Buy Me A Coffee

Future Features

  • File attachments
  • Markdown code syntax highlighting

Got an idea? Open an issue or submit a PR


About

A Dumb Pad with collaborative editing, fuzzy search, & markdown preview functionality

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 7