Paging #4
100
docs/superpowers/specs/2026-03-22-paging-design.md
Normal file
100
docs/superpowers/specs/2026-03-22-paging-design.md
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
# 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:
|
||||||
|
```go
|
||||||
|
PostsPerPage int
|
||||||
|
```
|
||||||
|
|
||||||
|
**New shared type** (`models/paging.go`):
|
||||||
|
```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`.
|
||||||
Loading…
Reference in a new issue