- **Collapsible folder navigation** — a pull-tab button on mobile and a `View → Hide/Show Folder Nav` toggle at any width let you collapse the folder list to give the note list more room
- **Independent mobile scrolling** — the folder nav and note list each scroll within their own bounded area on phones, instead of sharing one scroll position
- **Save Note moved** — the action now lives in the `File` menu alongside `New Note`, rather than under `Edit`
- **Folder-nav state persists** — hiding the folder nav saves the preference to browser storage and switches the sidebar to All Notes without navigating away from an open note, so unsaved edits survive
- **Delete confirmation** — deleting a note now asks you to confirm, showing the note's folder and title so you know exactly what you are about to remove
- **Virtual folders** — organize notes into folders without creating real directories. A folder is encoded as a `[Folder]uuid.md` filename prefix, so a single notes directory can hold many of them
- **Move notes between folders** — drag a note onto a folder in the sidebar, use `File → Move to Folder…`, or use the Move control in the editor on a phone
- **Re-filing is a rename** — `[Work]uuid.md` becomes `[Home]uuid.md`. The note's id never changes, so links to it keep working, and its modified time is not bumped
- **Long-press drag on touch** — the re-file gesture on a phone
- **Quieter folder counts** — badges show across every folder in the All Notes view, and only on the folder you are inside otherwise
- **Pinned folder list** — folders stay visible and droppable however long the note list grows
- **Uses a small amount of JavaScript** — note editing, search, and the login form are plain HTML; the menus, mobile tabs, live preview, and drag-and-drop re-filing are the JS-dependent parts
- **Optional weather** — server-side wttr.in lookup with a Celsius/Fahrenheit choice, a current-plus-forecast table, caching, and a graceful offline fallback
- **Welcome quotes** — locally stored quotes rotate under the welcome message with pause and reduced-motion support
- **Mobile weather page** — `View → Weather` offers a mobile-first weather view on phones
Notes are stored in the `notes/` directory as `.md` files with YAML frontmatter. If you configure weather, its location is stored in `notes/.weather_location` and its unit in `notes/.weather_units` alongside the notes and both follow `--notes-dir`. Saved quotes live in `notes/.quotes.json`.
Root notes (no folder) keep the plain `uuid.md` format. Folders exist only when they contain at least one note — there is no separate folder metadata to manage.
**Filtering:** click a folder name in the sidebar to see only that folder's notes. Click **All Notes** to see everything grouped by folder. When a folder is active, the **+ New Note** button creates notes in that folder.
**Moving a note between folders:** drag it from the sidebar onto a folder, pick `File → Move to Folder…`, or use the Move control under the editor on a phone. Dropping a note on **All Notes** — or choosing **Unfiled** — takes it back out of its folder.
A move renames the file: `[Work]uuid.md` becomes `[Home]uuid.md`. The note's id is left untouched, so links to it keep working, and its modified time is not bumped, since re-filing is not an edit.
**Validation:** folder names reject path traversal (`..`), shell metacharacters (`;`, `|`, `&`, `$`, backtick, parens, angle brackets), control characters, leading dots, and names over 100 characters. Invalid names show a red flash message at the top of the page.
**First launch:** the server prints a QR code to your terminal and waits for a 6-digit code. Scan it with any TOTP authenticator (FreeOTP, Aegis, Bitwarden, Google Authenticator, …), or type the Base32 secret by hand if you would rather not scan. Only after a valid code is the secret committed to `.totp_secret` in the project root with mode `0600` — and only then does the port start listening.
Enrollment deliberately happens in the terminal rather than on a web page. There is no `/setup` route to reach: an HTTP-reachable setup endpoint would let anyone who can reach the port before you finish claim the device.
**Every launch after that:** you land on `/login` and need a current code. Sessions last one hour and live only in memory, so restarting the server invalidates them.
**Lost your authenticator?** Delete the secret and restart:
```bash
rm .totp_secret
```
There is no recovery-code fallback by design — that file is the only thing holding the secret, and it stays on your machine.
The proxy strips the prefix, so the app still sees ordinary paths and adds the prefix back when generating links, form actions, and redirects. The session cookie's `Path` is scoped to the prefix, so the token is not sent to sibling apps on the same host.
## Command Line Options
```
Usage: eternalibre-notes [OPTIONS]
Options:
--host <HOST> Host address to bind to [default: 0.0.0.0]
-p, --port <PORT> Port to listen on [default: 3000]
--base-path <BASE_PATH> Path prefix when behind a reverse proxy subdirectory. Example: --base-path /forgejo when the app answers at https://host/forgejo/. Leave empty when mounted at the site root [default: ""]