Pagination¶
Burrow provides offset-based pagination utilities for numbered pages. All types and functions are in the root burrow package.
Types¶
PageRequest¶
Parsed from query parameters via ParsePageRequest(r):
type PageRequest struct {
Limit int // items per page (default 20, max 100)
Page int // 1-based page number for offset-based pagination
}
Query parameters: ?limit=20&page=2.
PageResult¶
Returned alongside query results:
type PageResult struct {
HasMore bool // convenience: more pages exist
Page int // current page number (1-based)
TotalPages int // total number of pages
TotalCount int // total number of items
}
Offset-Based Pagination¶
Best for admin panels, tables, and infinite scroll where users need to jump to specific pages or load the next page.
QuerySet Pagination¶
Use Den's QuerySet API with Limit and Skip for pagination:
Building Results¶
OffsetResult computes page metadata from a total count:
Full Example¶
func (r *Repository) ListAllPaged(ctx context.Context, pr burrow.PageRequest) ([]Note, burrow.PageResult, error) {
count, err := den.NewQuery[Note](r.db).Count(ctx)
if err != nil {
return nil, burrow.PageResult{}, err
}
notes, err := den.NewQuery[Note](r.db).
Sort("created_at", den.Desc).
Limit(pr.Limit).
Skip(pr.Offset()).
All(ctx)
if err != nil {
return nil, burrow.PageResult{}, err
}
return notes, burrow.OffsetResult(pr, count), nil
}
Handler¶
func (a *App) AdminList(w http.ResponseWriter, r *http.Request) error {
pr := burrow.ParsePageRequest(r)
notes, page, err := a.repo.ListAllPaged(r.Context(), pr)
if err != nil {
return burrow.NewHTTPError(http.StatusInternalServerError, "failed to list notes")
}
// pass page to template...
}
Building Pagination URLs¶
PageURL builds a URL that preserves existing query parameters (search terms, filters, sort order) and sets the page parameter. This prevents pagination links from dropping the current query state.
// In a handler:
rawQuery := r.URL.RawQuery // e.g. "q=alpha&sort=-created_at"
url := burrow.PageURL("/notes", rawQuery, 3)
// => "/notes?page=3&q=alpha&sort=-created_at"
In templates, pass the current query string and use pageURL to generate links:
{{- $base := "/notes" }}
{{- $query := .Query }}
{{- range pageNumbers .Page.Page .Page.TotalPages }}
<a href="{{ pageURL $base $query . }}">{{ . }}</a>
{{- end }}
Built-in Pagination Component¶
contrib/admin ships a ready-made Tailwind-classed pagination nav as admin/pagination. Call it from any template by passing a struct or map with BasePath, RawQuery, and Page:
This renders a <nav> with numbered page links, previous/next buttons, and ellipsis for large page counts. The current page is marked with aria-current="page". Query parameters (search terms, filters) are preserved in pagination links.
JSON API¶
The JSON CRUD APIs layer wraps results in PageResponse for you
(offset and cursor); reach for the helpers below when hand-writing endpoints.
For JSON APIs, wrap results with PageResponse: