Sign inSign up

xhenxhe/dailynotes

By xhenxhe

•Updated 7 months ago

Image
0

9.5K

xhenxhe/dailynotes repository overview

⁠DailyNotes: Daily tasks and notes in Markdown


⁠In Loving Memory of Joe Ipson⁠

This project is dedicated to Joe Ipson⁠, the original creator of DailyNotes, who passed away in the summer of 2025 after a courageous battle with cancer.

Joe was a kindred spirit who believed in the simple power of writing things down. He built DailyNotes to bring the mindful experience of a physical planner into the digital world. His vision was to create something personal, self-hosted, and beautifully simple.

This project continues in his memory. Every commit, every feature, every bug fix is a small tribute to a dear friend whose spirit lives on in the code he wrote and the ideas he shared.

Rest easy, Joe. We'll take it from here.


⁠About

The idea for this app came from using my Hobonichi Techo planner every morning to write down what I needed to accomplish that day & using it for scratching down random thoughts and notes as the day went on. The closest thing I've seen to an app for replacing this system is Noteplan, but I don't use a Mac or an iOS device, and it's not self-hostable, so I decided to write my own.

To check your current version, open Settings in the app and look in the About section.

Since I had the need for keeping track of to-dos throughout the day, regular Markdown didn't work for me since it doesn't natively support tasks. So as an alternative I'm using Github Flavored Markdown (GFM). I really wanted it to feel like an actual text editor and not just a textbox, so I decided to use CodeMirror to handle all the input. Fira Code is used to provide font ligatures. Some other nice features include code highlighting, text/code folding, and a task list where you can toggle the status of any task from any date or note.

⁠Features

Joe had a vision for what DailyNotes could become before calling it a 1.0 release. I've done my best to interpret and implement those features, along with feature requests from GitHub issues that Joe was considering. Here's what makes DailyNotes a powerful daily planning tool:

⁠Core Experience
  • GitHub Flavored Markdown — Full GFM support with task lists (- [ ] / - [x]), tables, code blocks, and more
  • CodeMirror Editor — A real text editor experience with syntax highlighting, code folding, and keyboard shortcuts
  • Fira Code Font — Beautiful font ligatures for a polished writing experience
  • Auto-save — Never lose your work with optional automatic saving
  • Data Encryption — All notes encrypted at rest with AES encryption
  • Powerful Search⁠ — Syntax-based search with tag:, project:, and full-text queries
  • Nested Tags⁠ — Hierarchical tag organization (e.g., work/meetings, home/family)
  • Kanban Board⁠ — Visual task management with drag-and-drop columns
  • Task List — View and toggle tasks within each note with one-click status updates
⁠Preview & Visualization
  • HTML Preview⁠ — Live markdown preview with Cmd+K V (side-by-side) or Shift+Cmd+V (full screen)
  • Mermaid Diagrams⁠ — Create flowcharts, sequence diagrams, ERDs, and more directly in your notes
  • Themes⁠ — Light, Dark, and System themes to match your environment
⁠Calendar Integration
  • Calendar Feed (ICS)⁠ — Subscribe to your notes in Google Calendar, Apple Calendar, or any ICS-compatible app
  • External Calendar Support — Display events from external ICS feeds alongside your daily notes
⁠Self-Hosted & Private
  • Self-hosted — Your data stays on your server, under your control
  • Docker Ready — Easy deployment with Docker and Docker Compose
  • Multi-user Support — Multiple users with separate, encrypted data
  • No Vendor Lock-in — Export all your notes as markdown files anytime
⁠Account Security
  • Password Recovery⁠ — Reset your password via email if forgotten
  • Magic Link Sign-in⁠ — Sign in with a secure email link instead of a password
  • Email Management — Add or update your email in Settings to enable these features

DailyNotes supports password recovery and passwordless sign-in via email. These features require SMTP configuration (see Environment Variables⁠).

⁠Setting Up Your Email
  1. Click the menu icon (⋮) in the header
  2. Select Settings
  3. In the Account section, enter your email address
  4. Click Add Email

Once configured, you can use password recovery and magic link sign-in.

⁠Forgot Password

If you forget your password:

  1. Go to the login page
  2. Click Forgot password?
  3. Enter your email address
  4. Check your email for a reset link (valid for 1 hour)
  5. Click the link and enter your new password

Sign in without entering your password:

  1. Go to the login page
  2. Click Sign in with email
  3. Enter your email address
  4. Check your email for a sign-in link (valid for 15 minutes)
  5. Click the link to automatically sign in
