Update README and AGENTS
This commit is contained in:
82
AGENTS.md
82
AGENTS.md
@@ -32,9 +32,13 @@ The entire API surface should stay minimal:
|
||||
|
||||
| Method | Path | Behaviour |
|
||||
|--------|------|-----------|
|
||||
| GET | `/{path}` | If folder: render `index.md` + list contents. If file: serve raw. |
|
||||
| GET | `/{path}?edit` | Mobile-friendly editor with `index.md` content in a textarea |
|
||||
| POST | `/{path}` | Write updated `index.md` to disk |
|
||||
| GET | `/{path}/` | If folder exists: render `index.md` + list contents. If not: show empty create prompt. |
|
||||
| GET | `/{path}/?edit` | Mobile-friendly editor with `index.md` content in a textarea |
|
||||
| POST | `/{path}` | Write `index.md` to disk; creates the folder if it does not exist yet |
|
||||
|
||||
Non-existent paths without a trailing slash redirect to the slash form (GET only — POSTs
|
||||
are not redirected because `path.Clean` strips the trailing slash from `PostURL` and the
|
||||
content would be lost).
|
||||
|
||||
Do not add endpoints beyond these without a concrete stated need.
|
||||
|
||||
@@ -59,6 +63,78 @@ modifiers for new shortcuts.
|
||||
`data-key` (the `ALT+SHIFT+KEY` shortcut letter). Adding a `data-key` to a button
|
||||
automatically registers its shortcut — no extra wiring needed.
|
||||
|
||||
## Code Structure
|
||||
|
||||
The backend is split across three files:
|
||||
|
||||
| File | Responsibility |
|
||||
|------|----------------|
|
||||
| `main.go` | Server setup, routing, `serveDir`, `handlePost`, `pageTypeHandler` interface, `readPageSettings` |
|
||||
| `render.go` | Shared helpers: markdown rendering, heading extraction, file listing, icons, formatting |
|
||||
| `diary.go` | Diary page type: all types, templates, and render functions |
|
||||
|
||||
When adding a new special folder type, create a new `.go` file. Do not add type-specific
|
||||
logic to `main.go` or `render.go`.
|
||||
|
||||
## Special Folder Types (`pageTypeHandler`)
|
||||
|
||||
Folders can opt into special rendering by placing a `.page-settings` file in them.
|
||||
Format: one `key = value` per line; `#` lines are comments.
|
||||
|
||||
```
|
||||
# example
|
||||
type = diary
|
||||
```
|
||||
|
||||
The server walks up from the requested path looking for a `.page-settings` file. When
|
||||
found, it determines the depth of the current path relative to that root and dispatches
|
||||
to the matching `pageTypeHandler`.
|
||||
|
||||
**Interface** (defined in `main.go`):
|
||||
|
||||
```go
|
||||
type specialPage struct {
|
||||
Content template.HTML
|
||||
SuppressListing bool
|
||||
}
|
||||
|
||||
type pageTypeHandler interface {
|
||||
handle(root, fsPath, urlPath string) *specialPage
|
||||
}
|
||||
```
|
||||
|
||||
`handle` returns `nil` when the handler does not apply. `SuppressListing` hides the
|
||||
default file/folder table (used when the special content replaces it).
|
||||
|
||||
**Registering a new type:** implement the interface in a new file and register via
|
||||
`init()`:
|
||||
|
||||
```go
|
||||
func init() {
|
||||
pageTypeHandlers = append(pageTypeHandlers, &myHandler{})
|
||||
}
|
||||
```
|
||||
|
||||
`serveDir` iterates `pageTypeHandlers` and uses the first non-nil result. It has no
|
||||
knowledge of specific types.
|
||||
|
||||
### Diary type (`diary.go`)
|
||||
|
||||
Activated by `type = diary` in a `.page-settings` file. Folder structure:
|
||||
|
||||
```
|
||||
Root/ ← .page-settings (type = diary)
|
||||
YYYY/ ← depth 1 — year view (month sections + photo counts)
|
||||
YYYY-MM-DD Description.ext ← photos live here, named with date prefix
|
||||
MM/ ← depth 2 — month view (day sections with content + photos)
|
||||
DD/ ← depth 3 — day view (index.md content + photo grid)
|
||||
index.md
|
||||
```
|
||||
|
||||
Photos are associated to days by parsing the `YYYY-MM-DD` prefix from filenames in the
|
||||
year folder. No thumbnailing is performed — images are served at full resolution with
|
||||
`loading="lazy"`. The year view shows only photo counts, not grids, for performance.
|
||||
|
||||
## Auth
|
||||
- Basic auth is sufficient — this is a personal tool on a private VPN
|
||||
- Do not over-engineer access control
|
||||
|
||||
37
README.md
37
README.md
@@ -25,6 +25,39 @@ GOOS=linux GOARCH=arm go build -o datascape .
|
||||
|--------|-----|
|
||||
| Browse | Navigate folders at `/` |
|
||||
| Read | Any folder with `index.md` renders it as HTML |
|
||||
| Edit | Append `?edit` to any folder URL, or click **Edit** |
|
||||
| Save | POST from the edit form writes `index.md` to disk |
|
||||
| Edit | Append `?edit` to any folder URL, or click **[EDIT]** (Alt+Shift+E) |
|
||||
| Save | POST from the edit form writes `index.md` to disk; folder is created if needed |
|
||||
| New page | Click **[NEW]** (Alt+Shift+N), enter a name — opens the new page in edit mode |
|
||||
| Files | Drop PDFs, images, etc. next to `index.md` — they appear in the listing |
|
||||
|
||||
Navigating to a URL that does not exist shows an empty page with a **[CREATE]** prompt.
|
||||
|
||||
## Special Folder Types
|
||||
|
||||
A folder can opt into special rendering by adding a `.page-settings` file:
|
||||
|
||||
```
|
||||
type = diary
|
||||
```
|
||||
|
||||
### Diary
|
||||
|
||||
Designed for a chronological photo diary. Expected structure:
|
||||
|
||||
```
|
||||
FolderName/
|
||||
.page-settings ← type = diary
|
||||
YYYY/
|
||||
YYYY-MM-DD Desc.jpg ← photos named with date prefix
|
||||
MM/
|
||||
DD/
|
||||
index.md ← diary entry for that day
|
||||
```
|
||||
|
||||
| View | What renders |
|
||||
|------|-------------|
|
||||
| Year (`YYYY/`) | Section per month with link and photo count |
|
||||
| Month (`MM/`) | Section per day with entry content and photo grid |
|
||||
| Day (`DD/`) | Entry content and photo grid |
|
||||
|
||||
Days with photos but no `index.md` still appear in the month view and can be created by clicking their heading link.
|
||||
|
||||
Reference in New Issue
Block a user