# Org Web Adapter A lightweight local web app for browsing and editing Org files. The app is implemented as a single Python server (`main.py`) plus one HTML template (`templates/index.html`) and one stylesheet (`static/style.css`). It scans a notes directory for `.org` files and renders a 3-pane UI: - left sidebar: note list + search/sort controls - center pane: note content (preview or edit) - right sidebar: backlinks to the current note ## Screenshots ### Desktop ![Desktop view](media/desktop.png) ### Mobile ![Mobile view](media/mobile.png) ## Instructions 1. Symlink your notes directory to `notes`. 2. Edit the bind address and port in `config.yaml` if desired. 3. `python3 main.py`. ## How's it work? 1. `main.py` starts an HTTP server. 2. On each page request (`GET /`), it rescans the notes directory for `.org` files. 3. It resolves links/backlinks and builds HTML fragments. 4. It injects those fragments into `templates/index.html` placeholders: - `{{NAV_ITEMS}}` - `{{MAIN_CONTENT}}` - `{{BACKLINKS}}` 5. Browser JS in `templates/index.html` handles client-side interactions (search, shuffle, sorting, jump-to-current, theme toggle). ## Server-side components (`main.py`) - File discovery and parsing: - `scan_org_files(...)` recursively finds `.org` files. - Extracts title from `#+TITLE:` and ID from `:ID:`. - Org link/backlink handling: - `resolve_link_target(...)` supports `file:...` and `id:...` links. - `find_backlinks(...)` computes notes linking to the selected note. - `build_backlink_counts(...)` computes backlink totals for sorting. - Rendering: - `render_org_to_html(...)` converts headings (`*`, `**`, ...) and paragraphs to simple HTML. - `render_line_with_links(...)` converts org links in text to clickable app links where resolvable. - `truncate_label(...)` caps sidebar labels to 32 chars with `...`. - Editing: - `POST /edit` updates a selected `.org` file and redirects back with status flags. - Static files: - `serve_static(...)` serves files under `static/` with path traversal protection. ## Frontend components - `templates/index.html`: - Base layout markup. - Sidebar controls. - Small JS controller for filtering/sorting/shuffling nav links. - MathJax initialization for inline `$...$` rendering. - `static/style.css`: - 3-column desktop grid and stacked mobile layout. - Independent scroll regions for note list and backlinks. - Mobile note-list cap (about 5 notes visible before scrolling). ## Configuration Startup config is read from `config.yaml` by default. - `bind_addr`: host/IP to bind - `bind_port`: TCP port (must be `1..65535`) Notes: - If `config.yaml` is missing, defaults are `127.0.0.1:8000`. - CLI flags `--host` and `--port` override config values. - You can choose a different config file with `--config /path/to/config.yaml`. ## Useful run commands ```bash python3 main.py --dir notes python3 main.py --host 127.0.0.1 --port 9000 python3 main.py --config ./config.yaml python3 main.py --no-browser ``` ## Features ### Note browsing - Recursive `.org` file discovery. - Sidebar note list with active-note highlighting. - Title/path search filter. ### Sidebar ordering controls - Shuffle notes. - Sort by backlink count (descending). - Sort by created date (ascending). - Notes without timestamps are treated as older than notes with timestamps. - Jump to current note button. ### Backlinks - Right sidebar lists notes linking to the current note. - Supports both `file:` and `id:` link resolution. ### Editing - Toggle Preview/Edit for the selected note. - Save changes from browser to disk. - Inline status messages for save success/errors. ### Math rendering - Inline math rendering via MathJax using `$...$` delimiters. ### UI behavior - Light/dark theme toggle (persisted in `localStorage`). - Desktop: independent scrollable sidebars. - Mobile: notes list capped with its own scroll area. - Sidebar text truncation with ellipsis and tooltip for full text. ## Project layout - `main.py`: server, parsing, rendering, routing. - `templates/index.html`: page template + UI behavior JS. - `static/style.css`: styling and responsive layout. - `config.yaml`: bind config. - `notes/`: notes directory (can be a symlink). - `old_notes/`: alternate local notes snapshot. ## Limitations - Not a full Org parser; rendering is intentionally simple. - Notes are rescanned on each request (simple and fresh, but not optimized for huge note sets). - Math rendering depends on loading MathJax from CDN.