⁠Security Features
FeatureDescription
Secure tokensCryptographically random, SHA-256 hashed
Rate limiting3 requests per email per hour
Short expirationReset: 1 hour, Magic link: 15 minutes
Single-use tokensEach token can only be used once
Email enumeration preventionSame response whether email exists or not
Encrypted email storageEmail addresses encrypted at rest (AES)
⁠SMTP Configuration Examples

Gmail (with App Password):

SMTP_HOST: smtp.gmail.com
SMTP_PORT: 587
SMTP_USER: [email protected]
SMTP_PASSWORD: your-app-password # Generate at myaccount.google.com/apppasswords
SMTP_FROM_NAME: DailyNotes
APP_URL: https://your-dailynotes-instance.com

Mailgun:

SMTP_HOST: smtp.mailgun.org
SMTP_PORT: 587
SMTP_USER: [email protected]
SMTP_PASSWORD: your-mailgun-password
SMTP_FROM_EMAIL: [email protected]
APP_URL: https://your-dailynotes-instance.com

Amazon SES:

SMTP_HOST: email-smtp.us-east-1.amazonaws.com
SMTP_PORT: 587
SMTP_USER: your-ses-smtp-username
SMTP_PASSWORD: your-ses-smtp-password
SMTP_FROM_EMAIL: [email protected]
APP_URL: https://your-dailynotes-instance.com

Important Notes:

  • Gmail requires an App Password⁠, not your regular password
  • The APP_URL must match the URL users access DailyNotes from (for email links to work)
  • If SMTP is not configured, password recovery and magic link features are automatically disabled
  • Users can still sign in with username/password even without email configured

⁠Themes

DailyNotes supports Light, Dark, and System themes to match your preferred working environment.

⁠Theme Options
ThemeDescription
🌙 DarkDefault dark interface, optimized for low-light environments
☀️ LightClean, bright interface with light backgrounds
💻 SystemAutomatically follows your operating system's color scheme setting
⁠How to Change Themes
  1. Click the menu icon (⋮) in the header
  2. Select Settings
  3. In the Appearance section, click your preferred theme
  4. The theme changes instantly and is saved for future sessions

The System option automatically switches between light and dark themes based on your OS settings (e.g., macOS Dark Mode, Windows Dark Theme). This is perfect if you prefer dark mode at night and light mode during the day.

⁠Mermaid Diagrams

DailyNotes supports Mermaid⁠ diagrams in the markdown preview, allowing you to create flowcharts, sequence diagrams, class diagrams, and more directly in your notes.

⁠Creating Diagrams

Use a fenced code block with mermaid as the language:

```mermaid
graph TD
    A[Start] --> B{Decision}
    B -->|Yes| C[Do something]
    B -->|No| D[Do something else]
    C --> E[End]
    D --> E
```
⁠Viewing Diagrams

Diagrams are rendered in the HTML preview:

  • Side-by-side: Press Cmd+K V (Mac) or Ctrl+K V (Windows/Linux)
  • Preview only: Press Shift+Cmd+V (Mac) or Shift+Ctrl+V (Windows/Linux)
⁠Supported Diagram Types

Mermaid supports many diagram types. Here are some examples:

Diagram TypeUse CaseExample Syntax
FlowchartProcess flows, decisionsgraph TD or graph LR
SequenceAPI calls, interactionssequenceDiagram
ClassObject relationshipsclassDiagram
StateState machinesstateDiagram-v2
Entity RelationshipDatabase schemaserDiagram
GanttProject timelinesgantt
PieData distributionpie
Git GraphBranch visualizationgitGraph
⁠Theme Support

Diagrams automatically adapt to your app theme:

  • Dark theme: Diagrams render with dark-friendly colors
  • Light theme: Diagrams render with light-friendly colors
  • Switching themes re-renders diagrams with the appropriate color scheme
⁠Error Handling

If a diagram has syntax errors, DailyNotes displays a helpful error message instead of breaking the preview. This makes it easy to debug and fix diagram issues.

⁠Learn More

For full syntax documentation and examples, visit the Mermaid documentation⁠.

⁠Calendar feed (ICS)

  • Generate or rotate a private read-only ICS URL with GET/POST /api/calendar_token (requires auth).
  • Subscribe in Google Calendar via Settings -> Add calendar -> From URL using /api/calendar.ics?token=<your_token>.
  • Each daily note becomes an all-day event; the feed updates when notes change (Google polls periodically).
  • Rotate the token to immediately revoke previous subscriptions or disable sharing with DELETE /api/calendar_token.
  • You can now subscribe to external ICS feeds (e.g., Google private links) in Settings; DailyNotes shows those events on the matching day.

