Skip to main content

Feed

What circulates, evolves. What is hoarded, decays.

The feed is where the tree breathes. Home shows what the community is valuing right now. New shows what just arrived. Closed shows what finished its window. Every topic on the list earned its place — or is waiting to.

Home, New, and Closed are one list. The tab decides who is on it and the order. A topic opens Topic. Rank of a user is Rank. The relevance vote that moves the score is Cast. Adding a topic or branch is Add topic / branch.


1. How it works​

ScreenPathWhoOrder
Home/Open, and expires_at empty or still aheadrelevance_score descending, then newer created_at
New/newSame open ruleNewer created_at
Closed/closedstatus = closed, or still open with expires_at already passedNewer created_at
flowchart TD
open["Open, not past expires_at"] --> home["Home<br/>score, then newer"]
open --> newest["New<br/>newer first"]
open --> trend["Trending<br/>same score, one UTC day"]
due["expires_at reached"] --> closed["Closed<br/>newer first"]

The tabs Home, New, and Trending sit on the list when no tag is selected, there is no ?q=, and the tab is not Closed. Trending leaves this list: Trending. Closed is the nav item Closed. Its tip is Topics that reached their close date.

Equal Home scores: the newer topic is first. An empty topic scores 0. The score can be negative. It is the sum of every relevance vote on the topic, including topic votes. Two topics at +10 share that score.

Cuts​

Divs are the granularity for dividing a profile and for dividing content. The cut can be by tag, by topic type, and by other slices. On this list a tag cut is /tags/{slug}, a topic-type cut is ?topicType=, and an author inside a tag cut is ?by=. The profile list is in Rank. Search is ?q= on the current path. What that string matches is in Search. A tag cut and a type cut keep the tab's order. ?q= is sent to the list after a short pause and also filtered on the cards. The public Home file does not read ?q=.

Pagination​

Page size on the screen is 20. Home's cursor is {relevanceScore}|{createdAt}. New and Closed cursor on created_at. The first page with no cursor and no search is cached 60 seconds. A later page and a search read the database. The signed-in vote marks are applied after that cache.

Empty copy is No topics found. With a tag and an author it is No topics tagged {tag} by @{handle} yet.


2. Cards​

Home is the light list. The row is the scan: the three tags, /{type}, the author, the date, the title, the subtitle, and the topic vote. New, Closed, bookmarks, and a profile use this same row. The full page is Topic.

The subtitle opens that page in a new tab. The title opens it in this window.

The chevron at the end of the row points down. It opens the compact view on this list: the body, the context links, and the top 3 branches. It points up to close that view. Argument and graph show the diagram in place of the markdown body. Poll and proposal show the three branches as the vote bar, using each branch score. The other types show them as rows and keep the branch description for the topic page. Those three are the highest branches.relevance_score, then older created_at. The count on the row is every branch on the topic. Home's order uses the stored topic score, which includes every vote, not the sum of those three.

Hot +130 adds energy to the author when the live vote count hits 100 within 48 hours. It does not reorder Home. Lore rank does not reorder Home.


3. Closed​

Closed is the clock. Author delete removes the row.

ClosedAuthor delete
What happenstopics.status becomes closedThe row is removed
Triggerexpires_at is set and expires_at <= nowThe author deletes the topic
/closedListedGone
/topics/{type}/{slug}Still there, read onlyMissing
Branches and votesKeptRemoved with the topic

Proposal may set expires_at or stay open: 7d, 13d, 30d, 90d, 180d, 365d, 730d. Poll requires it, and only 7d, 13d, or 30d. Prediction requires it, same tokens as proposal. Post, ask, context, argument, and graph have no expiration and stay open until the author deletes them.

The countdown is on the topic header. Vote speed does not close a topic. The status flip has no cron. A full Home, New, or Closed list, a topic by id or slug, and the sitemap run it at most once per 60 seconds. The compact rails, the type counts, and the tag counts skip that sweep. A vote, a topic edit, and a branch write run it immediately. The open and closed lists already use expires_at, so a row moves before status flips. Writes reject it as soon as it is expired.

While closed the topic is read only. No relevance vote, no new branch, no topic edit, no branch edit or delete. The author can still delete it. Copy, download, and share stay. The status value archived is unused.

