feat(engine): add tag pages, archive, and related posts#127
Merged
Conversation
Add GET /tags (all tags with post counts, sorted by count then name) and
GET /tags/{tag} (case-insensitive listing; unknown tag renders empty, not
404). Drafts follow the same is_admin gating as /posts. Tag chips on post
cards and detail pages now link to their tag pages, and a Tags nav link is
added across all three bundled themes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add GET /archive rendering all posts grouped by year then month, newest first, as a compact title plus date list with no excerpts. Dateless posts collect into a trailing Undated group. Drafts follow is_admin gating. An Archive nav link and matching styles are added across all three themes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Compute 3 to 5 related posts in the post detail route, ranked by shared-tag count with date-descending tiebreaks, excluding the post itself and (for non-admins) drafts. When tag overlap is thin the list tops up with the most recent posts so readers always get suggestions. Rendered via a shared _related.html partial included and styled across all three themes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds three discovery/navigation features to SquishMark—tag browsing, a date-based archive, and “related posts” suggestions—implemented as new routes plus reusable “pure helper” functions in the content service layer, with cross-theme support via the theme loader’s default-theme fallback.
Changes:
- Add
/tagsand/tags/{tag}routes, plus default templates for tag index and tag listings (styled across all bundled themes). - Add
/archiveroute with default archive template, grouping posts by year/month with a trailing “Undated” group. - Add “related posts” computation and render it on post pages via a shared
_related.htmlpartial; plumbrelated_poststhroughThemeEngine.render_post.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| themes/terminal/static/css/style.css | Adds tag/archive/related-posts styles for terminal theme. |
| themes/terminal/post.html | Turns tags into links; includes shared related-posts partial. |
| themes/terminal/index.html | Turns tags into links on index listing. |
| themes/terminal/base.html | Adds Tags/Archive nav links. |
| themes/default/tags.html | New tags index template. |
| themes/default/tag.html | New tag listing template (compact listing). |
| themes/default/static/style.css | Adds shared styles for tag/archive/related-posts. |
| themes/default/post.html | Turns tags into links; includes related-posts partial. |
| themes/default/index.html | Turns tags into links on index listing. |
| themes/default/base.html | Adds Tags/Archive nav links. |
| themes/default/archive.html | New archive page template. |
| themes/default/_related.html | New shared related-posts partial. |
| themes/blue-tech/static/style.css | Adds tag/archive/related-posts styles for blue-tech theme. |
| themes/blue-tech/post.html | Turns tags into links; includes related-posts partial. |
| themes/blue-tech/index.html | Turns tags into links on index listing. |
| themes/blue-tech/base.html | Adds Tags/Archive nav links. |
| tests/test_tags.py | Unit + cross-theme render tests for tag index/listing templates. |
| tests/test_routes_tags.py | Integration tests for /tags and /tags/{tag} (incl. draft gating). |
| tests/test_routes_posts.py | Integration test asserting related-posts section appears on post pages. |
| tests/test_routes_archive.py | Integration tests for /archive (incl. undated + draft gating). |
| tests/test_related.py | Unit + cross-theme render tests for related-posts computation/partial. |
| tests/test_archive.py | Unit + cross-theme render tests for archive grouping/template. |
| src/squishmark/services/theme/engine.py | Adds related_posts plumbing into render_post() context. |
| src/squishmark/services/content.py | Adds helpers: build_tag_index, posts_for_tag, build_archive, build_related_posts. |
| src/squishmark/routers/tags.py | New tags routes rendering tags.html / tag.html. |
| src/squishmark/routers/posts.py | Computes related posts and passes them into render_post(). |
| src/squishmark/routers/archive.py | New archive route rendering archive.html. |
| src/squishmark/main.py | Registers new tags and archive routers. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #10
Three discovery features, each as its own commit:
Shared templates live only in themes/default and inherit each theme's base via the loader fallback (no per-theme template copies needed); all three themes got matching CSS, linked tag chips, and Tags/Archive nav entries. Pure helpers (build_tag_index, posts_for_tag, build_archive, build_related_posts) in services/content.py mirror build_series_context and read the cached content layer.
Tests: 487 total (72 new) covering tag grouping/casing, draft gating, archive grouping and undated handling, related ranking/tiebreak/fallback/self-exclusion, plus cross-theme render tests.
Browser-verified on all three themes: tags index, tag listing (including case variants and unknown tags), archive, related section, nav links.
🤖 Generated with Claude Code