DailyNotes features a powerful syntax-based search that lets you quickly find notes using text queries.

⁠Search Syntax
SyntaxDescriptionExample
tag:valueFilter by tagtag:meeting
project:valueFilter by projectproject:work
t:valueShorthand for tagt:1on1
p:valueShorthand for projectp:DN
tag:"multi word"Quoted values for spacestag:"code review"
Plain textSearch note contentbudget report
⁠Example Searches
QueryWhat it finds
budgetAll notes containing "budget"
tag:meetingAll notes tagged "meeting"
project:work tag:Q4Notes in "work" project with "Q4" tag
tag:1on1 tag:feedbackNotes with both tags (AND)
project:DN project:personalNotes in either project (OR)
tag:meeting notes agendaTagged "meeting" containing "notes" AND "agenda"
⁠Search Logic
  • Multiple tags = AND (note must have all specified tags)
  • Multiple projects = OR (note can be in any specified project)
  • Multiple text terms = AND (note must contain all words)
⁠Features
  • Autocomplete: Type tag: or project: to see suggestions from your existing tags/projects
  • Keyboard navigation: Use arrow keys to select, Tab/Enter to confirm
  • Result highlighting: Matching text is highlighted in search results with context snippets
  • Syntax help: Click the ? button for a quick reference

⁠Nested Tags

DailyNotes supports hierarchical tag organization using / as a delimiter. This lets you create tag hierarchies like work/meetings, home/family, or projects/dailynotes/frontend.

⁠Creating Nested Tags

Use the / character in your frontmatter to create nested tags:

---
title: Weekly Team Sync
tags: work/meetings, work/1on1, home/family
---
⁠Sidebar Display

Nested tags appear as a collapsible tree in the sidebar:

DisplayDescription
▶ workCollapsed parent tag (click arrow to expand)
▼ workExpanded parent showing children below
meetingsChild tag indented under parent
1on1Flat tag (no /) displayed inline at top
  • Flat tags (without /) are displayed inline at the top, wrapping as needed
  • Parent tags show a collapsible chevron (▶/▼)
  • Child tags are displayed inline under their parent when expanded
  • Expand/collapse state is saved and persists across page refreshes
⁠Search Behavior

Nested tags support hierarchical search - searching for a parent tag matches all its children:

Search QueryMatches
tag:workNotes with work, work/meetings, work/1on1
tag:work/meetingsOnly notes with exactly work/meetings
tag:homeNotes with home, home/family, home/tech

This makes it easy to search broadly (tag:work for all work-related notes) or specifically (tag:work/meetings for just meeting notes).

⁠Examples
Tags in FrontmatterSidebar Display
tags: meeting, 1on1, reviewmeeting 1on1 review (inline)
tags: work/meetings, work/reviews▼ work → meetings reviews
tags: home/tech, home/family, work▼ home → family tech, work
⁠Tips
  • Existing tags are unchanged: Tags without / continue to work exactly as before
  • Autocomplete works: Type tag:work/ to see suggestions for nested tags
  • Mix and match: You can use both flat and nested tags in the same note
  • Deep nesting: Multiple levels work too: projects/dailynotes/frontend/components

⁠Kanban Board

DailyNotes includes an optional Kanban board view for organizing tasks with drag-and-drop support.

⁠Enabling Kanban
  1. Click the menu icon (⋮) in the header
  2. Select Settings
  3. Find the Kanban section
  4. Toggle Enable Kanban board

When enabled, the Tasks icon in the header changes to a columns icon. Click it to open the Kanban modal.

⁠Task Syntax

Use the >>column syntax at the end of any task to assign it to a specific column:

Task SyntaxColumn Assignment
- [ ] Plain taskDefaults to "todo"
- [x] Completed taskDefaults to "done"
- [ ] In progress >>doingExplicit "doing" column
- [x] Done but in review >>reviewStays in "review" (explicit wins)

Column names support letters, numbers, and hyphens: >>in-progress, >>stage-2, >>Q4

⁠Default Columns
SettingDefault Value
Default columnstodo, done
Configurable inSettings → Kanban

Add, remove, or reorder columns in the Settings panel.

⁠Per-Note Column Override

Override columns for a specific note using YAML frontmatter:

