✨ Check out this must-read post from Hacker News 📖
📂 **Category**:
💡 **What You’ll Learn**:
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.


- Symlink your notes directory to
notes. - Edit the bind address and port in
config.yamlif desired. python3 main.py.
main.pystarts an HTTP server.- On each page request (
GET /), it rescans the notes directory for.orgfiles. - It resolves links/backlinks and builds HTML fragments.
- It injects those fragments into
templates/index.htmlplaceholders:🔥🔥{{BACKLINKS}}
- Browser JS in
templates/index.htmlhandles 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.orgfiles.- Extracts title from
#+TITLE:and ID from:ID:.
- Org link/backlink handling:
resolve_link_target(...)supportsfile:...andid:...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 /editupdates a selected.orgfile and redirects back with status flags.
- Static files:
serve_static(...)serves files understatic/with path traversal protection.
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).
Startup config is read from config.yaml by default.
bind_addr: host/IP to bindbind_port: TCP port (must be1..65535)
Notes:
- If
config.yamlis missing, defaults are127.0.0.1:8000. - CLI flags
--hostand--portoverride config values. - You can choose a different config file with
--config /path/to/config.yaml.
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
- Recursive
.orgfile 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.
- Right sidebar lists notes linking to the current note.
- Supports both
file:andid:link resolution.
- Toggle Preview/Edit for the selected note.
- Save changes from browser to disk.
- Inline status messages for save success/errors.
- Inline math rendering via MathJax using
$...$delimiters.
- 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.
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.
- 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.
{💬|⚡|🔥} **What’s your take?**
Share your thoughts in the comments below!
#️⃣ **#SpaceTurthOrgWebAdapter #simple #view #org #roam #notes #editing #backlinks #rendered #math**
🕒 **Posted on**: 1771261362
🌟 **Want more?** Click here for more info! 🌟