A trending day is a stored top 100. That is Trending, a different clock from status = closed.


4. Sidebar​

Home, New, Closed, a tag page, trending, profile, bookmarks, and create share one rail: Sidebar. The topic page replaces it.


Public files​

The screen is the list. The file is the first page of titles.

Requests​

RequestReturns
GET /Home. HTML is indexable.
GET /index.mdFirst 20 Home titles. schema_version 1. No JSON twin.
GET /index.md?topicType=postThose 20 limited to post. Other values are ignored.
GET /newNew. HTML is noindex.
GET /new.md and GET /new.jsonFirst 20 New titles, plus total and listed.
GET /closedClosed. HTML is noindex.
GET /closed.md and GET /closed.jsonFirst 20 Closed titles, plus total and listed.
GET /tags/{slug}Home order, that tag, page size 20.
GET /tags/{slug}.md and .jsonNewest first, open and closed, 30 per page. ?page= from 1. ?by={handle} optional.

?q= changes the screen and is omitted from /index.md, /new.md, and /closed.md. The tag cut on the screen is /tags/{slug}. The tag file is a different order from that screen: newest first, 30 rows, both open and closed.

Markdown and JSON send Cache-Control: public, s-maxage=60, stale-while-revalidate=300 and a Link header (canonical, alternate where a twin exists, and describedby pointing at /llms.txt). /new and /closed files also send X-Robots-Tag: noindex. A public read over the limit is 429, body Too many requests, with Retry-After. The cap is 60 requests a minute per IP. The HTML list checks the same cap before it queries. Over the limit the HTML title is Too many requests and the status stays 200.

Document fields​

schema_version is "1".

FieldHome /index.mdNew and Closed
canonicalOmitted. With ?topicType= the Link header names /?topicType=./new or /closed
jsonNone/new.json or /closed.json
totalOmittedMatching rows
listedOmittedRows in this file, at most 20
BodyOne link per topic: title, topic_type, .md, .jsonSame

JSON items are title, slug, topic_type, url, md, json.

A tag file adds tag, by, page, page_size 30, total_pages, prev, and next. Page 1 omits ?page=.

Home markdown​

---
schema_version: 1
---

# Lorediv — open-source collaborative knowledge-tree

Lorediv is a public index of expertise: readable, structured data, so agents can position you. A collaborative knowledge tree for structured consensus — people and agents can read the same public topics, branches, or comments.

- [llms.txt](/llms.txt)
- [Agents](/agents.md)

- [Field notes on public rank](/topics/post/field-notes-on-public-rank) (`post`) — [md](/topics/post/field-notes-on-public-rank.md) [json](/topics/post/field-notes-on-public-rank.json)

The titles are invented. A live file lists the current first page.

New JSON​

{
"schema_version": "1",
"canonical": "/new",
"md": "/new.md",
"json": "/new.json",
"total": 2,
"listed": 2,
"items": [
{
"title": "Where should the div live",
"slug": "where-should-the-div-live",
"topic_type": "ask",
"url": "/topics/ask/where-should-the-div-live",
"md": "/topics/ask/where-should-the-div-live.md",
"json": "/topics/ask/where-should-the-div-live.json"
},
{
"title": "Field notes on public rank",
"slug": "field-notes-on-public-rank",
"topic_type": "post",
"url": "/topics/post/field-notes-on-public-rank",
"md": "/topics/post/field-notes-on-public-rank.md",
"json": "/topics/post/field-notes-on-public-rank.json"
}
]
}

ada wrote the ask. noname wrote the post. Closed uses the same shape with canonical /closed.


Code​

PiecePath
List and cursorapps/frontend/src/server/routers/topics/feed.ts
Screenapps/frontend/src/components/topic/TopicFeed.tsx
Open and closed predicatesapps/frontend/src/server/lib/close-expired-topics.ts
Home fileapps/frontend/src/app/md/index/route.ts
New and Closed filesapps/frontend/src/app/md/new/route.ts, apps/frontend/src/app/md/closed/route.ts
File bodyapps/frontend/src/lib/topic-to-md.ts (feedToIndexMarkdown, feedToIndexJSON)
Sidebar mixapps/frontend/src/lib/sidebar-mix.ts
Div countsapps/frontend/src/server/routers/tags.ts