---
title: Sprint Planning
kanban:
  - backlog
  - in-progress
  - review
  - done
---

- [ ] Design mockups >>backlog
- [ ] Implement API >>in-progress
- [ ] Write tests >>review
⁠Auto-Column Creation

If you use a column that doesn't exist in your configuration:

ScenarioResult
Columns: [todo, done]Default setup
Task uses >>stagingColumns become [todo, staging, done]
Task uses >>reviewColumns become [todo, staging, review, done]

New columns are automatically inserted before "done". To reorder, update the columns in Settings or note frontmatter.

⁠Drag and Drop
  • Drag any task card to move it between columns
  • The task's >>column syntax is automatically updated in the markdown
  • Changes are saved immediately to the note
⁠Column Assignment Rules
ConditionResulting Column
No >>column + unchecked [ ]todo
No >>column + checked [x]done
Explicit >>column (any checkbox state)The specified column

Key point: Explicit >>column syntax always takes precedence over the checkbox state. This lets you have completed tasks in a "review" column.

⁠In Action

Here are some screenshots of what it looks like:

Main editor:

Search page:

Task list:

⁠Running

The recommended way of running is to pull the image from Docker Hub⁠.

⁠Docker Setup
⁠Environment Variables
Environment VariableDescriptionDefault
API_SECRET_KEYUsed to sign API tokens.Will be generated automatically if not passed in.
DATABASE_URIConnection string for DB.Will create and use a SQLite DB if not passed in.
DB_ENCRYPTION_KEYSecret key for encrypting data. Length must be a multiple of 16.

Warning: If changed data will not be able to be decrypted!
Will be generated automatically if not passed in.
PREVENT_SIGNUPSDisable signup form? Anything in this variable will prevent signups.False
BASE_URLUsed when using a subfolder on a reverse proxyNone
PUIDUser ID (for folder permissions)None
PGIDGroup ID (for folder permissions)None
DEFAULT_TIMEZONEOptional TZ name (e.g., America/Denver) for external ICS events; falls back to server local timeNone
SMTP_HOSTSMTP server hostname for sending emails (password reset, magic links)None (email features disabled)
SMTP_PORTSMTP server port587
SMTP_USERSMTP username/email for authenticationNone
SMTP_PASSWORDSMTP password or app-specific passwordNone
SMTP_USE_TLSUse TLS for SMTP connection (true or false)true
SMTP_FROM_EMAILFrom address for sent emailsSMTP_USER value
SMTP_FROM_NAMEDisplay name for sent emailsDailyNotes
APP_URLPublic URL of your DailyNotes instance (used in email links)http://localhost:8000⁠
⁠Volumes
Volume NameDescription
/app/configUsed to store DB and environment variables. This is not needed if you pass in all of the above environment variables.
⁠Docker Run

By default, the easiest way to get running is:

docker run -p 8000:8000 -v /config_dir:/app/config xhenxhe/dailynotes
⁠Docker Compose

Here is a complete docker-compose example with all configuration options:

services:
  dailynotes:
    image: xhenxhe/dailynotes:latest
    container_name: DailyNotes
    ports:
      - '8000:8000'
    volumes:
      # Persistent storage for database and config
      - ./dailynotes-data:/app/config
    environment:
      # Required: Secret key for signing JWT tokens
      # Generate with: openssl rand -hex 32
      API_SECRET_KEY: 'your-secure-api-secret-key-here'

      # Required: Encryption key for data at rest (must be multiple of 16)
      # Generate with: openssl rand -hex 32
      # WARNING: Changing this will make existing data unreadable!
      DB_ENCRYPTION_KEY: 'your-secure-db-encryption-key-here'

      # Optional: Database connection string
      # Default: SQLite database in /app/config/app.db
      # Examples:
      #   PostgreSQL: postgresql://user:password@host:5432/dailynotes
      #   MySQL:      mysql+pymysql://user:password@host:3306/dailynotes?charset=utf8mb4
      # DATABASE_URI: "sqlite:////app/config/app.db"

      # Optional: Prevent new user signups (set to any value to disable)
      # PREVENT_SIGNUPS: "true"

      # Optional: Base URL when using a reverse proxy subfolder
      # Example: If accessing via https://example.com/notes, set to "/notes"
      # BASE_URL: ""

      # Optiona

Tag summary

Content type

Image

Digest

sha256:0b3bc9dd9…

Size

72.9 MB

Last updated

7 months ago

docker pull xhenxhe/dailynotes