Remove Agents.md
This commit is contained in:
163
AGENTS.md
163
AGENTS.md
@@ -1,163 +0,0 @@
|
||||
# AGENTS.md — Personal Wiki (go-wiki)
|
||||
|
||||
## Project Philosophy
|
||||
This is a minimal personal wiki where the **folder structure is the wiki**.
|
||||
There is no database, no CMS, no abstraction layer between the user and their files.
|
||||
Every decision should reinforce this — if a proposed solution adds indirection between
|
||||
the filesystem and what the user sees, question it.
|
||||
|
||||
## Core Concept
|
||||
- Every folder *is* a page
|
||||
- `index.md` in a folder is that page's content
|
||||
- All related files (PDFs, images, CAD files, etc.) live in the same folder as `index.md`
|
||||
- Image links in `index.md` like `` work because siblings are served at the same path
|
||||
- There are no "attachments" — files are just files in a folder
|
||||
|
||||
## Target Environment
|
||||
- Runs on a QNAP TS-431P3 NAS (Annapurna Labs AL-314, ARMv7 32-bit, `linux/arm`)
|
||||
- All files live on the NAS and are mounted/accessed locally by the binary
|
||||
- Users access via browser over Wireguard VPN from Windows, Linux, and Android
|
||||
- Must cross-compile cleanly: `GOARCH=arm GOOS=linux GOARM=7 go build`
|
||||
|
||||
## Tech Constraints
|
||||
- **Language:** Go
|
||||
- **Output:** Single static binary, no installer, no runtime dependencies
|
||||
- **Markdown:** `goldmark` for server-side rendering — no other markdown libraries
|
||||
- **Assets:** Embedded via `embed.FS` — no external asset serving or CDN
|
||||
- **HTTP:** stdlib `net/http` only — no web framework
|
||||
- **Dependencies:** Keep to an absolute minimum. If stdlib can do it, use stdlib.
|
||||
|
||||
## HTTP Interface
|
||||
The entire API surface should stay minimal:
|
||||
|
||||
| Method | Path | Behaviour |
|
||||
|--------|------|-----------|
|
||||
| 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.
|
||||
|
||||
## UI Principles
|
||||
- Mobile-first — the primary editing device is Android over Wireguard
|
||||
- No JavaScript frameworks — vanilla JS only, and only when necessary
|
||||
- No build pipeline for frontend assets — what is embedded is what is served
|
||||
- Readable on small screens without zooming
|
||||
- Fast on a low-power ARM CPU — no heavy rendering, no large payloads
|
||||
|
||||
## Frontend Conventions
|
||||
|
||||
**JS file scoping:** each feature gets its own file. Global app behaviour goes in
|
||||
`global-shortcuts.js`. Feature-specific logic gets its own file (e.g. `editor.js`).
|
||||
Do not inline JS in the template or consolidate unrelated features into one file.
|
||||
|
||||
**Keyboard shortcuts:** `ALT+SHIFT` is the established modifier for all application
|
||||
shortcuts — it avoids collisions with browser and OS bindings. Do not use other
|
||||
modifiers for new shortcuts.
|
||||
|
||||
**Editor toolbar:** buttons use `data-action` (maps to a JS action function) and
|
||||
`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
|
||||
|
||||
## What to Avoid
|
||||
- No database of any kind
|
||||
- No indexing or caching layer unless explicitly requested and justified
|
||||
- No parallel folder structures (the DokuWiki anti-pattern: `pages/` mirrored by `media/`)
|
||||
- No frameworks (web, ORM, DI, etc.)
|
||||
- No build steps for frontend assets
|
||||
- Do not suggest Docker unless the user asks — a plain binary is preferred
|
||||
|
||||
## Development Order
|
||||
When building new features, follow this priority order:
|
||||
1. Correctness on the filesystem (never corrupt or lose user files)
|
||||
2. Mobile usability
|
||||
3. Simplicity of implementation
|
||||
4. Performance
|
||||
|
||||
## Out of Scope (for now)
|
||||
These are explicitly deferred — do not implement or scaffold unless asked:
|
||||
- Full-text search
|
||||
- File upload via browser
|
||||
- Version history / git integration
|
||||
- Multi-user support
|
||||
- Tagging or metadata beyond `index.md` content
|
||||
Reference in New Issue
Block a user