Phase 8 Artifacts — Agent Dashboard + Search + Community
Status: Draft Last Updated: August 29, 2026 Tags: agentic, dashboard, search, bookmarks, comments, rss
Summary
Three artifacts from Phase 8:
- Agent Dashboard — real-time KPI cards for infrastructure status
- Search / Related Content — tag chips + related post links
- Comments / Bookmarks / RSS — brief design for community features
1. Agent Dashboard — Real-Time Status Design
Route
/admin/dashboard (admin/owner only; renders inside the admin layout)
KPI Cards (top row)
| Card | Metric | Source | Color |
|---|---|---|---|
| Infrastructure | 3/3 healthy | k8s API: kubectl get nodes |
Green |
| Deploys This Week | N (count of deploy workflow runs) | GitHub/Forgejo API | Blue |
| Active Tickets | N open | Forgejo Issues API | Amber |
| KB Sync Status | Synced / Behind | git log --oneline -1 |
Green/Red |
| Uptime (30d) | 99.X% | Uptime Kuma API | Green/Amber/Red |
| Mailgun Delivery Rate | XX% (delivered / sent) | Mailgun stats API | Green/Amber |
Card component sketch
┌──────────────────────────┐
│ Infrastructure ● │ ← green dot = healthy
│ 3 / 3 nodes healthy │
│ Updated 14s ago │
└──────────────────────────┘
┌──────────────────────────┐
│ Deploys This Week 📦 │
│ 4 deploys │
│ Last: 2h ago │
└──────────────────────────┘
Implementation notes
- Poll interval: 30s for infra status, 5m for ticket/deploy counts
- Use SWR or React Query with
refreshInterval - Status dots: green (< 60s stale), amber (60s–5m), red (> 5m or error)
- If the infra API is unreachable, show "Unknown" in red with a refresh button
Prisma model additions needed
model Deployment {
id String @id @default(cuid())
sha String
branch String
status String // "pending" | "running" | "success" | "failed"
triggeredAt DateTime @default(now())
finishedAt DateTime?
environment String // "staging" | "production"
}
2. Search / Related Content — Tag + Related Links
Tag chips (below post title / on blog listing cards)
Tags: [Infrastructure] [Self-Hosting] [Privacy]
- Each tag is a link to
/blog?tag=infrastructure - Tags rendered from
PostTag → Tagrelation - Max 6 visible; "+ N more" overflow on blog cards
- On mobile: horizontal scroll chip row
Related posts section (bottom of post template)
Related:
→ Building a Self-Hosted Email Server (same tags: 3)
→ Why I Migrated Away from the Cloud (same author: 1)
→ The Philosophy of Self-Sufficiency (same category: 1)
Algorithm (simple, no ML):
-- Related by shared tag count, then recency
SELECT p.id, p.title, p.slug,
COUNT(pt_shared.tag_id) AS shared_tags
FROM Post p
JOIN PostTag pt_shared ON pt_shared.post_id = p.id
WHERE pt_shared.post_id != :currentPostId
AND pt_shared.tag_id IN (
SELECT tag_id FROM PostTag WHERE post_id = :currentPostId
)
AND p.status = 'PUBLISHED'
GROUP BY p.id
ORDER BY shared_tags DESC, p.publishedAt DESC
LIMIT 5;
Frontend component:
function RelatedPosts({ currentPostId, tags }: { currentPostId: string; tags: Tag[] }) {
// Fetches /api/posts/related?postId=...&tags=...
// Renders <RelatedPostCard> list
}
3. Comments / Bookmarks / RSS — Design Brief
Comments
Decision: Implement threaded comments (post author can moderate).
model Comment {
id String @id @default(cuid())
postId String
post Post @relation(fields: [postId], references: [id])
authorId String? // null = guest comment
author User? @relation(fields: [authorId], references: [id])
authorName String // guest display name
authorEmail String // guest email (not shown publicly)
body String
status String @default("PENDING") // PENDING | APPROVED | SPAM | DELETED
parentId String? // null = top-level
parent Comment? @relation("CommentReplies", fields: [parentId], references: [id])
replies Comment[] @relation("CommentReplies")
createdAt DateTime @default(now())
}
Endpoints:
POST /api/posts/:id/comments— create (guest or authenticated)GET /api/posts/:id/comments— list approvedDELETE /api/comments/:id— soft-delete (author or admin)PATCH /api/comments/:id— moderate (admin: APPROVED/SPAM)
UI states: Loading skeleton, empty ("Be the first to comment"), thread list with reply button, comment form (name/email/body for guests), success toast.
Bookmarks
model Bookmark {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
postId String
post Post @relation(fields: [postId], references: [id])
@@unique([userId, postId])
createdAt DateTime @default(now())
}
Endpoints:
POST /api/bookmarks—{ postId }toggle (upsert)GET /api/bookmarks— list user's bookmarksDELETE /api/bookmarks/:postId— remove
UI: Bookmark icon on post cards and post template. Filled = bookmarked. Requires auth; prompts login if not authenticated.
RSS Feed
Route: /feed.xml
Generated at build time (static) or server-side on request (dynamic for up-to-date counts):
// src/routes/feed.xml.tsx
// Content-Type: application/rss+xml
// Returns <rss><channel> with last 20 published posts
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>fogserv.cloud</title>
<link>https://fogserv.cloud</link>
<description>Self-hosted infrastructure, agentic automation, and democratic technology.</description>
<language>en-us</language>
<lastBuildDate>Fri, 29 Aug 2026 12:00:00 +0000</lastBuildDate>
<atom:link href="https://fogserv.cloud/feed.xml" rel="self" type="application/rss+xml"/>
<!-- <item> repeated per post -->
</channel>
</rss>
Implementation: TanStack Router supports file-based routes; create src/routes/feed.xml.tsx that renders XML. Add <link rel="alternate" type="application/rss+xml"> to the HTML <head>.
Next Steps / Ops Actions
- Dashboard: Add
Deploymentmodel toprisma/schema.prisma. Wire Forgejo API or GitHub Actions API for deploy counts. Build<KPICard>component and<DashboardPage>in admin. - Related content: Add
GET /api/posts/relatedendpoint. Render<RelatedPosts>onPostPage. - Comments: Add
Commentmodel + migration. BuildCommentSectioncomponent withCommentFormandCommentThread. Implement moderation UI in admin. - Bookmarks: Add
Bookmarkmodel + migration. Wire bookmark toggle on post cards and post template. - RSS: Create
src/routes/feed.xml.tsxwith XML rendering. Add to<head>.
Sources & Related
kb/agentic/agentic-workflows.md— agent orchestration patternskb/agent.md— agent reference for dashboard contextkb/tasks.mdPhase 8 — all three tasks listedkb/wireframes.md— existing wireframe conventions
Change Log
- August 29, 2026 — Created Phase 8 artifacts: Agent Dashboard KPI card design with sources and polling notes, Search/Related Content tag + SQL algorithm, Comments/Bookmarks/RSS design brief with Prisma models and endpoint specs.