Skip to content

Repository files navigation

Notes App

A simple, self-hosted note-taking application similar to Obsidian, built with Kotlin, Ktor, and HTMX.

Features

  • Markdown Notes: All notes stored as .md files with YAML frontmatter support
  • Split Editor: CodeMirror editor with live preview
  • Wiki Links: [[Note Name]] syntax for linking notes
  • Full-Text Search: SQLite-powered search across all notes
  • Folder Organization: Support for nested folders and subdirectories
  • GitHub OAuth: Secure authentication via oauth2-proxy
  • Per-User Storage: Each user has their own private note space

Tech Stack

  • Backend: Kotlin + Ktor 3.3.0
  • Frontend: FreeMarker templates + HTMX + CodeMirror
  • Search: SQLite with LIKE-based full-text search
  • Markdown: CommonMark with YAML frontmatter parsing
  • Auth: oauth2-proxy with GitHub provider
  • Container: Podman Compose

Prerequisites

  • Java 25+ (or compatible JDK)
  • Podman and Podman Compose
  • GitHub OAuth App (for authentication)

GitHub OAuth App Setup

  1. Go to GitHub Developer Settings
  2. Click "New OAuth App"
  3. Fill in:
    • Application Name: Notes App
    • Homepage URL: http://localhost:8000
    • Authorization callback URL: http://localhost:8000/oauth2/callback
  4. Click "Register application"
  5. Copy the Client ID and generate a Client Secret

Local Development

1. Clone and Configure

git clone <repository-url>
cd notes-app

2. Set Up Environment

cp .env.example .env

Edit .env with your GitHub OAuth credentials:

GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
OAUTH2_PROXY_COOKIE_SECRET=$(openssl rand -base64 32)

3. Build the Application

./gradlew build

4. Run with Docker Compose

podman-compose up --build

The application will be available at:

Running Without Docker

For development, you can run the app directly:

# Set environment variable
export NOTES_PATH="./notes"
export GITHUB_CLIENT_ID="your-client-id"
export GITHUB_CLIENT_SECRET="your-client-secret"

# Run the application
./gradlew installDist
./build/install/notes-app/bin/notes-app

Note: Without oauth2-proxy, you'll need to add the X-Auth-Request-User header manually for testing:

curl -H "X-Auth-Request-User: testuser" http://localhost:8080/

Project Structure

notes-app/
├── src/main/kotlin/com/notes/
│   ├── Application.kt          # Main Ktor application
│   ├── model/
│   │   └── Note.kt             # Data models
│   ├── services/
│   │   ├── NoteService.kt      # File operations
│   │   └── SearchService.kt    # SQLite search
│   └── util/
│       └── MarkdownParser.kt   # Markdown & frontmatter
├── src/main/resources/
│   ├── application.conf         # Ktor configuration
│   └── templates/              # FreeMarker templates
├── compose.yaml                 # Podman Compose
├── Dockerfile                    # Container build
└── notes/                       # Note storage (created at runtime)

Usage

Creating Notes

  1. Click "+ New Note" in the sidebar
  2. Enter a title and optional tags
  3. The note is created with YAML frontmatter

Markdown Frontmatter

Notes support YAML frontmatter:

---
title: My Note Title
tags:
  - kotlin
  - jvm
created: 2024-01-15T10:00:00Z
---

# My Note Title

Content here...

Wiki Links

Link to other notes using double brackets:

See [[Another Note]] for details.

Search

Use the search bar in the sidebar to search across all your notes.

API Endpoints

Endpoint Method Description
/ GET Main application (requires auth)
/notes GET List all notes
/notes/{path} GET View/edit specific note
/notes/new POST Create new note
/notes/{path} PUT Update note
/notes/{path} DELETE Delete note
/search?q= GET Search notes
/tree GET Folder tree structure
/health GET Health check (no auth)

Configuration

Environment Variables

Variable Description Default
NOTES_PATH Path to notes storage ./notes
GITHUB_CLIENT_ID GitHub OAuth Client ID -
GITHUB_CLIENT_SECRET GitHub OAuth Secret -
OAUTH2_PROXY_COOKIE_SECRET Session encryption key -

Application Configuration

Edit src/main/resources/application.conf:

ktor {
    application {
        modules = [com.notes.ApplicationKt.module]
    }
    deployment {
        port = 8080
    }
}

notes {
    path = ${NOTES_PATH ?: "./notes"}
}

Testing

./gradlew test

Troubleshooting

Notes not appearing

  • Ensure the notes/{username}/ directory exists and contains .md files
  • Check file permissions

Search not working

  • Search requires at least 2 characters
  • The SQLite database is created automatically on first run

OAuth not working

  • Verify callback URL matches exactly: http://localhost:8000/oauth2/callback
  • Ensure GitHub OAuth app is registered correctly

License

MIT

About

A vibe coded notepad web application

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages