diff --git a/README.md b/README.md index 13f9e43..066a4c2 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Route paths are configuration, not files. The layer's page components live in `a ## Features - **Post list** (`journal-index`): paginated with `?page=N`, or `//N` when vue-seo-layer's `seo.pagination.form` is `path`. A non-numeric page or a page past the last one answers 404. -- **Post** (`journal-post`): title, date, reading time, categories, author, featured image, body, previous and next links, and related posts. When the API returns no related posts (a post without a category), the latest posts are shown instead. +- **Post** (`journal-post`): title, date, reading time, categories, author, featured image, body, previous and next links, and related posts. When the API returns no related posts (a post without a category), the latest posts are shown instead. With the Journal's opt-in `golem15.journal.related_mode: scored`, the related posts are the Journal's ranked ones and the previous and next links are the post's neighbours within its first category (`previous_in_category`, `next_in_category`, server-rendered links with the title in the anchor text); without them, the site-wide `previous_post` and `next_post`. - **Category** (`journal-category`): name, description and the category's rich HTML content (the pillar text, on page 1 only; the description shows on every page) above its posts. Categories are always requested with `include_empty=1`, so a category without posts still has a page. An unknown category answers 404, which makes the route safe as a root-level catch-all such as `/:category`. - **Tag** (`journal-tag`) and **author** (`journal-author`) pages. An author resolves by author slug, or by login once the author has a published post; a login URL sets the canonical to the slug URL. Post meta links to the author by `author.slug` (sm-journal-plugin v0.3.1+), falling back to the login on older APIs. - **Search** (`journal-search`, opt-in): a results page for `?q=` and the `JournalSearchBox` header component with suggestions as the visitor types. Off until the app sets `journal.routes.search`. See [Search](#search). diff --git a/app/journal-pages/PostPage.vue b/app/journal-pages/PostPage.vue index b41aa7a..d706379 100644 --- a/app/journal-pages/PostPage.vue +++ b/app/journal-pages/PostPage.vue @@ -13,7 +13,7 @@ // The head comes from the CMS through vue-seo-layer; the post's own title, // excerpt and featured image apply only while there is no CMS answer. import { cmsHeadPresent, journalPostTitleTag, journalSiteOrigin, postSeoMeta } from '../utils/seo.ts' -import { demotesH1, toPostView } from '../utils/postView.ts' +import { demotesH1, postNeighbours, toPostView } from '../utils/postView.ts' import { journalBreadcrumbsOn, toListPost } from '../utils/view.ts' import type { JournalModuleOptions } from '../utils/types.ts' @@ -65,6 +65,9 @@ useSeoMeta({ const titleTag = computed(() => journalPostTitleTag(cfg.postTitleTag, post.value?.content_h1_to_h2)) const demoteH1 = computed(() => demotesH1(post.value)) const crumbs = journalBreadcrumbsOn(cfg.breadcrumbs) +// previous_in_category / next_in_category (the Journal's opt-in scored +// mode) win over the site-wide neighbours when the Journal answers one. +const siblings = computed(() => (post.value ? postNeighbours(post.value) : { previous: null, next: null, inCategory: false }))