Color mode

Related Posts

Build-time "related notes" navigation. For every published entry, the plugin ranks the other entries in the content manifest and contributes a related-posts section to the article.footer Slot. No client-side JavaScript is required.

日本語

Overview

relatedPosts() reads the manifest's content graph and scores every other published entry against the current one:

Signal Weight Meaning
Direct link 3 The entry links to the candidate, or the candidate links to the entry
Shared tag 2 per common tag The entry and the candidate share a tag
Co-citation 1 per common target Both entries link to the same note

Candidates are sorted by score (descending), then by title, then by slug, and clamped to limit. Entries that score below minScore are dropped. When no candidate qualifies, the entry's HTML is left untouched.

The plugin contributes the section to each manifest entry's article.footer Slot. The Site decides where to render that Slot, so the section appears on generated pages and in feeds when the standard article footer is used.

Usage

ts
import { defineConfig } from "@riebeckite/core";
import { relatedPosts } from "@riebeckite/plugin-related-posts";
 
export default defineConfig({
  // ...
  plugins: [relatedPosts()],
});

Component

In addition to the automatic article.footer Slot contribution, the navigation is available as a server-rendered Hono JSX Component for placement in a Site layout. Build the entries with the existing helper and pass resolved options:

tsx
import RelatedPosts from "@riebeckite/plugin-related-posts/components";
 
<RelatedPosts entries={related} options={resolvedOptions} />;

related is the result of buildRelatedPosts() and resolvedOptions is the result of resolveRelatedPostsOptions(). Import style.css when the Plugin is not registered.

Options

Option Type Default Description
limit number 5 Maximum number of related entries
minScore number 1 Minimum score required to be listed
heading boolean true Render the <h2> heading
headingText string "Related" Heading text
className string "rb-related-posts" Root CSS class
useTags boolean true Include the shared-tag signal
useBacklinks boolean true Include the direct-link signal
ts
relatedPosts({
  limit: 8,
  minScore: 2,
  headingText: "Related notes",
});

Output

html
<nav class="rb-related-posts" data-related-posts>
  <h2 class="rb-related-posts__heading">Related</h2>
  <ul>
    <li class="rb-related-posts__item">
      <a class="rb-related-posts__link" href="/notes/example" data-related-score="5">Example Note</a>
    </li>
  </ul>
</nav>

Style

The package ships style.css. Register it like any other plugin stylesheet:

ts
import "@riebeckite/plugin-related-posts/style.css";

Exports

  • relatedPosts(options?) — plugin factory
  • relatedPostsPlugin — alias of relatedPosts
  • resolveRelatedPostsOptions(options?) — apply option defaults
  • buildRelatedPosts({ manifest, entry, options, config? }) — rank related entries
  • renderRelatedPosts(entries, options) — render the navigation HTML
  • RelatedPosts and @riebeckite/plugin-related-posts/components — Hono JSX Component
  • Types: RelatedPostsOptions, ResolvedRelatedPostsOptions, RelatedPostsEntry

Limitations

  • Ranking is fixed at build time. A full rebuild always recomputes correctly.
  • Only tags, direct links, and co-citations are considered. Reading time, recency, and folders are intentionally ignored to keep ranking deterministic.

See also

History

