From 5aeb2d05dd286ea9786d542706f0d968f791dcdc Mon Sep 17 00:00:00 2001 From: Sven Date: Thu, 9 Apr 2026 21:09:46 +0200 Subject: [PATCH] docs: tag entry autocomplete design spec --- .../specs/2026-04-09-tag-search-design.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-09-tag-search-design.md diff --git a/docs/superpowers/specs/2026-04-09-tag-search-design.md b/docs/superpowers/specs/2026-04-09-tag-search-design.md new file mode 100644 index 00000000..5d452763 --- /dev/null +++ b/docs/superpowers/specs/2026-04-09-tag-search-design.md @@ -0,0 +1,85 @@ +# Tag Entry Autocomplete — Design Spec + +**Date:** 2026-04-09 +**Status:** Approved + +## Problem + +The tag/category input in the Indiekit post compose form is a plain text field with no suggestions. The `q=category` Micropub endpoint returns an empty array because `publication.categories` is not configured — tags only exist in the `posts` MongoDB collection as `properties.category` values. + +## Solution + +Two patch scripts that wire up autocomplete end-to-end with no new endpoints and no changes to the Indiekit config. + +--- + +## Patch 1 — Backend: `patch-micropub-category-from-posts.mjs` + +**Target:** `node_modules/@indiekit/endpoint-micropub/lib/controllers/query.js` + +**What it does:** + +Inserts a `case "categories":` block before the existing `default:` case in `queryController`. When `q=category` is requested, instead of falling through to `config.categories` (which is empty), this case: + +1. Calls `postsCollection.distinct("properties.category")` to get every unique tag used across all published posts. +2. Filters out falsy values (`Boolean` filter) and sorts alphabetically. +3. Passes the result through the existing `queryConfig(cats, { filter, limit, offset })` so the `filter=` query param works for substring matching. +4. Returns `{ categories: [...] }`. + +If `postsCollection` is not available, returns an empty array gracefully. + +**Example request/response:** +``` +GET /micropub?q=category&filter=pho +→ { "categories": ["photography"] } +``` + +--- + +## Patch 2 — Frontend: `patch-tag-input-autocomplete.mjs` + +**Target:** `node_modules/@indiekit/frontend/components/tag-input/index.js` + +**What it does:** + +After the `$tagInputInput` reference is obtained inside `TagInputFieldComponent.connectedCallback()`, appends the following behaviour: + +1. Creates a `` element and appends it to the component. The uid is derived from the input's `name` attribute to be stable per field. +2. Sets `$tagInputInput.setAttribute("list", datalistId)` — the browser's native datalist autocomplete now applies to the text field. +3. Adds a debounced (300ms) `input` event listener: + - If the current value is ≥ 1 char, fetches `GET /micropub?q=category&filter=` (same-origin, session cookie included by default). + - Replaces datalist `