Add tracked and freeform tag editing
Deploy production / deploy (push) Successful in 4s

This commit is contained in:
2026-08-13 15:56:02 -07:00
parent 841c213087
commit 6c762c3b33
8 changed files with 742 additions and 78 deletions
+36 -17
View File
@@ -65,7 +65,7 @@ modify trusted site models, templates, scripts, or content.
```text
Labyricorn.lektorproject Lektor project definition
content/ Editable site content (`contents.lr` files)
content/tags/ Controlled tag vocabulary and dedicated tag routes
content/tags/ Tracked tag registry and dedicated tag routes
models/ Lektor content models
templates/ Jinja templates
assets/static/ CSS, filtering JavaScript, favicon, and static assets
@@ -114,9 +114,9 @@ source-controlled.
## Tags and filtering workflow
`content/tags/` is the single source of truth for the controlled tag
vocabulary. Each child directory is a normal Lektor record whose directory name
is the canonical lowercase, hyphenated slug used in entry data and URLs:
`content/tags/` is the tracked tag registry. Each child directory is a normal
Lektor record whose directory name is the canonical lowercase, hyphenated slug
used in entry data and URLs:
```text
content/tags/deployment/contents.lr -> /tags/deployment/
@@ -130,19 +130,21 @@ The tag record supplies the editor label and public description:
---
summary: Build, release, rollout, verification, and rollback workflows.
The entry model reads its checkbox choices directly from these records. Blog
entries and articles store the selected slugs as a comma-separated `tags`
value:
Blog entries and articles store all tag slugs in one comma-separated `tags`
value. The entry model reads its tracked checkbox choices from the registry,
while the focused entry editors also accept arbitrary additional tags:
```text
tags: lektor, deployment, operations
```
To add a tag, create its `content/tags/<slug>/contents.lr` record, run a build,
and then select it on the relevant entries. Do not add a slug directly to an
entry before its tag record exists. To rename or retire a tag, update every
referencing entry deliberately and verify that no old slug remains before
renaming or removing its record.
A tag with a matching registry record is tracked: it links to a dedicated tag
page and participates in tag discovery. A tag without a matching record remains
visible using the existing nonlinked presentation but is excluded from tracked
discovery. Tracking an already-used freeform slug, or untracking an existing
slug, changes that behavior on the next build without rewriting content
entries. Slug renaming is different: it can require deliberately updating every
reference and is not provided by the tag editor.
`/tags/` lists every approved tag and counts its usage across projects, project
devlog entries, blog entries, and articles. Dedicated tag URLs combine matching
@@ -165,8 +167,8 @@ After taxonomy or filtering changes:
1. Run `python scripts/build_with_projects.py --output-path build`.
2. Verify `/tags/`, at least one dedicated tag URL, the three top-level section
listings, and a project devlog index.
3. Confirm tag counts cover projects, devlog entries, blog entries, and
articles; every stored entry slug has a matching tag record; and unapproved
3. Confirm tracked-tag counts cover projects, devlog entries, blog entries, and
articles; freeform entry tags remain visible but unlinked; and unapproved
remote labels are not counted.
4. Test filtering with JavaScript enabled and confirm tag links remain usable
without JavaScript.
@@ -298,9 +300,10 @@ run:
python scripts/blog_editor.py
```
The editor uses Tkinter from the Python standard library. It reads the approved
tag choices from `content/tags/`, writes normal `contents.lr` records to the
working tree, and can delete a loaded entry after explicit confirmation. Entry
The editor uses Tkinter from the Python standard library. It presents tracked
tag choices from `content/tags/`, accepts normalized additional/freeform tags,
writes normal `contents.lr` records to the working tree, and can delete a
loaded entry after explicit confirmation. Entry
deletion removes its complete record directory, including attachments, so the
confirmation identifies additional files before proceeding. The editor does
not commit, push, build, or deploy changes. Review saved or deleted records with
@@ -314,6 +317,20 @@ attachment that the existing narration player recognizes. It uses a fixed
confirmation. If `ffmpeg` is unavailable or conversion fails, the existing
narration attachment is left unchanged.
### Local tracked tag editor
To create, edit, or untrack records in the tracked tag registry, run:
```bash
python scripts/tag_editor.py
```
The editor manages only `content/tags/<slug>/contents.lr`. Creating a tracked
record does not rewrite existing content that already uses the slug. Untracking
requires confirmation, removes only that tracked record, and leaves all tag
values in blog, article, project, and devlog content untouched. Display names
and summaries can be edited, but slugs cannot be renamed in this editor.
### Local article editor
For a focused desktop form that creates and edits records under
@@ -327,6 +344,8 @@ The article editor follows the existing cover convention: a first Markdown
image referencing an article-local `cover-image.png` or `cover-image.jpg`.
Choose a PNG, JPG, or JPEG in the editor and it is copied beside `contents.lr`
with that canonical name. Replacing or removing a cover requires confirmation.
Tracked tags are selected from `content/tags/`; arbitrary additional tags may
be entered without creating tracked records.
The editor does not commit, push, build, or deploy changes; review all working
tree changes with the routine content workflow above.