1 changesCollapseExpand
1 + <!-- Generated from packages/plugins/related-posts/README.md. Do not edit this page directly; edit the package README and run `pnpm docs:sync`. -->
2 +
3 + # Related Posts
4 +
5 + Build-time "related notes" navigation. For every published entry, the plugin
6 + ranks the other entries in the content manifest and contributes a related-posts
7 + section to the `article.footer` Slot. No client-side JavaScript is required.
8 +
9 + [日本語](./related-posts.md)
10 +
11 + ## Overview
12 +
13 + `relatedPosts()` reads the manifest's content graph and scores every other
14 + published entry against the current one:
15 +
16 + | Signal | Weight | Meaning |
17 + | ------ | ------ | ------- |
18 + | Direct link | 3 | The entry links to the candidate, or the candidate links to the entry |
19 + | Shared tag | 2 per common tag | The entry and the candidate share a tag |
20 + | Co-citation | 1 per common target | Both entries link to the same note |
21 +
22 + Candidates are sorted by score (descending), then by title, then by slug, and
23 + clamped to `limit`. Entries that score below `minScore` are dropped. When no
24 + candidate qualifies, the entry's HTML is left untouched.
25 +
26 + The plugin contributes the section to each manifest entry's `article.footer`
27 + Slot. The Site decides where to render that Slot, so the section appears on
28 + generated pages and in feeds when the standard article footer is used.
29 +
30 + ## Usage
31 +
32 + ```ts
33 + import { defineConfig } from "@riebeckite/core";
34 + import { relatedPosts } from "@riebeckite/plugin-related-posts";
35 +
36 + export default defineConfig({
37 + // ...
38 + plugins: [relatedPosts()],
39 + });
40 + ```
41 +
42 + ## Component
43 +
44 + In addition to the automatic `article.footer` Slot contribution, the navigation
45 + is available as a server-rendered Hono JSX Component for placement in a Site
46 + layout. Build the entries with the existing helper and pass resolved options:
47 +
48 + ```tsx
49 + import RelatedPosts from "@riebeckite/plugin-related-posts/components";
50 +
51 + <RelatedPosts entries={related} options={resolvedOptions} />;
52 + ```
53 +
54 + `related` is the result of `buildRelatedPosts()` and `resolvedOptions` is the
55 + result of `resolveRelatedPostsOptions()`. Import `style.css` when the Plugin is
56 + not registered.
57 +
58 + ## Options
59 +
60 + | Option | Type | Default | Description |
61 + | ------ | ---- | ------- | ----------- |
62 + | `limit` | `number` | `5` | Maximum number of related entries |
63 + | `minScore` | `number` | `1` | Minimum score required to be listed |
64 + | `heading` | `boolean` | `true` | Render the `<h2>` heading |
65 + | `headingText` | `string` | `"Related"` | Heading text |
66 + | `className` | `string` | `"rb-related-posts"` | Root CSS class |
67 + | `useTags` | `boolean` | `true` | Include the shared-tag signal |
68 + | `useBacklinks` | `boolean` | `true` | Include the direct-link signal |
69 +
70 + ```ts
71 + relatedPosts({
72 + limit: 8,
73 + minScore: 2,
74 + headingText: "Related notes",
75 + });
76 + ```
77 +
78 + ## Output
79 +
80 + ```html
81 + <nav class="rb-related-posts" data-related-posts>
82 + <h2 class="rb-related-posts__heading">Related</h2>
83 + <ul>
84 + <li class="rb-related-posts__item">
85 + <a class="rb-related-posts__link" href="/notes/example" data-related-score="5">Example Note</a>
86 + </li>
87 + </ul>
88 + </nav>
89 + ```
90 +
91 + ## Style
92 +
93 + The package ships `style.css`. Register it like any other plugin stylesheet:
94 +
95 + ```ts
96 + import "@riebeckite/plugin-related-posts/style.css";
97 + ```
98 +
99 + ## Exports
100 +
101 + - `relatedPosts(options?)` — plugin factory
102 + - `relatedPostsPlugin` — alias of `relatedPosts`
103 + - `resolveRelatedPostsOptions(options?)` — apply option defaults
104 + - `buildRelatedPosts({ manifest, entry, options, config? })` — rank related entries
105 + - `renderRelatedPosts(entries, options)` — render the navigation HTML
106 + - `RelatedPosts` and `@riebeckite/plugin-related-posts/components` — Hono JSX Component
107 + - Types: `RelatedPostsOptions`, `ResolvedRelatedPostsOptions`, `RelatedPostsEntry`
108 +
109 + ## Limitations
110 +
111 + - Ranking is fixed at build time. A full rebuild always recomputes correctly.
112 + - Only tags, direct links, and co-citations are considered. Reading time,
113 + recency, and folders are intentionally ignored to keep ranking deterministic.
114 +
115 + ## See also
116 +
117 + - [Plugin guide](../reference/plugin-api.en.md)
118 +