mirror of
https://git.srhtnin.garden/sarah/SaraView.git
synced 2026-10-13 18:28:14 +02:00
271 lines
9.5 KiB
Markdown
271 lines
9.5 KiB
Markdown
# SaraView
|
|
|
|
A self-hosted web file previewer/editor. Obsidian's look, without the parts
|
|
you don't use, plus image and video previewing. Read-only integration with
|
|
SaraTag's per-file Book tags is included.
|
|
|
|
It's made by Sarah, hence the name. :3
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
SaraView is for people who want an Obsidian-style notes app they host
|
|
themselves, people who want to preview and edit files from any browser, and
|
|
people who want multiple accounts with their own private directories.
|
|
|
|
Example use-cases:
|
|
|
|
- Browsing and editing markdown notes from your phone, without installing
|
|
anything.
|
|
|
|
- Previewing images and videos that live next to your notes.
|
|
|
|
- Giving a friend or family member their own login, with a directory only
|
|
they can see.
|
|
|
|
---
|
|
|
|
## Dependencies
|
|
|
|
Docker + Docker Compose. That's it for running it.
|
|
|
|
For local development instead: Python 3.11+, and Node.js + npm.
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
Here's a step-by-step tutorial.
|
|
|
|
1. Clone or download this repository.
|
|
2. Edit `SaraViewConf.toml` at the project root. Set your `[Roots]`,
|
|
`[SaraTag]`, and `[Storage]` paths. (See Config Info below for what each
|
|
field does.)
|
|
3. Edit `docker-compose.yml`. Add a `volumes:` line for every root you
|
|
declared, mount your SaraTag `.saratag` folder read-only, and bind the
|
|
port to your Tailscale interface's IP instead of `0.0.0.0` if you want it
|
|
reachable only over the tailnet.
|
|
4. Run ```docker compose up --build -d```.
|
|
|
|
The backend serves the built frontend directly, so the whole app is on one
|
|
port (`8420` by default).
|
|
|
|
---
|
|
|
|
## Config Info
|
|
|
|
Paths in `SaraViewConf.toml` are resolved as given. Use absolute container
|
|
paths when running via Docker (see `docker-compose.yml`), matching whatever
|
|
you mount the volumes to.
|
|
|
|
```toml
|
|
[SaraView]
|
|
ConfigVersion = 1
|
|
ApplicationVersion = "0.1.0-beta"
|
|
|
|
[Server]
|
|
Host = "0.0.0.0"
|
|
Port = 8420
|
|
|
|
[Storage]
|
|
DataDirectory = "/data/SaraViewData"
|
|
|
|
[Roots]
|
|
Notes = "/data/notes"
|
|
|
|
[SaraTag]
|
|
Enabled = true
|
|
CoreModulePath = "/data/SaraTag/.saratag"
|
|
HideInternalFiles = true
|
|
InternalPatterns = [".saratag", ".SaraTag*", "*.book.toml"]
|
|
```
|
|
|
|
- `[Storage] DataDirectory` is where SaraView keeps its own data - Settings,
|
|
Users, Themes, and so on. This is NOT one of the `[Roots]` below, so it's
|
|
structurally unreachable from the file browser regardless of any
|
|
hidden-file setting. Give it its own persistent volume (see
|
|
`docker-compose.yml`) so it survives rebuilds.
|
|
|
|
- `[Roots]` lists the named roots the browser can navigate. Add as many as
|
|
you like; each becomes a top-level entry point in the frontend's root
|
|
switcher.
|
|
|
|
- `[SaraTag]`, if `Enabled`, makes SaraView import SaraTag's own `Core.py`
|
|
directly (by file path, not by installing it as a package) to resolve
|
|
Book tag files exactly the way SaraTag itself does. This is read-only -
|
|
SaraView never writes Book or Lexicon files.
|
|
|
|
---
|
|
|
|
## Local Development
|
|
|
|
Backend:
|
|
|
|
```bash
|
|
cd Backend
|
|
pip install -r requirements.txt
|
|
uvicorn Main:Application --reload --port 8420
|
|
```
|
|
|
|
Frontend, in a second terminal. Vite proxies `/api` to the backend.
|
|
|
|
```bash
|
|
cd Frontend
|
|
npm install
|
|
npm run dev
|
|
```
|
|
|
|
---
|
|
|
|
## Directories as Files
|
|
|
|
Every directory gets its own note file. It's a hidden `.sv_{DirectoryName}.md`,
|
|
created automatically the moment you make the directory. Any extension works
|
|
if you rename the note later; markdown is just the default.
|
|
|
|
Click a directory the same way you'd click a file, and its note opens with
|
|
the same edit/view/save toolbar. There's no separate "directory mode."
|
|
Renaming or moving a directory keeps its note's name in sync automatically.
|
|
Deleting a directory takes its note with it.
|
|
|
|
Browsing what's actually inside a directory is a sidebar-only action.
|
|
Expand a folder there to see its contents. The "Open directory file on
|
|
click" setting in Settings decides whether expanding a directory in the
|
|
sidebar also opens its note in the main pane, or leaves the main pane alone.
|
|
|
|
Note files are hidden from listings by default, since their name starts
|
|
with `.sv_`. This is independent of the regular "show hidden directories"
|
|
setting. Flip on "Show directory note files (.sv_*)" in Settings if you
|
|
want to see and manage them directly, like any other file.
|
|
|
|
---
|
|
|
|
## SaraTag Integration
|
|
|
|
SaraView never writes to Book or Lexicon files. It only reads them, by
|
|
loading SaraTag's own `Core.py` directly (by file path, not as an installed
|
|
package), so tag resolution always matches what SaraTag itself would show.
|
|
|
|
Editing tags from SaraView isn't implemented yet. SaraTag's own TUI remains
|
|
the place to do that for now.
|
|
|
|
---
|
|
|
|
## Settings and Themes
|
|
|
|
Settings (font, font size, active theme, hidden-folder visibility,
|
|
breadcrumb visibility) and themes live in `Settings.toml` and
|
|
`Themes/*.toml` inside the `saraview_data` volume. Not in any of your
|
|
`[Roots]`, so they're never browsable from the app itself.
|
|
|
|
Three themes ship built in: CatppuccinMocha, Gruvbox, and Forest. Every
|
|
theme is just a flat set of named color roles (Background, Surface, Text,
|
|
Red, Orange, ... Purple), so creating a custom theme from Settings, or
|
|
hand-writing a new file in `Themes/`, only needs those same role names
|
|
filled in.
|
|
|
|
This is all per-user. Each account gets its own `Settings/<Username>.toml`
|
|
inside the data volume, seeded from the same defaults the first time that
|
|
user logs in. Themes themselves are shared across everyone (there's only
|
|
one copy of each theme file), but which theme is active is a per-user
|
|
choice.
|
|
|
|
---
|
|
|
|
## Accounts and Login
|
|
|
|
On first launch, with no accounts yet, SaraView shows a one-time "create
|
|
the admin account" screen instead of a normal login. Whoever sets that up
|
|
first becomes an admin. After that, it's a normal username/password login
|
|
screen for everyone.
|
|
|
|
Accounts live in `Users.toml` in the same `saraview_data` volume as
|
|
Settings and Themes. Passwords are hashed with PBKDF2-SHA256, never stored
|
|
in plain text. Admins get a "Users" section inside Settings to create
|
|
additional accounts, including other admins.
|
|
|
|
Sessions are currently in-memory only, so restarting the container logs
|
|
everyone out. Fine for now with a small, trusted set of tailnet users.
|
|
|
|
---
|
|
|
|
## Running on the Server
|
|
|
|
SaraView runs on SpineS as a **Portainer stack built straight from this
|
|
repo**. Portainer clones the repo, builds the image from the `Dockerfile`
|
|
and starts it, using `docker-compose.server.yml`. There's no image registry
|
|
and no CI: pushing a commit is all a release takes.
|
|
|
|
Config and data live in plain directories on the server (by default
|
|
`/media/ZimaOS-HD/AppData/SaraView`, holding `SaraViewConf.toml` and
|
|
`Data/`), not in a Docker volume, so redeploying or removing the stack never
|
|
touches them. The files SaraView serves are mounted at `/data/files`
|
|
(default `/media/ZimaOS-HD/Storage/Files`); the Roots in the server's
|
|
`SaraViewConf.toml` point inside it.
|
|
|
|
### Setting up the stack
|
|
|
|
1. `SaraViewConf.toml` has to exist in the config directory before the first
|
|
deploy: Docker would otherwise create a *directory* with that name.
|
|
2. In Portainer: **Stacks** → **Add stack** → **Repository**, on the
|
|
SpineS environment.
|
|
- Repository URL: this repo on Gitea (`http://git.srhtnin.garden/sarah/SaraView`)
|
|
- Repository reference: `refs/heads/main`
|
|
- Compose path: `docker-compose.server.yml`
|
|
- Environment variables: none needed on SpineS. Set `SaraViewDir` and/or
|
|
`FilesDir` to use other directories.
|
|
- **GitOps updates** on, with polling (e.g. every 5 minutes), so new
|
|
commits on `main` redeploy on their own.
|
|
3. Stop anything else using port 8420 (e.g. an older SaraView install), then
|
|
**Deploy the stack**. The first build takes a few minutes.
|
|
|
|
### Updating
|
|
|
|
Push to `main`. With GitOps updates on, Portainer notices the new commit
|
|
and rebuilds and redeploys by itself. Otherwise, press **Pull and redeploy**
|
|
on the stack.
|
|
|
|
---
|
|
|
|
## Groups and Access Control
|
|
|
|
Admin isn't a hardcoded flag. It's the built-in "Admin" group, which can't
|
|
be deleted but is otherwise just a group like any other. Manage groups
|
|
(create, delete, edit membership) from Settings → Groups (admin-only).
|
|
|
|
Setting access on a file or directory is **not** admin-only. Anyone can
|
|
restrict a file or directory to specific users and/or groups, whether at
|
|
creation time (the New File/New Directory dialog includes a search-and-
|
|
checkbox picker) or afterwards via the 🔒 button next to any entry, in
|
|
either the sidebar tree or the directory-browse pane. If you can currently
|
|
see something, you're trusted to change who else can.
|
|
|
|
Admins do not bypass restrictions. Admin is a management group (creating
|
|
users, managing groups, and so on), not a way to view everyone's private
|
|
directories. Only direct access to the server's files can see everything.
|
|
|
|
Restricting is per-file-or-directory. Locking a directory covers everything
|
|
inside it automatically (there's only ever one restriction record per
|
|
locked directory; reaching anything underneath still requires being
|
|
permitted on that ancestor), while locking an individual file affects only
|
|
that file.
|
|
|
|
Anyone without access gets a plain 404, both for direct requests and for
|
|
that entry showing up in a directory listing. A restricted item's existence
|
|
isn't revealed to people who can't see it. Admins get a global overview of
|
|
every current restriction from Settings → Locked Directories.
|
|
|
|
---
|
|
|
|
## Blame Privacy
|
|
|
|
Each person can turn off "Show my edits in others' blame view" in their own
|
|
Settings. When that's off, other users still see that lines were changed,
|
|
just with the identity redacted, rather than attributing it to someone who
|
|
asked not to be shown. You can always see your own attribution regardless
|
|
of this setting.
|
|
|
|
There's also a per-viewer toggle for showing avatars instead of usernames
|
|
in the blame gutter, using each author's chosen colour either way.
|