diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/decisions.md | 70 | ||||
| -rw-r--r-- | docs/help.md | 430 |
2 files changed, 500 insertions, 0 deletions
diff --git a/docs/decisions.md b/docs/decisions.md new file mode 100644 index 0000000..54a759b --- /dev/null +++ b/docs/decisions.md @@ -0,0 +1,70 @@ +# Decisions + +## 2026-07-07 - Build A Go CLI First + +Decision: + +Implement `gemcms` first as a Go command-line tool. + +Rationale: + +- A single static binary fits the self-hosted Gemini audience. +- The core workflows are filesystem and text processing tasks. +- Avoiding a web admin panel keeps the first version simple and robust. + +Consequences: + +- The first user experience is terminal-first. +- A TUI or local web editor can be added later without changing the capsule format. + +## 2026-07-07 - Keep Capsules File-Based + +Decision: + +Store pages, articles, menus, widgets, and config as project files. Do not use a database. + +Rationale: + +- Gemini capsules are naturally static and text-first. +- File storage keeps content easy to edit, back up, diff, and publish. +- A database would add operational cost before it solves a real problem. + +Consequences: + +- Build-time validation and generation are important. +- Future features should preserve direct file editability. + +## 2026-07-07 - Treat Widgets As Build-Time Blocks + +Decision: + +Widgets are static Gemtext blocks expanded during `gemcms build`. + +Rationale: + +- Gemini has no browser-side runtime. +- Static blocks keep output simple and portable. +- Menus, recent articles, indexes, and similar blocks can be generated reliably. + +Consequences: + +- Widget behavior is deterministic at build time. +- Interactive runtime widgets are out of scope for the core CMS. + +## 2026-07-07 - Import Existing Content As A First-Class Workflow + +Decision: + +Support importing one file or a directory of Markdown/Gemtext files through `gemcms add`, and support `gemcms create capsule` for creating a capsule, importing content, and optionally building output in one command. + +Rationale: + +- Many users will already have notes or articles as `.md` or `.gmi` files. +- A CMS for Gemini should reduce setup friction rather than requiring manual folder work. +- Keeping imports deterministic and file-based preserves direct editability. + +Consequences: + +- Import behavior must infer metadata from frontmatter, headings, and filenames. +- Directory imports should skip unrelated files rather than fail on them. +- Health/status commands become important for confidence after bulk imports. diff --git a/docs/help.md b/docs/help.md new file mode 100644 index 0000000..fd61e79 --- /dev/null +++ b/docs/help.md @@ -0,0 +1,430 @@ +# gemcms Help + +`gemcms` is a file-based CLI CMS for Gemini capsules. Most commands are run +inside a capsule directory, or one of its subdirectories. A capsule is detected +by the presence of `capsule.toml`. + +## Global Usage + +```text +gemcms +gemcms help +gemcms -h +gemcms --help +``` + +With no arguments, or with `help`, `-h`, or `--help`, `gemcms` prints the short +usage summary. + +Command flags can be placed before or after positional arguments: + +```bash +gemcms add ~/article.md --section journal +gemcms add --section journal ~/article.md +``` + +## Commands Overview + +```text +gemcms add <file-or-directory> [options] +gemcms create capsule <name> [options] +gemcms create site <name> [options] +gemcms create page <slug> [options] +gemcms create article <title> [options] +gemcms create section <name> [options] +gemcms create menu <name> +gemcms create widget <type> [options] +gemcms menu add <menu> <kind> [target] [options] +gemcms list <pages|articles|menus|widgets> +gemcms status +gemcms health +gemcms build +gemcms check +``` + +`create capsule` and `create site` are aliases. + +## `gemcms add` + +Import an existing Markdown or Gemtext file, or a directory containing importable +files. + +```text +gemcms add <file-or-directory> [--type article|page] [--title title] [--slug slug] [--section name] [--tags a,b] [--draft] [--menu name] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--type article|page` | `article` | Imported content type. Frontmatter `type` is used when present and this option is omitted. | +| `--title title` | inferred | Content title. Only valid when importing one file. | +| `--slug slug` | inferred | Content slug. Only valid when importing one file. | +| `--section name` | `articles` | Article section. Ignored for pages. | +| `--tags a,b` | none | Comma-separated tags. | +| `--draft` | `false` | Mark imported content as draft. Drafts are not built and are not added to menus. | +| `--menu name` | none | Add imported non-draft content to the named menu. | + +Accepted input extensions: + +```text +.md +.markdown +.gmi +.gemini +``` + +Directory imports recursively import supported files, skip hidden directories, +and sort files deterministically. `--title` and `--slug` cannot be used with +directory imports. + +Title inference order: + +1. Frontmatter `title` +2. First `# Heading` +3. File name converted to title case + +Examples: + +```bash +gemcms add ~/article.md --section journal --tags gemini --draft --menu top +gemcms add ~/notes/ --section journal --tags gemini +gemcms add ~/about.gmi --type page --slug about --menu top +``` + +## `gemcms create capsule` + +Create a new capsule project. This command also creates the default top menu, +home page, recent-articles widget, content directories, asset directory, and +`public/`. + +```text +gemcms create capsule <name> [--title title] [--host host] [--author name] [--language code] [--import path] [--type article|page] [--section name] [--tags a,b] [--draft] [--menu name] [--build] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--title title` | title-cased name | Capsule title written to `capsule.toml`. | +| `--host host` | empty | Gemini host name. | +| `--author name` | empty | Default author metadata. | +| `--language code` | `en` | Content language metadata. | +| `--import path` | none | Import one file or a directory after capsule creation. | +| `--type article|page` | inferred or `article` | Type for imported content. | +| `--section name` | `articles` | Section for imported articles. | +| `--tags a,b` | none | Tags for imported content. | +| `--draft` | `false` | Mark imported content as draft. | +| `--menu name` | none | Add imported non-draft content to a menu. | +| `--build` | `false` | Build `public/` after creation and optional import. | + +Example: + +```bash +gemcms create capsule my-capsule --title "My Capsule" --host gemini.example.org --import ~/articles --section journal --tags gemini --build +``` + +## `gemcms create site` + +Alias of `create capsule`. + +```text +gemcms create site <name> [same options as create capsule] +``` + +## `gemcms create page` + +Create a new page in `content/pages/`. + +```text +gemcms create page <slug> [--title title] [--menu name] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--title title` | title-cased slug | Page title. | +| `--menu name` | none | Add the page to the named menu. | + +Example: + +```bash +gemcms create page about --title "About" --menu top +``` + +## `gemcms create article` + +Create a new article in `content/articles/`. + +```text +gemcms create article <title> [--section name] [--tags a,b] [--draft] [--menu name] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--section name` | `articles` | Article section. | +| `--tags a,b` | none | Comma-separated tags. | +| `--draft` | `false` | Mark article as draft. Drafts are not built and are not added to menus. | +| `--menu name` | none | Add the non-draft article to the named menu. | + +Example: + +```bash +gemcms create article "Hello Gemini" --section journal --tags gemini,capsule --menu top +``` + +## `gemcms create section` + +Create a section config in `site/sections/`. + +```text +gemcms create section <name> [--title title] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--title title` | title-cased name | Section display title. | + +Example: + +```bash +gemcms create section journal --title "Journal" +``` + +## `gemcms create menu` + +Create an empty menu config in `site/menus/`. + +```text +gemcms create menu <name> +``` + +Example: + +```bash +gemcms create menu footer +``` + +## `gemcms create widget` + +Create a build-time widget config in `site/widgets/`. + +```text +gemcms create widget <type> [--name name] [--section name] [--limit n] +``` + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--name name` | widget type | Widget config name. | +| `--section name` | `articles` | Section used by recent article widgets. | +| `--limit n` | `5` | Maximum number of items. Values below `1` become `5`. | + +Currently supported widget type: + +| Type | Description | +| --- | --- | +| `recent` | Render recent non-draft articles from one section. | + +Example: + +```bash +gemcms create widget recent --name recent-journal --section journal --limit 10 +``` + +Use the widget in content: + +```text +{{ widget recent-journal }} +``` + +## `gemcms menu add` + +Add an item to a menu. Missing menus are created automatically. + +```text +gemcms menu add <menu> <home|page|section|article|custom> [target] [--label label] [--url url] +``` + +Kinds: + +| Kind | Target required | Default URL | Notes | +| --- | --- | --- | --- | +| `home` | no | `/` | Default label: `Home`. | +| `page` | yes | `/<target>.gmi` | `index` maps to `/`. | +| `section` | yes | `/<target>/` | Links to a generated section index. | +| `article` | yes | `/articles/<target>.gmi` | Uses the default `articles` section path. | +| `custom` | yes | none | Requires `--url`. | + +Options: + +| Option | Default | Description | +| --- | --- | --- | +| `--label label` | inferred | Link label. | +| `--url url` | inferred | Link URL. Required for `custom`. | + +Examples: + +```bash +gemcms menu add top home +gemcms menu add top page about --label "About" +gemcms menu add top section journal --label "Journal" +gemcms menu add top custom external --label "Project" --url "gemini://example.org/" +``` + +Use the menu in content: + +```text +{{ menu top }} +``` + +## `gemcms list` + +List project objects. + +```text +gemcms list <pages|articles|menus|widgets> +``` + +Output: + +| Target | Output format | +| --- | --- | +| `pages` | `slug<TAB>title` | +| `articles` | `date<TAB>section<TAB>slug<TAB>title` | +| `menus` | `name<TAB>N items` | +| `widgets` | `name<TAB>type` | + +Examples: + +```bash +gemcms list pages +gemcms list articles +gemcms list menus +gemcms list widgets +``` + +## `gemcms status` + +Print a project summary. + +```text +gemcms status +``` + +Includes: + +- capsule root +- title +- host +- page, article, and draft counts +- menu, section, and widget counts +- number of generated public files +- health summary + +## `gemcms health` + +Print only health status and issues. + +```text +gemcms health +``` + +Returns an error exit when errors are present. Warnings are printed but do not +fail the command. + +## `gemcms build` + +Generate Gemtext output into `public/`. + +```text +gemcms build +``` + +Build behavior: + +- Deletes and recreates `public/`. +- Copies files from `assets/` into `public/`. +- Skips draft documents. +- Writes pages as `/<slug>.gmi`, with `index` mapped to `/index.gmi`. +- Writes articles as `/<section>/<slug>.gmi`. +- Generates `/index.gmi` if no `index` page exists. +- Generates section indexes as `/<section>/index.gmi`. +- Expands build-time blocks: + - `{{ menu name }}` + - `{{ widget name }}` + +## `gemcms check` + +Validate common capsule problems. + +```text +gemcms check +``` + +Checks include: + +- missing capsule title +- missing content documents +- missing index page warning +- missing slugs +- duplicate output paths +- broken or suspicious local Gemtext links +- empty menu labels or URLs +- missing widget type +- invalid recent widget section + +The command prints `OK` when no issues are found. It returns an error exit when +errors are present. + +## Capsule Layout + +```text +capsule.toml +content/ + pages/ + articles/ +assets/ +site/ + menus/ + sections/ + widgets/ +public/ +``` + +## Content Frontmatter + +Gemtext files use TOML-like frontmatter: + +```text ++++ +title = "Hello Gemini" +type = "article" +slug = "hello-gemini" +date = "2026-07-07" +section = "articles" +tags = ["gemini", "capsule"] +draft = true ++++ + +# Hello Gemini +``` + +Imported Markdown can also use simple YAML-style frontmatter: + +```text +--- +title: Hello Gemini +tags: gemini, capsule +--- + +# Hello Gemini +``` + +Markdown imports are converted to Gemtext before being stored. |
