weiro/docs/superpowers/specs/2026-03-22-paging-design.md
Leon Mika 4d96ec8b95 Add paging feature design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-22 12:46:43 +11:00

3.1 KiB

Paging Feature Design

Overview

Introduce offset-based pagination to the admin post list and the generated static site (both post listings and category listings).

Data Layer

New sites column

Add posts_per_page INTEGER NOT NULL DEFAULT 10 to the sites table. This setting controls the number of posts per page on the generated static site only.

New SQL queries

  • CountPostsOfSite(siteID, showDeleted) — returns total post count for the site
  • CountPostsOfCategory(categoryID) — returns total published post count for a category

Model changes

models.Site — add field:

PostsPerPage int

New shared type (models/paging.go):

type PageInfo struct {
    CurrentPage  int
    TotalPages   int
    PostsPerPage int
}

Existing db.PagingParams and queries (SelectPostsOfSite, SelectPostsOfCategory) already support LIMIT/OFFSET and remain unchanged.

Admin Section

Post list pagination

  • Page size: hardcoded at 25 (not tied to the PostsPerPage site setting)
  • Handler (handlers/posts.go Index()) reads a page query parameter (default 1)
  • Computes offset as (page - 1) * 25
  • Fetches total post count via new CountPosts() service method to build PageInfo
  • Passes PageInfo to template

Service changes

  • ListPosts() accepts paging params from the handler instead of hardcoding them
  • New CountPosts() method that calls the count query

Template (views/posts/index.html)

  • Full numbered pagination with Previous/Next below the post list: < 1 2 3 ... 10 >
  • Preserves existing query params (e.g. ?filter=deleted) when paginating
  • Both regular post list and trash view are paginated

Site settings form

  • Add "Posts per page" number input to views/sitesettings/general.html
  • Add PostsPerPage field to UpdateSiteSettingsParams
  • Server-side validation: minimum 1, maximum 100

Generated Static Site

URL structure

Post listing pages:

  • /posts/ — page 1
  • /posts/page/2/ — page 2
  • /posts/page/N/ — page N

Category listing pages:

  • /categories/<slug>/ — page 1
  • /categories/<slug>/page/2/ — page 2
  • /categories/<slug>/page/N/ — page N

Site root

/ (site root) shows the same content as /posts/ (page 1 of all posts).

Builder changes (providers/sitebuilder/builder.go)

  • Instead of rendering one posts_list.html with all posts, generate multiple page files
  • Uses site.PostsPerPage from the site setting to determine page size
  • Same pattern for category pages

Publisher changes (services/publisher/iter.go)

  • Existing iterator fetches posts in batches of 50 internally — this stays as-is
  • The builder chunks posts into pages of PostsPerPage size and renders each page as a separate HTML file

Template (layouts/simplecss/templates/posts_list.html)

  • Receives PageInfo plus the posts for that page
  • Renders Previous / Next links only (no numbered pagination)
  • Previous link hidden on page 1; Next link hidden on last page

Approach

Offset-based pagination using the existing db.PagingParams infrastructure. Page number maps to offset: offset = (page - 1) * postsPerPage.