Hashtags, content kinds, and feed tab taxonomy.
Product and engineering plan for classifying posts with hashtags (e.g. #Imyazi, #Umwazi) so Lola can group content and show feed tabs for related material. Builds on LOLA-TAGS.md (current hashtag behaviour).
Status: Documented — not implemented yet.
Feature plan: LOLA-FEATURE-PLAN.md → social-content-types-001, social-feed-tabs-001.
Today, #Imyazi in a post is only text. Search can find it; the app does not know “this is a news post.”
Goal: When an author uses recognized tags, capture them at publish time and use them for:
#Imyazi, #Umwazi), and later question, story, etc.#imikolwa, #Bafuliiru, …)This aligns Lola with the wider Tabula ecosystem (Imyazi as news/stories) while keeping Lola posts on feed_activities.
| Need | How tags help | |------|----------------| | News vs general chat | Type tags (#Imyazi, #Umwazi) mark what the post is | | Cultural / language discovery | Topic tags mark what it is about | | Less crowded feed | Tabs filter to one lane at a time | | Future Imyazi / FM | Structured contentKind can later sync or cross-link platforms | | Pulse & sidebar | Same taxonomy can power “what’s growing” by topic |
Important: Hashtags in the body alone are not enough. We must parse and persist recognized tags when a post is created or edited (see Capture on publish).
| Kind | Role | Examples | Drives tabs? | |------|------|----------|--------------| | Type | What the post is | #Imyazi, #Umwazi (news); later #question, #story | Primary tab lanes | | Topic | What the post is about | #Kifuliiru, #Abaandu, #umuundu, #imikolwa, #Bafuliiru | Topic filters / secondary tabs |
Authors can use one type tag (recommended) and multiple topic tags.
Single source of truth for code (sidebar, parser, composer, tabs). Names are case-insensitive at capture time; store a canonical form.
| Canonical tag | Maps to contentKind | Meaning (draft) | |---------------|----------------------|-----------------| | Imyazi | imyazi | News / current-events style post (Imyazi lane on Lola) | | Umwazi | umwazi | News (Kifuliiru label; see open decisions) |
Future type tags (not in v1): question, story, proverb, song.
| Canonical tag | Topic group (draft) | Notes | |---------------|---------------------|--------| | Kifuliiru | language | Language itself | | Abaandu | people | People / community | | umuundu | person | Individual / personal | | imikolwa | culture | Customs / culture | | Bafuliiru | community | Bafuliiru identity |
Registry file (planned): src/lib/lola-tag-registry.ts — kinds, aliases, tab mapping.
Resolve before or during implementation:
#Imyazi vs Imyazi platformimyazi tables. Cross-platform sync is a later task.#Imyazi vs #UmwazicontentKind: 'news' and one News tab; keep both spellings in the registry for authors.#Imyazi and #question appear, which wins?#MyTag stays in text only until added to registry (no contentKind change).LolaFeedFilterContext + LolaFeedStatusFilter filter moderation status (pending / approved).LolaFeedContentFilter + contentFilter state) so tabs do not mix with mod status.Reuse feed_activities.metadata (JSON), same pattern as postLocale in src/lib/post-locale.ts.
// feed_activities.metadata (extended)
{
postLocale?: 'kifuliiru' | 'sw' | 'fr' | 'en' | 'other'; // existing
tags?: string[]; // canonical topic + type tag strings, e.g. ['Imyazi', 'imikolwa']
contentKind?: string; // derived primary type: 'news' | 'question' | ... (v1: 'news' from Imyazi/Umwazi)
topicGroups?: string[]; // optional derived: ['culture', 'community']
}
```text
### Capture on publish
On **create** and **edit** (in post publish path / `CreatePost` → activity insert):
1. Run hashtag parser on post body (same rules as `PostContentWithHashtags`).
2. Normalize to canonical names (registry lookup, case-insensitive).
3. Split into **type** vs **topic** lists.
4. Set `contentKind` from first matching type tag.
5. Merge into existing `metadata` (preserve `postLocale`, images, etc.).
Planned helpers:
- `src/lib/lola-tag-parser.ts` — extract `#tokens` from text
- `src/lib/lola-tag-registry.ts` — canonical list, kind mapping
- `src/lib/lola-post-metadata.ts` — build/merge metadata blob
### v2 — optional schema
When counts, trending, and tag pages are needed:
- `tags` (id, slug, kind, label, …)
- `feed_activity_tags` (activity_id, tag_id)
See Phase C in [LOLA-TAGS.md](/lola-kifuliiru/guides/tags).
---
## Feed tabs (planned UX)
Horizontal tabs on **home** (and optionally **explore**), separate from moderation filter in the header.
### v1 tab set (draft)
| Tab id | Shows posts where | |--------|-------------------| | `all` | Everything (default) | | `news` | `metadata.contentKind === 'news'` OR tag `Imyazi` / `Umwazi` | | `culture` | topic group `culture` OR tag `imikolwa` | | `community` | tags `Bafuliiru`, `Abaandu`, or topic groups `community` / `people` | | `language` | tag `Kifuliiru` or topic group `language` |
Exact tab labels and Kifuliiru copy → `lola.feed.tabs.*` in `translations.ts`.
### Filtering behaviour
- **Client-side v1:** Filter loaded `activities` by `metadata` (fast to ship; matches current locale filter pattern).
- **Server-side v2:** Query `metadata->>contentKind` / join `feed_activity_tags` for pagination and large feeds.
Clicking a **sidebar tag chip** should eventually set the matching tab (or `?tab=news`), not only open search.
---
## Implementation phases
### Phase A — Capture (first engineering slice)
| Step | Work | |------|------| | A1 | `lola-tag-registry.ts` + `lola-tag-parser.ts` | | A2 | On publish/edit, write `metadata.tags` + `metadata.contentKind` | | A3 | Unit tests for parser + Imyazi/Umwazi → `news` | | A4 | Optional: badge on `PostCard` (“News”) when `contentKind === 'news'` |
**Exit criteria:** Post with `#Imyazi` in body has `metadata.contentKind: 'news'` after save.
### Phase B — Feed tabs
| Step | Work | |------|------| | B1 | `LolaFeedContentFilter` context (or extend filter context with separate key) | | B2 | Tab UI above feed on home | | B3 | Client filter from `metadata` | | B4 | Sidebar tags → switch tab or deep link `/?tab=culture` | | B5 | i18n for tab labels |
**Exit criteria:** **News** tab shows only posts captured as news; **All** shows everything.
### Phase C — Composer & polish
| Step | Work | |------|------| | C1 | Composer hint or chip picker for official type/topic tags | | C2 | Warn if multiple type tags | | C3 | Backfill script optional: scan existing posts, fill metadata from body hashtags |
### Phase D — Scale (later)
- Supabase tag tables, tag pages `/tags/imikolwa`, trending counts, pulse by topic.
---
## Relationship to existing features
| Feature | Relationship | |---------|----------------| | `metadata.postLocale` | Orthogonal — language of post vs type/topic of content | | `LolaFeedStatusFilter` | Keep for mod status; do not overload for content tabs | | `LOLA-TAGS.md` | Today’s hashtag render + search; this doc adds **semantics** | | Imyazi (Tabula) | Separate product; v1 tag is Lola classification only ([KIFULIIRU-FM-INTEGRATION.md](/lola-kifuliiru/guides/kifuliiru-fm) for FM `source: imyazi`) | | Right-rail tags | Same canonical list as topic tags; wire to tabs in Phase B | | Language Pulse | Unchanged in v1; future: pulse slices by `topicGroups` |
---
## Author guidance (once Phase A ships)
**News post:**
```text
#Imyazi Amakuru ma lelo…
```text
or
```text
#Umwazi …
```text
**Culture + community:**
```text
#imikolwa #Bafuliiru …
```text
Authors should use **registry spellings** (see [Canonical tag registry](#canonical-tag-registry-draft)); aliases can be added to the registry later.
---
## Key files (current vs planned)
| File | Status | |------|--------| | `src/lib/post-locale.ts` | Exists — pattern for metadata helpers | | `src/lib/lola-sidebar-tags.ts` | Exists — topic list; align with registry | | `src/components/feed/PostContentWithHashtags.tsx` | Exists — render only | | `src/components/feed/CreatePost.tsx` | Exists — publish path to extend | | `src/context/LolaFeedFilterContext.tsx` | Exists — mod filter today | | `src/lib/lola-tag-registry.ts` | **Planned** | | `src/lib/lola-tag-parser.ts` | **Planned** | | `src/lib/lola-post-metadata.ts` | **Planned** | | `src/components/lola/LolaFeedContentTabs.tsx` | **Planned** |
---
## Related docs
- [LOLA-TAGS.md](/lola-kifuliiru/guides/tags) — current hashtag behaviour and generic tag roadmap
- [LOLA-FEATURE-PLAN.md](/lola-kifuliiru/guides/feature-plan) — task IDs
- [KIFULIIRU-FM-INTEGRATION.md](/lola-kifuliiru/guides/kifuliiru-fm) — Imyazi as FM source (platform level)