fix(10): revise plans based on checker feedback
- Plan 10-02: Added explicit UserMailService wiring in Account.scala onRegister handler for activation emails when activateMode == User - Plan 10-04: Split into backend-only (models, services, admin controller) reducing from 16 to 15 files, estimated context ~50% - Plan 10-05: New plan for frontend components (Posts, Post, Categories, RelatedPosts), Wave 3 depends on 10-04 - Updated ROADMAP.md to reflect 5 plans for Phase 10
This commit is contained in:
287
.planning/phases/10-core-plugins/10-05-PLAN.md
Normal file
287
.planning/phases/10-core-plugins/10-05-PLAN.md
Normal file
@@ -0,0 +1,287 @@
|
||||
---
|
||||
phase: 10-core-plugins
|
||||
plan: 05
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on: ["10-04"]
|
||||
files_modified:
|
||||
- plugins/golem15/blog/components/Posts.scala
|
||||
- plugins/golem15/blog/components/Post.scala
|
||||
- plugins/golem15/blog/components/Categories.scala
|
||||
- plugins/golem15/blog/components/RelatedPosts.scala
|
||||
- plugins/golem15/blog/resources/views/posts/default.peb
|
||||
- plugins/golem15/blog/resources/views/posts/item.peb
|
||||
- plugins/golem15/blog/resources/views/post/default.peb
|
||||
- plugins/golem15/blog/resources/views/categories/default.peb
|
||||
- plugins/golem15/blog/resources/views/relatedposts/default.peb
|
||||
- plugins/golem15/blog/Plugin.scala
|
||||
autonomous: true
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Frontend displays post listings with pagination"
|
||||
- "Frontend displays individual post pages"
|
||||
- "Related posts shown based on shared categories/tags"
|
||||
- "Category tree/list component available for navigation"
|
||||
- "Infinite scroll works via HTMX"
|
||||
artifacts:
|
||||
- path: "plugins/golem15/blog/components/Posts.scala"
|
||||
provides: "Frontend post listing component"
|
||||
exports: ["PostsComponent", "onLoadMore"]
|
||||
- path: "plugins/golem15/blog/components/Post.scala"
|
||||
provides: "Single post display component"
|
||||
exports: ["PostComponent"]
|
||||
- path: "plugins/golem15/blog/components/Categories.scala"
|
||||
provides: "Category listing/tree component"
|
||||
exports: ["CategoriesComponent"]
|
||||
- path: "plugins/golem15/blog/components/RelatedPosts.scala"
|
||||
provides: "Related posts component"
|
||||
exports: ["RelatedPostsComponent"]
|
||||
- path: "plugins/golem15/blog/resources/views/posts/default.peb"
|
||||
provides: "Post listing template"
|
||||
contains: "hx-post"
|
||||
key_links:
|
||||
- from: "plugins/golem15/blog/components/Posts.scala"
|
||||
to: "BlogPostService"
|
||||
via: "post listing"
|
||||
pattern: "postService\\.listFrontend"
|
||||
- from: "plugins/golem15/blog/components/Post.scala"
|
||||
to: "BlogPostService"
|
||||
via: "single post lookup"
|
||||
pattern: "postService\\.findBySlug"
|
||||
- from: "plugins/golem15/blog/components/RelatedPosts.scala"
|
||||
to: "BlogPostService"
|
||||
via: "related posts query"
|
||||
pattern: "postService\\.getRelatedPosts"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create frontend components for blog display with pagination and HTMX interactions.
|
||||
|
||||
Purpose: Enable visitors to browse and read blog content, demonstrating frontend component patterns with HTMX.
|
||||
|
||||
Output: Complete Blog frontend with:
|
||||
- Posts component with pagination/infinite scroll
|
||||
- Post component for single post display with OpenGraph meta
|
||||
- Categories component for navigation
|
||||
- RelatedPosts component for content discovery
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/jin/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/jin/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/10-core-plugins/10-CONTEXT.md
|
||||
@.planning/phases/10-core-plugins/10-RESEARCH.md
|
||||
|
||||
# Prior plans in this phase
|
||||
@.planning/phases/10-core-plugins/10-03-SUMMARY.md
|
||||
@.planning/phases/10-core-plugins/10-04-SUMMARY.md
|
||||
|
||||
# Reference: Phase 3 component patterns for HTMX
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Posts and Post listing components</name>
|
||||
<files>
|
||||
plugins/golem15/blog/components/Posts.scala
|
||||
plugins/golem15/blog/components/Post.scala
|
||||
plugins/golem15/blog/resources/views/posts/default.peb
|
||||
plugins/golem15/blog/resources/views/posts/item.peb
|
||||
plugins/golem15/blog/resources/views/post/default.peb
|
||||
</files>
|
||||
<action>
|
||||
Create frontend components for blog display:
|
||||
|
||||
**Posts.scala (research Pattern 8):**
|
||||
- Extend SummerComponent trait
|
||||
- ComponentDetails: name "Posts", description "Blog post listing"
|
||||
- Property schema:
|
||||
- pageNumber: String, URL param for pagination, default "{{ :page }}"
|
||||
- categoryFilter: String, filter by category slug
|
||||
- postsPerPage: String, default "10", validation 1-100
|
||||
- noPostsMessage: String, default "No posts found."
|
||||
- sortOrder: Dropdown with BlogPost.allowedSortingOptions
|
||||
- throwNotFound: Checkbox, 404 on empty results
|
||||
- Page variables: posts (PaginatedResult), category (Option), noPostsMessage
|
||||
- onRun lifecycle:
|
||||
- Load category if categoryFilter set
|
||||
- Build PostListOptions from properties
|
||||
- Call postService.listFrontend or listByCategory
|
||||
- Handle empty results per throwNotFound
|
||||
- Set page context variables
|
||||
- onLoadMore HTMX handler:
|
||||
- Parse page number from form
|
||||
- Load next page of posts
|
||||
- Return items partial
|
||||
- Trigger "postsExhausted" when no more
|
||||
|
||||
**Post.scala component:**
|
||||
- ComponentDetails: name "Post", description "Single post display"
|
||||
- Property schema:
|
||||
- slug: String, URL param for post slug, default "{{ :slug }}"
|
||||
- notFoundMessage: String
|
||||
- Page variables: post (BlogPostWithRelations)
|
||||
- onRun lifecycle:
|
||||
- Get slug from URL
|
||||
- Call postService.findBySlug
|
||||
- 404 if not found
|
||||
- Set page context: post, author, categories, tags, readingTime
|
||||
- Set OpenGraph meta tags for social sharing
|
||||
|
||||
**Templates:**
|
||||
|
||||
**posts/default.peb (research code example):**
|
||||
```html
|
||||
<div class="blog-posts" id="posts-{{ __SELF__ }}">
|
||||
{% if posts.items is empty %}
|
||||
<div class="no-posts">{{ noPostsMessage }}</div>
|
||||
{% else %}
|
||||
<div class="posts-list">
|
||||
{% for post in posts.items %}
|
||||
{% include "posts/item" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if posts.hasNext %}
|
||||
<div class="load-more">
|
||||
<button
|
||||
hx-post="{{ componentHandler('onLoadMore') }}"
|
||||
hx-vals='{"page": {{ posts.currentPage + 1 }}}'
|
||||
hx-target="#posts-{{ __SELF__ }} .posts-list"
|
||||
hx-swap="beforeend"
|
||||
hx-indicator=".htmx-indicator">
|
||||
Load More
|
||||
<span class="htmx-indicator">Loading...</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
```
|
||||
|
||||
**posts/item.peb:**
|
||||
- Article element with post data
|
||||
- Featured image (lazy load)
|
||||
- Title as link to post page
|
||||
- Excerpt or auto-generated summary
|
||||
- Author name, published date, reading time
|
||||
- Category and tag links
|
||||
|
||||
**post/default.peb:**
|
||||
- Full post display
|
||||
- OpenGraph meta tags in head
|
||||
- Title, featured image, author, date
|
||||
- Content HTML
|
||||
- Categories and tags
|
||||
- Share buttons (copy link, Twitter, Facebook)
|
||||
- Include RelatedPosts component placeholder
|
||||
</action>
|
||||
<verify>
|
||||
./mill summercms.compile succeeds
|
||||
Posts component has onLoadMore HTMX handler
|
||||
Post component sets OpenGraph meta tags
|
||||
Templates have valid Pebble syntax
|
||||
</verify>
|
||||
<done>
|
||||
Posts component displays paginated listings with infinite scroll.
|
||||
Post component displays single post with meta tags.
|
||||
Templates render with HTMX interactions.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Categories and RelatedPosts components</name>
|
||||
<files>
|
||||
plugins/golem15/blog/components/Categories.scala
|
||||
plugins/golem15/blog/components/RelatedPosts.scala
|
||||
plugins/golem15/blog/resources/views/categories/default.peb
|
||||
plugins/golem15/blog/resources/views/relatedposts/default.peb
|
||||
plugins/golem15/blog/Plugin.scala (modify)
|
||||
</files>
|
||||
<action>
|
||||
Create category navigation and related posts components:
|
||||
|
||||
**Categories.scala component:**
|
||||
- ComponentDetails: name "Categories", description "Category listing/tree"
|
||||
- Property schema:
|
||||
- displayMode: Dropdown (tree/flat), default "tree"
|
||||
- showPostCount: Checkbox, default true
|
||||
- includeEmpty: Checkbox, show categories with no posts
|
||||
- Page variables: categories (tree or flat list)
|
||||
- onRun: Load category tree, filter empty if needed
|
||||
|
||||
**RelatedPosts.scala component:**
|
||||
- ComponentDetails: name "RelatedPosts", description "Related posts by category/tag"
|
||||
- Property schema:
|
||||
- limit: String, max posts to show, default "3"
|
||||
- postSlug: String, current post slug (from context)
|
||||
- Page variables: relatedPosts (List)
|
||||
- onRun: Call postService.getRelatedPosts, set context
|
||||
|
||||
**Templates:**
|
||||
|
||||
**categories/default.peb:**
|
||||
- Tree or flat list based on displayMode
|
||||
- Category name as link
|
||||
- Post count if showPostCount
|
||||
- Recursive include for tree mode
|
||||
|
||||
**relatedposts/default.peb:**
|
||||
- Grid of related post cards
|
||||
- Image, title, excerpt snippet
|
||||
- Link to full post
|
||||
|
||||
**Register all components in Plugin.scala boot method:**
|
||||
- Posts component
|
||||
- Post component
|
||||
- Categories component
|
||||
- RelatedPosts component
|
||||
</action>
|
||||
<verify>
|
||||
./mill summercms.compile succeeds
|
||||
Components registered in Plugin.scala
|
||||
Templates have valid Pebble syntax
|
||||
HTMX attributes properly formatted
|
||||
</verify>
|
||||
<done>
|
||||
Categories component shows category tree/list.
|
||||
RelatedPosts component shows related content.
|
||||
All components registered in Plugin.scala.
|
||||
Blog frontend fully functional.
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
After all tasks complete:
|
||||
1. Blog plugin compiles: `./mill summercms.compile`
|
||||
2. All four components registered in Plugin.scala
|
||||
3. Posts component loads and paginates
|
||||
4. Post component displays with OpenGraph meta
|
||||
5. Categories component renders tree structure
|
||||
6. RelatedPosts component shows related content
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Frontend /blog shows post listing with load more
|
||||
- Frontend /blog/:slug shows full post with related posts
|
||||
- Category pages filter posts by category and children
|
||||
- Tag pages filter posts by tag
|
||||
- Infinite scroll works via HTMX onLoadMore handler
|
||||
- OpenGraph meta tags present for social sharing
|
||||
- Category tree/list renders correctly
|
||||
- Related posts show content with shared categories/tags
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/10-core-plugins/10-05-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user